<!-- Canonical: https://startupmail.dev/docs/api-overview -->
<!-- Documentation index: https://startupmail.dev/llms.txt -->

# API overview

> Authenticate to the v1 REST API, choose scopes, and handle responses and errors.

## Base URL

All public REST routes use HTTPS beneath:

```text
https://api.startupmail.dev/v1
```

The SDK uses this base by default. During local development, pass your local origin as `baseUrl`.

## Create an API key

Open **Settings → Developers → API keys**. Give the key a workload-specific name, optional description and expiry, and only the scopes it needs. The full secret is shown once.

| Scope            | Allows                                               |
| ---------------- | ---------------------------------------------------- |
| `mailboxes:read` | List accessible mailbox metadata                     |
| `mail:read`      | List threads, read threads, and download attachments |
| `mail:send`      | Upload attachments, send, and reply                  |
| `webhooks:write` | List, create, and delete webhook endpoints           |

## Authenticate

Send the key as a Bearer token. Never expose it in browser code or commit it to source control.

```bash
curl https://api.startupmail.dev/v1/mailboxes \
  -H "Authorization: Bearer $STARTUPMAIL_API_KEY" \
  -H "Accept: application/json"
```

## Response shape

Successful JSON resources are wrapped in `data`. Sending returns `202`; creation commonly returns `201`; a successful delete returns `204` with no body.

Errors use a stable code and a readable message:

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "This API key requires the mail:read scope."
  }
}
```

The response `x-request-id` is useful when contacting support. Clients should handle `401`, `403`, `404`, `413`, and `429` explicitly and retry only when the operation is safe to repeat.

> **Prefer one key per workload**
>
> Separate keys make rotation, expiry, last-used review, and incident containment much simpler than
> sharing one broad secret.
