> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://documents.pyramid-ai.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://documents.pyramid-ai.com/_mcp/server.

# Error Handling

All API errors follow a consistent envelope with machine-readable error codes.

## Error response format

```json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "project_id is required",
    "field": "project_id"
  },
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}
```

Always log the `request_id` (also in the `X-Request-Id` header) — it's required for support lookups.

## Error codes

| HTTP Status | Code                     | Description                                                                                             |
| ----------- | ------------------------ | ------------------------------------------------------------------------------------------------------- |
| 400         | `VALIDATION_ERROR`       | Invalid request body or parameters. Check the `field` property for the specific field.                  |
| 401         | `UNAUTHORIZED`           | Missing or invalid API key.                                                                             |
| 402         | `QUOTA_EXCEEDED`         | Monthly token or request quota reached.                                                                 |
| 403         | `FORBIDDEN`              | Valid key, but not authorized for this resource.                                                        |
| 403         | `FEATURE_NOT_ENABLED`    | This API feature is not enabled for your organization.                                                  |
| 403         | `AGENT_NOT_ENABLED`      | The requested chat agent is not enabled for your organization. Contact your administrator to enable it. |
| 404         | `NOT_FOUND`              | Resource does not exist or you don't have access.                                                       |
| 409         | `CONFLICT`               | Duplicate resource or conflicting state.                                                                |
| 409         | `IDEMPOTENCY_KEY_REUSED` | Idempotency key was used with a different request body.                                                 |
| 429         | `RATE_LIMITED`           | Too many requests. See [Rate Limits](/rate-limits).                                                     |
| 500         | `INTERNAL_ERROR`         | Server error. Retry with backoff.                                                                       |

## Idempotency

All `POST` endpoints accept an `Idempotency-Key` header for safe retries:

```bash
curl -X POST https://api.pyramid-ai.com/api/v2/projects \
  -H "Authorization: Bearer pai_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-unique-key-12345" \
  -d '{"name": "My Project"}'
```

**How it works:**

1. First request with a given key executes normally and caches the response
2. Subsequent requests with the **same key and same body** return the cached response (no duplicate side effects)
3. Same key with a **different body** returns `409 IDEMPOTENCY_KEY_REUSED`
4. Keys expire after 24 hours

> **Note**
>
> Idempotency keys are scoped per organization and per endpoint. The same key string can be used on different endpoints without collision.

## Retry strategy

| Error Code         | Retry? | Strategy                                             |
| ------------------ | ------ | ---------------------------------------------------- |
| `VALIDATION_ERROR` | No     | Fix the request                                      |
| `UNAUTHORIZED`     | No     | Check your API key                                   |
| `RATE_LIMITED`     | Yes    | Wait for `Retry-After` header value                  |
| `QUOTA_EXCEEDED`   | No     | Contact your account manager                         |
| `INTERNAL_ERROR`   | Yes    | Exponential backoff (1s, 2s, 4s), max 3 retries      |
| `CONFLICT`         | No     | Resource already exists or is in a conflicting state |

## Request IDs

Every response includes a unique `request_id` in both the response body and the `X-Request-Id` header. When contacting support, always include this ID for fast diagnosis.