> ## Documentation Index
> Fetch the complete documentation index at: https://docs.capy.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# API quickstart

> From an API key to a running agent thread in five curl commands.

This page takes you from nothing to a thread you can watch working at capy.ai. Everything is copy-paste curl; the only prerequisites are a Capy account with a project set up and a terminal.

## 1. Mint an API key

In the app, go to **Settings → API** and create a key. The plaintext is shown exactly once (there's no re-display, only revoke-and-remint), so export it now:

```bash theme={null}
export CAPY_API_KEY="capy_..."
```

## 2. Find your project id

Threads live in [projects](/projects), and the public API has no projects endpoint yet, so the id comes from the app: open any of your project's pages and copy the whole route parameter after `/project/` in the URL. Newly created projects use `project_...` ids; imported ones keep their original id.

```bash theme={null}
export PROJECT_ID="..."
```

Verify the key and the project together by listing threads; an empty page is a working setup:

```bash theme={null}
curl -H "Authorization: Bearer $CAPY_API_KEY" \
  "https://api.capy.ai/api/v1/threads?projectId=$PROJECT_ID"
```

A `capy/Unauthorized` means the key is wrong or revoked; a `capy/ProjectNotFound` means the id is wrong or the project isn't reachable from this key's organization.

## 3. Create a thread

`requestId` is an idempotency token you mint: retries with the same id return the same thread instead of starting a second billable run.

```bash theme={null}
curl -X POST "https://api.capy.ai/api/v1/threads" \
  -H "Authorization: Bearer $CAPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "requestId": "'"$(uuidgen)"'",
    "projectId": "'"$PROJECT_ID"'",
    "message": "Fix the flaky retry test in packages/queue and open a PR."
  }'
```

The response is the `Thread` projection, the same shape every thread read returns:

```json theme={null}
{
  "id": "jam_01...",
  "projectId": "proj_...",
  "title": null,
  "status": "active",
  "archived": false,
  "usage": { "llmCredits": 0, "vmCredits": 0, "totalCredits": 0 },
  ...
}
```

Save the id:

```bash theme={null}
export THREAD_ID="jam_01..."
```

## 4. Poll the status

```bash theme={null}
curl -H "Authorization: Bearer $CAPY_API_KEY" \
  "https://api.capy.ai/api/v1/threads/$THREAD_ID"
```

`status` is what you poll on:

| Status             | Meaning                                                |
| ------------------ | ------------------------------------------------------ |
| `active`           | The agent is working                                   |
| `waiting`          | Waiting on something external: CI, a timer, a callback |
| `pending_user`     | Blocked on your input; read the messages and reply     |
| `ready_for_review` | Work delivered, awaiting your review                   |
| `idle`             | At rest                                                |
| `error`            | The run failed                                         |
| `archived`         | Archived                                               |

Poll every few seconds until the status leaves `active` and `waiting`. Threads run for minutes, not seconds; a real coding task takes as long as the work does.

## 5. Read the messages

```bash theme={null}
curl -H "Authorization: Bearer $CAPY_API_KEY" \
  "https://api.capy.ai/api/v1/threads/$THREAD_ID/messages"
```

The transcript is `{ items, cursor }` of `Message` entries: your messages (`source: "user"`), the agent's replies (`source: "assistant"`), and one-line tool activity (`source: "tool"` with the tool name, never raw arguments or results). When the agent opens a pull request, the PR link arrives in its assistant reply text.

Page forward by passing the response's `cursor` back as `after`; poll the same way to tail a live thread.

## 6. Reply

```bash theme={null}
curl -X POST "https://api.capy.ai/api/v1/threads/$THREAD_ID/message" \
  -H "Authorization: Bearer $CAPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Also update the changelog."}'
```

The response is an admit receipt, `{ "id": "...", "deduped": false }`: the message landed and the agent wakes. By default a message interrupts what the agent is doing; pass `"delivery": "queue"` to wait for the current work to finish first.

## You're done

Open [capy.ai](https://capy.ai): the thread you just created is on the Threads page, transcript and all, exactly as the API reported it. Everything the app shows rides the same platform you just drove with curl.

Next: [common flows](/api-reference/common-flows) for the task tree, reviews, and automation webhooks.
