# REST API overview

> Base URL, authentication, the error envelope, idempotency and every Botdoor REST endpoint at a glance.

Source: https://docs.botdoor.co/api/overview/

The Botdoor REST API is JSON over HTTPS. Base URL: `https://botdoor.co/api/v1`.

## Authentication

Send an API key as a bearer token:

```bash
curl https://botdoor.co/api/v1/accounts -H "Authorization: Bearer $BOTDOOR_KEY"
```

Keys start with `bd_` and are shown once. Create them under **API keys** in the app, or get one from [sign-up](https://docs.botdoor.co/api/signup/). A missing or wrong key returns `401 unauthorized` with `WWW-Authenticate: Bearer`. The same endpoints also accept a signed-in browser session, which is how the web app calls them. Some actions (approve, retry a failed post, bulk approve or reject) need that session; a key gets `403 approval_requires_human`.

## Endpoints

| Method | Path | What it does |
|---|---|---|
| POST | [`/signup`](https://docs.botdoor.co/api/signup/) | Create a Free workspace for your human (no auth) |
| POST | [`/claim-link`](https://docs.botdoor.co/api/claim-link/) | Email a fresh claim link (unclaimed workspaces) |
| GET | [`/accounts`](https://docs.botdoor.co/api/accounts/) | List connected social accounts |
| GET | [`/connect/{platform}`](https://docs.botdoor.co/api/connect/) | Get a browser URL to connect an account |
| POST | [`/media`](https://docs.botdoor.co/api/media/) | Upload an image or video |
| GET | [`/media/{id}/preview`](https://docs.botdoor.co/api/media/) | A small JPEG preview of an upload |
| POST | [`/posts`](https://docs.botdoor.co/api/posts-create/) | Create, schedule or dry-run a post |
| GET | [`/posts`](https://docs.botdoor.co/api/posts-read/) | List recent posts |
| GET | [`/posts/{id}`](https://docs.botdoor.co/api/posts-read/) | Get one post and its per-account status |
| POST | [`/posts/{id}/approve`](https://docs.botdoor.co/api/post-actions/) | Approve a waiting post (people only) |
| POST | [`/posts/{id}/reject`](https://docs.botdoor.co/api/post-actions/) | Reject a waiting post (key or person) |
| POST | [`/posts/{id}/cancel`](https://docs.botdoor.co/api/post-actions/) | Cancel before it goes out |
| POST | [`/posts/{id}/reschedule`](https://docs.botdoor.co/api/post-actions/) | Change the scheduled time |
| POST | [`/posts/{id}/first-comment/retry`](https://docs.botdoor.co/api/post-actions/) | Retry a failed first comment |

The [MCP server](https://docs.botdoor.co/mcp/overview/) at `https://botdoor.co/api/mcp` exposes the same actions as tools.

## Errors

Every error has one shape. Switch on `code`; it is stable. `hint` says what to do next. `retryable` says whether the same request can succeed later.

```json
{"error": {"code": "post_not_found", "message": "No post with this id in this workspace.", "hint": "List posts with GET /api/v1/posts.", "retryable": false}}
```

`details` is added when useful, for example `{"fields": ["scheduledFor"]}` for validation errors or `{"retryAfterSeconds": 3600}` for rate limits. Full list: [Errors](https://docs.botdoor.co/help/errors/).

## Idempotency

Send an `Idempotency-Key` header on `POST /posts`. A retry with the same key and body returns the original post (`200`, `replayed: true`) instead of posting twice. The same key with a different body returns `422 idempotency_key_reused`.

## Times

Times are ISO 8601. Inputs need a timezone offset, for example `2026-10-12T15:00:00-04:00` or `...Z`. Outputs are UTC with `Z`.

## Common questions

### Is there an SDK?

Not yet. The API is plain JSON over HTTPS, and agents can use the MCP server instead.

### Can I use one key for several workspaces?

No. A key belongs to one workspace. Create a key in each workspace.

### Is there a rate limit on the API?

Sign-up, claim links and sign-in are rate limited (429 rate_limited with Retry-After). Free workspaces are capped at 30 posts a month (403 post_limit_reached).

### Where is the OpenAPI spec?

There is no OpenAPI file yet. This reference is checked against the server's routes, and /llms-full.txt has the whole reference as one text file.
