Run it

The API

The board’s JSON API: how to sign in, the routes for tasks, agents, GitHub, repositories, and routines, which ones only the signed-in browser may call, and how to fire a routine from a webhook.

The CLI and the web board are both clients of one JSON API on the board’s address. You can call it from scripts too. The CLI (npx breakaway) is the supported client; it tracks the API’s changes, so prefer it when a command exists.

#Authentication

Every /api/* route except /api/ping and a routine’s /fire needs the board’s token:

export BREAKAWAY_URL=https://board.example.com
curl -H "Authorization: Bearer $BREAKAWAY_TOKEN" "$BREAKAWAY_URL/api/health"

#Health

RouteAnswers
GET /api/pingPublic. { ok, version, release }: the Cloudflare version ID and the semver release. Nothing about tasks.
GET /api/sessionWhich board this is: its name and address.
GET /api/healthThe server’s state, with task counts, the CLI version, and the release.
GET /api/connectionsThe Connections report.
GET /api/activity?limit=&before=Recent changes, newest first.
GET /api/stats?days=&tz=&repo=The Activity view’s numbers.

#Tasks

RouteDoes
GET /api/tasks?status=pendingLists tasks. status is pending, completed, deleted, or all.
POST /api/tasksCreates a task, or several: send one object, an array, or { tasks: […] }. Later items may depend on earlier ones by work ID. Answers 201 with { tasks }.
GET /api/tasks/<ref>One task in full: fields, comments, dependencies, and what it blocks. <ref> is a work ID, a UUID, or its first 8 characters.
PATCH /api/tasks/<ref>Changes fields.
POST /api/tasks/<ref>/claim{ agent, force?, repo? }. Atomic: 409 if someone else has it, or it’s blocked, or it belongs to another repository.
POST /api/tasks/<ref>/release{ agent, force? }.
POST /api/tasks/<ref>/done{ note?, by? }.
POST /api/tasks/<ref>/comments{ text, by? }. Append-only.
POST /api/tasks/<ref>/pingsAn agent pings you: { kind, message, proposal? }.
POST /api/tasks/<ref>/decision/answersYou answer a decision. DELETE reopens it.
POST /api/nextThe best ready task; with claim: true, claims it in one step.

A task you create or change takes these fields: description (the title), brief, done_when, project (the area), priority, horizon, spec, pr, due, wait, scheduled, status, autostart, decision, and repo (on create). A create also takes tags, depends, related, and note; a change takes addTags, removeTags, addDepends, removeDepends, addRelated, removeRelated, and annotate.

curl -X POST -H "Authorization: Bearer $BREAKAWAY_TOKEN" -H "Content-Type: application/json" \
  "$BREAKAWAY_URL/api/tasks" -d '{
    "description": "Sort the inbox by age",
    "project": "web",
    "horizon": "now",
    "tags": ["agent"],
    "brief": "The oldest ping should be first, so nothing waits unseen.",
    "done_when": "The inbox shows the oldest open ping first."
  }'

Images are POST /api/tasks/<ref>/attachments (the raw image as the body, with X-Attachment-Name and an optional X-Attachment-Alt), GET to list, and GET /api/attachments/<id> for the bytes: PNG, JPEG, WebP, and GIF, up to 1 MB each and 4 per task.

#Agents, pings, and routines

RouteDoes
GET /api/agentsRunning and waiting agents, limits, and settings.
POST /api/agents/start{ ref, note?, mode? }. Starts an agent (mode: "refine" to refine).
POST /api/agents/next{ count, horizon?, repo?, dryRun? }. Start the next few.
PATCH /api/agents/settingsThe limits, plan, auto-start, and alert severity.
GET /api/agents/prompt?repo=A repository’s agent prompt as it is on its default branch.
GET /api/pingsYour inbox: open pings and notices.
POST /api/pings/<id>/apply, /dismiss, /handledOwner only (the cookie).
GET /api/tasks/<ref>/session, POST …/sessionA session’s live output; the hooks send it.
POST /api/tasks/<ref>/messagesOwner only: message a running agent. GET …/messages lists them.
GET /api/routines, POST /api/routinesList or create routines.
PATCH /api/routines/<slug>Change one.
POST /api/routines/<slug>/runRun it now.
POST /api/routines/<slug>/triggers, DELETE …/triggers/<id>Make or revoke a webhook trigger.
POST /api/horizons/closeClose now; { dryRun: true } only counts.

#Firing a routine from outside

A routine’s webhook trigger has its own secret and no board token:

curl -X POST "$BREAKAWAY_URL/api/routines/changelog/fire" \
  -H "Authorization: Bearer swr_…" -H "Content-Type: application/json" \
  -d '{ "note": "Release v0.3 is out.", "data": { "tag": "v0.3.0" } }'

The secret may also come in an X-Routine-Secret header. The body is at most 16 KB with an optional note (up to 1,000 characters) and data (up to 10 short keys). Nothing else is read, and what you send is stored as an untrusted comment, never as instructions. A wrong, revoked, or other routine’s secret gets 401, the same answer whether or not the routine exists. 429 means a cap or the gap stopped it, 409 that the routine is off, 413 that the body was too big. See Routines.

#GitHub

RouteDoes
GET /api/github?repo=Pull requests, checks, runs, deploys, alerts for a repository.
GET /api/github/pulls/<n>?repo=One pull request page, read live.
POST /api/github/syncSync now.
POST /api/github/pulls/<n>/fix, …/reviewStart an agent on a pull request, or review a Dependabot one.
POST /api/github/alerts/<n>/fixStart an agent on a Dependabot alert.
POST /api/github/pulls/<n>/publish, update-branch, merge, auto-mergeOwner only. The signed-in browser.
POST /api/github/promote, /rollbackOwner only. Start the repository’s Promote or Roll back workflow.

Without repo, the default repository is read.

#Repositories

RouteDoes
GET /api/reposThe registry: repositories, areas, the default, and firstRun.
POST /api/reposRegister one (dryRun: true only checks). Owner.
PATCH /api/repos/<slug>, DELETE /api/repos/<slug>Change or take one off the board. Owner.
POST /api/repos/<slug>/releaseGive a removed repository’s slug and prefixes back. Owner.
GET /api/repos/setup?slug=The Add a repository wizard’s state.

#The sync protocol

/v1/client/* is the TaskChampion sync protocol for Taskwarrior replicas. It isn’t part of the JSON API: it accepts only the install’s client ID, and its bodies are encrypted. Use Taskwarrior.