# For AI agents

Canonical URL: https://sendbunny.co/docs/agents

Use this page as a skill. The source of truth is [/openapi.json](https://sendbunny.co/openapi.json). Full prose is in [/llms-full.txt](https://sendbunny.co/llms-full.txt). Do not invent endpoints or scopes.

## Facts

- Self-hosted. Base URL is `https://<cloudfront>/v1`.
- Auth: `x-api-key: sb...` (or `Authorization: Bearer sb...`)
- Errors: `{ "error": string }`. 401 is always `Invalid API key`.
- `to` is always a JSON array. A string is a 400.
- Do not call `POST /api` or `/agent/*`.
- Do not mint keys. Do not invite users. Do not call Updates.
- If you get `Key lacks <scope> scope`, stop and ask the human to add that scope.

## Minimal send

**POST /v1/emails:**

```http
POST /v1/emails
x-api-key: sb...
Content-Type: application/json

{"from":"hello@domain.com","to":["user@example.com"],"subject":"Hi","text":"Hi"}
```

200: `{ "messageId": "...", "id": "..." }`. Confirm with `GET /v1/emails/{id}`.

## Choosing routes

| Goal | Scope | Route |
| --- | --- | --- |
| Send transactional mail | `email:send` | `POST /v1/emails` |
| Read inbox | `inbox:read` | `GET /v1/conversations?root=` |
| Reply in-thread | `inbox:reply` | `POST /v1/messages/{id}/reply` |
| Start a campaign | `campaigns:write` | `POST /v1/campaigns/{id}/start` |
| Add a contact | `audience:write` | `POST /v1/contacts` |
| Create a template | `templates:write` | `POST /v1/templates` |

## Inbox rules

- A key limited to specific addresses gets **404** (not 403) for other message ids.
- Reply recipients are server-derived. Do not send `to` on the reply route.
- Pass `cursor` for lists. Do not assume one page is complete. `limit` max is 50.