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

# Errors & rate limits

> Status codes, error bodies, and how to retry safely.

Comms returns JSON errors and standard HTTP statuses. Unknown failures stay opaque so engine internals never leak to API clients.

## Error shape

```json theme={null}
{ "error": "unauthorized" }
```

Some rate-limit responses include:

```json theme={null}
{ "error": "rate_limited", "retry_after": 60 }
```

## Status codes

| Status  | Meaning                                   | What to do                                         |
| ------- | ----------------------------------------- | -------------------------------------------------- |
| **200** | OK — including idempotent duplicate sends | Treat as success                                   |
| **201** | Created (e.g. webhook)                    | Persist returned id                                |
| **202** | Accepted for delivery                     | Persist `message.id`                               |
| **400** | Bad request / validation                  | Fix the payload                                    |
| **401** | Missing or invalid key                    | Check `Authorization` header                       |
| **403** | Valid key, missing scope                  | Mint a key with the right scope                    |
| **429** | Rate limited                              | Back off `retry_after` seconds (or 60s default)    |
| **5xx** | Server error                              | Retry with backoff + same idempotency key on sends |

## Rate limits

Defaults (configurable per environment):

| Bucket           | Default                  | Applies to                     |
| ---------------- | ------------------------ | ------------------------------ |
| Global Comms API | \~100 req / min / caller | All authenticated Comms routes |
| Send             | \~60 req / min / caller  | `POST /messages` only          |

Caller identity is derived from the API key (or staff session). Limits are per org + caller.

### Handling 429

1. Read `retry_after` when present.
2. Sleep / re-queue for at least that many seconds.
3. Retry **sends** with the **same** `Idempotency-Key`.

## Scope errors

```json theme={null}
{ "error": "missing comms_send scope" }
```

Create a new key (or rotate) with the required scopes from [Messages API keys](https://comms.osis.co/dashboard/settings/api-keys).

## Retry policy (recommended)

| Operation        | Retry?                         | Notes                                |
| ---------------- | ------------------------------ | ------------------------------------ |
| `POST /messages` | Yes, with same idempotency key | Safe                                 |
| `GET *`          | Yes                            | Read-only                            |
| `POST /webhooks` | Careful                        | May create duplicates if not checked |
| `POST /contacts` | Careful                        | Upsert semantics — usually safe      |

## Related

* [Authentication](/messages-api/authentication)
* [Idempotency](/guides/idempotency)
