# OpenAI-compatible API errors

> The OpenAI error envelope of /v1/responses and /v1/chat/completions, and the full table of status, type, code and the OpenAI SDK exception each raises.

The messaging routes, webhooks, `/v1/events`, `/v1/media` and
`/v1/recordings` answer the messaging envelope:
[Errors](/platform-api/errors/). The OpenAI-compatible endpoints
(`/v1/responses`, `/v1/chat/completions`, `/v1/models`) answer errors in the
standard OpenAI error envelope, so the OpenAI SDK raises the matching typed
exception automatically:

```json
{ "error": { "message": "...", "type": "invalid_request_error", "param": null, "code": "invalid_api_key" } }
```

### Self-correcting fields

Some errors add optional fields **alongside** the standard ones so an agent can
recover without a human. They're additive — the OpenAI SDK ignores unknown keys,
so the envelope stays wire-compatible:

| Field | Meaning |
|---|---|
| `hint` | What to do next (e.g. how to send a valid key, how to back off) |
| `docs_url` | The docs page that explains the fix |
| `did_you_mean` | The likely-intended value for a bad enum/param |

```json
{ "error": { "message": "No API key: send `Authorization: Bearer <your key>`.",
  "type": "invalid_request_error", "param": "authorization", "code": "invalid_api_key",
  "hint": "Send a valid key as `Authorization: Bearer sk-octo_...`.",
  "docs_url": "https://docs.omniocto.com/getting-started/authentication" } }
```

## Error table

| HTTP | `type` / `code` | When | SDK exception |
|---|---|---|---|
| `401` | `invalid_request_error` / `invalid_api_key` | Missing or invalid API key (`param` is `authorization`; the `message` says whether the key was missing, sent without `Bearer `, or not valid) | `AuthenticationError` |
| `403` | `insufficient_quota` | Workspace suspended or out of credits | `PermissionDeniedError` |
| `404` | `invalid_request_error` | Unknown `previous_response_id` / `conversation` / response id / model | `NotFoundError` |
| `400` | `invalid_request_error` | Malformed request body; `store:false` combined with `background:true` | `BadRequestError` |
| `422` | `invalid_request_error` | `Idempotency-Key` reused with a different request body | `UnprocessableEntityError` |
| `429` | `rate_limit_error` | Per-key or per-workspace rate limit exceeded (carries a `retry-after` header) | `RateLimitError` |

## Handling errors with the OpenAI SDK

```python
from openai import (
    AuthenticationError,
    PermissionDeniedError,
    NotFoundError,
    BadRequestError,
    UnprocessableEntityError,
    RateLimitError,
)

try:
    resp = client.responses.create(model="claude-sonnet-4-6", input="hi")
except AuthenticationError:
    ...  # bad/missing key — see Authentication
except PermissionDeniedError:
    ...  # workspace suspended or out of quota — see Usage & billing
except RateLimitError as e:
    ...  # back off using the retry-after header — see Rate limits
```

## Related

- [Authentication](/getting-started/authentication/) for `401`s.
- [Usage & billing](/openai-api/usage/) for `403 insufficient_quota`.
- [Rate limits](/openai-api/rate-limits/) for `429`s.
- [Statefulness](/openai-api/statefulness/) for `404`s on unknown ids and `422`s on idempotency conflicts.