The API

ogma has a JSON API under /api/v1 for automating projects and boards.

Building an integration with an LLM or agent? Two options:

  • MCP (the easy way): the workspace portal serves this whole API as ready-made tools (projects_board, projects_card_create, …) at its /mcp endpoint — one line to connect Claude Code or any MCP client, authenticated with the same API tokens. See the portal's /llms.txt.
  • Raw HTTP: point the model at /llms.txt — a single plain-Markdown page with this whole reference in a machine-friendly form.

Authenticating

Create a token on the account service (see Your account), then send it as a bearer token:

TOKEN=gbn_...
curl -H "Authorization: Bearer $TOKEN" https://your-ogma/api/v1/me

A token acts as you and carries your permissions. Requests that change data must send Content-Type: application/json.

What you can do

  • YouGET /me
  • ProjectsGET|POST /projects, GET|PATCH|DELETE /projects/{id}
  • BoardGET /projects/{id}/columns (columns with their cards in one call), POST /projects/{id}/columns, PATCH|DELETE /columns/{id}
  • CardsPOST /columns/{id}/cards, GET|PATCH|DELETE /cards/{id}, POST /cards/{id}/move, POST /cards/{id}/archive|unarchive (file a card away without destroying it — prefer this to DELETE). PATCH accepts title, body, assignee_id, due_at, priority_id, owner_type (human or agent), shepherds, and work_phase (empty string clears the optional ones — except shepherds, which is a list and clears with []). Every card payload carries number — the per-board handle the UI shows as #12 (server-assigned, never reused); routes always take the id.
  • CommentsGET|POST /cards/{id}/comments, DELETE /comments/{id}
  • ChecklistGET|POST /cards/{id}/checklist (POST: {"text": …}), PATCH|DELETE /checklist/{id} (PATCH: {"text": …, "done": …, "position": …}, every field optional; position = new 0-based index in the card's checklist order). Cards report the tally as checklist_done/checklist_total.
  • LabelsGET|POST /projects/{id}/labels, PATCH|DELETE /labels/{id} (PATCH renames/recolors: {"name": …, "color": …}, either field optional), GET|POST /cards/{id}/labels, DELETE /cards/{id}/labels/{label_id}
  • PrioritiesGET|POST /projects/{id}/priorities (the ordered ladder, most urgent first; POST appends at the bottom), PATCH|DELETE /priorities/{id} (PATCH: {"name": …, "color": …, "position": …}, every field optional; position = new 0-based rung, 0 = most urgent, and responses report the same rung unit; DELETE drops cards carrying it back to no priority)
  • AttachmentsGET|POST /cards/{id}/attachments, GET|POST /comments/{id}/attachments, GET|DELETE /attachments/{id}
  • MembersGET|POST /projects/{id}/members, DELETE /projects/{id}/members/{user_id}
  • For agents — claim and release a card with POST|DELETE /cards/{id}/claim, or take the next unclaimed agent card with POST /projects/{id}/claim-next; publish a plan, split a card, or hand it on with POST /cards/{id}/plan, /decompose, /handoff; entry gates via GET /cards/{id}/gate, POST /cards/{id}/gate/acks, DELETE /cards/{id}/gate/acks/{criterion_id} and GET|POST /projects/{id}/gate-criteria, PATCH|DELETE /gate-criteria/{id}; the stale-work report at GET /projects/{id}/rot; live attention with POST /cards/{id}/attention, DELETE /attention, GET /projects/{id}/attention; and findings at GET|POST /cards/{id}/findings. Bodies, responses and the rules behind them are spelled out in /llms.txt.

Your token's project roles apply exactly as they do in the app.

A couple of limits worth knowing: cards and comments created through the API don't run @mention parsing, so they generate no mentions, notifications, or activity-history entries (those come from the web app).

Examples

# Create a project
curl -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"name":"Website redesign","repo_url":"https://github.com/acme/site"}' \
  https://your-ogma/api/v1/projects

# Add a card, then move it
curl -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"title":"Ship it"}' https://your-ogma/api/v1/columns/$COL/cards
curl -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d "{\"to_column_id\":\"$COL2\",\"position\":0}" \
  https://your-ogma/api/v1/cards/$CARD/move

# Attach a file, then download it
AID=$(curl -H "Authorization: Bearer $TOKEN" -F "file=@diagram.png" \
  https://your-ogma/api/v1/cards/$CARD/attachments | jq -r .id)
curl -H "Authorization: Bearer $TOKEN" -OJ https://your-ogma/api/v1/attachments/$AID

Upload an attachment as multipart/form-data with a single file field (up to 10 MB). Downloads always come back as an attachment (never inline).

Errors

Errors have a consistent shape:

{ "error": { "code": "validation_failed", "message": "" } }

Codes include unauthenticated, forbidden, not_found, conflict, validation_failed, rate_limited, and internal.