Skip to main content
Six flows you’ll actually build, each complete enough to paste into a script. All of them assume:

Drive a thread end to end

Create with a caller-minted requestId so a timed-out create can be retried without starting a second run:
Poll until the thread leaves its working states:
pending_user means the agent asked you something; ready_for_review means it delivered. Either way, the answer is in the transcript:
Assistant entries carry the agent’s replies, including the PR link when it opened one. Tool entries are one-line activity summaries, never raw arguments or results. Page with after set to the response’s cursor until it’s null. Reply, and the loop starts again:
A message interrupts the agent’s current work by default. Pass "delivery": "queue" to let the current work finish first, and the receipt’s id is what you’d pass to POST $API/threads/$THREAD_ID/messages/{id}/cancel if you change your mind while it’s still waiting.

Inspect a thread’s task tree

Agents fan work out to task subagents, which either share the parent’s machine or run on a fresh one. The task endpoints are read-only observation: a task is driven through its thread, so if you want a task to change course, message the thread. List the tree; pages walk depth-first, so parents always precede children and every page prefix is a coherent subtree:
taskPath is the dotted address from the thread root: 1.2 is the second task under the first task. status is the run state: working, waiting, idle, done, or failed. Each task’s usage is its own subtree’s spend, so you can see where the credits went. Read one task and its transcript with the same Message shape threads use:

Start a review on a pull request

POST /reviews starts a Capy review round on any PR in a repository your organization’s GitHub installation covers:
A review round is keyed to the PR’s exact head and base commits, so retriggering the same code answers the existing round with adopted: true and runs nothing new. Push a commit and the next call opens a fresh round. Omit idempotencyKey and this scope keying is the whole dedup; pass forceRefresh: true for a confirmed manual re-run of an already-completed round. If one of your threads should hear the verdict, pass its id as sourceThreadId: the round’s outcome lands in that thread as an ordinary input and wakes it, instead of you polling. The response’s sourceRecorded tells you whether that notification was actually recorded (false when the adopted round already reports elsewhere or already finished; read the findings in the app instead of waiting). A closed or draft PR, or a PR GitHub won’t let Capy read, answers capy/ReviewRefused (422) with the reason.

Create, inspect, and pause automations

Create an enabled schedule automation and retain its id. Keep the same request id when retrying an ambiguous response:
If you create an incoming_webhook trigger, save the response’s webhookUrl at this point. The capability URL is returned only by the first successful request; an idempotent replay returns the existing automation with webhookUrl: null, and later reads and mutations omit the field. A human key can create automations. A service-user key needs read_write or admin, and its project allowlist applies to the requested projectId; read_only receives 403. List the automations visible to the API-key principal. Pass projectId when the integration should inspect one project only:
The response is cursor-paginated. Pass a non-null cursor back unchanged to read the next page. Pause the automation that’s causing unwanted runs:
The response’s enabled field is false after the schedules and provider routes have been removed. Resume it with the inverse transition:
Enabling revalidates the stored run-as principal before rebuilding schedules and provider routes. Human API keys and service-user keys with read_write or admin can change state; a read_only service key can inspect automations but receives 403 for either mutation. Delete and restore use the same authorization and return the resulting deleted state:

Create a thread for a teammate and put it on their board

A service-user key can attribute work to a member so it shows up as theirs in the app. First resolve the member: GET /users lists your organization’s active members, and every id it returns is a valid attribution target:
Create the thread with authorId, then pin it to that member’s board with the same id:
Both calls validate the id against your organization’s active members and answer 400 capy/InvalidRequest for anyone else. The thread now lists under the member’s threads, they’re seeded as a participant, and the attribution reads back as Thread.authorId; the kickoff message stays attributed to your key’s principal. A human key can omit userId to pin as itself; a service key must pass it, because a service principal has no board of its own. Pinned is per-member and private, so your service key can write to it but not read it back: confirm through the mutation’s outcomes (ok per thread). Shared folders are readable and writable by any key. List what your key can see, file the thread, and page the folder’s threads in board order:
Filing answers one outcome per thread: ok (re-filing an already-filed thread is also ok), not_found (absent, another organization’s, or outside a service key’s project access, deliberately indistinguishable), or not_allowed (a personal thread refused by a shared folder). A read_only service key can list and page folders but receives 403 for every mutation. Folders are created and managed in the app; the API files into them.

Trigger an automation webhook

An automation with an incoming-webhook trigger exposes a capability URL. Note this one is not under /api/v1 and takes no bearer header, because the URL itself is the credential:
Idempotency-Key is your retry safety: deliveries with the same key start one run, so your alerting system can fire the hook at-least-once without fanning out runs. A 202 body of accepted means a run was admitted, duplicate means your key already ran, and no-match means the automation’s trigger filters rejected this body: a valid delivery that starts no run, so don’t retry it. 404 means the URL is wrong or the automation is disabled, deliberately indistinguishable. The body reaches the agent as quoted, untrusted event context under the automation’s stored prompt: send data for the agent to act on, not instructions.