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

# Errors & rate limits

> Error response shape, machine-readable codes, and per-key rate limits for the Proceeds REST API.

## Error shape

Failed requests return a structured body with a human-readable `error`, a machine-readable `code`, optional `details`, and the standard `meta` object:

```json theme={null}
{
  "error": "Valid API key required",
  "code": "INVALID_API_KEY",
  "details": null,
  "meta": {
    "requestId": "req_...",
    "timestamp": "2026-01-01T00:00:00.000Z"
  }
}
```

Quote `meta.requestId` when contacting support — it correlates with the server log line for your request.

## HTTP status codes

| Status | Meaning                                                          |
| ------ | ---------------------------------------------------------------- |
| `400`  | Request validation failed (`VALIDATION_ERROR`)                   |
| `401`  | API key missing, invalid, revoked, or expired                    |
| `403`  | Insufficient scope, IP not allowed, or not the resource owner    |
| `404`  | Resource not found                                               |
| `409`  | Conflict — e.g. a paywall slug already exists within the service |
| `429`  | Rate limit exceeded                                              |
| `503`  | A dependency check failed (health endpoint only)                 |

## Error codes

The `code` field is stable and safe to branch on:

| Code                  | Typical status |
| --------------------- | -------------- |
| `INVALID_API_KEY`     | `401`          |
| `KEY_REVOKED`         | `401`          |
| `KEY_EXPIRED`         | `401`          |
| `KEY_INACTIVE`        | `401`          |
| `INSUFFICIENT_SCOPE`  | `403`          |
| `IP_NOT_ALLOWED`      | `403`          |
| `FORBIDDEN`           | `403`          |
| `NOT_FOUND`           | `404`          |
| `VALIDATION_ERROR`    | `400`          |
| `CONFLICT`            | `409`          |
| `RATE_LIMITED`        | `429`          |
| `KEY_LIMIT_REACHED`   | `403`          |
| `SSRF_BLOCKED`        | `400`          |
| `ALREADY_REVOKED`     | `409`          |
| `INVALID_WALLET`      | `400`          |
| `INVALID_SERVICE`     | `400`          |
| `BETA_LIMIT_PAYWALLS` | `403`          |
| `BETA_LIMIT_SERVICES` | `403`          |
| `INTERNAL_ERROR`      | `500`          |
| `DATABASE_ERROR`      | `500`          |

## Rate limits

Each API key may make up to **1000 requests per 60-second window**. When you exceed it, the API responds with `429 Too Many Requests` and a `Retry-After` header indicating how many seconds to wait:

```http theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 23
```

```json theme={null}
{
  "error": "Rate limit exceeded",
  "code": "RATE_LIMITED",
  "meta": { "requestId": "req_...", "timestamp": "2026-01-01T00:00:00.000Z" }
}
```

Back off for the number of seconds in `Retry-After` before retrying. Spread bursty workloads across the window to stay under the limit.

<Card title="Authentication" icon="key" href="/api-reference/authentication">
  Key format, header options, and scopes that drive `401` and `403` responses.
</Card>
