Error codes
10ex returns standard HTTP status codes. The body is always JSON.
Envelope
FastAPI/Pydantic validation errors:
{ "detail": [ { "loc": ["body", "field"], "msg": "...", "type": "..." } ] }Application errors:
{ "detail": "human-readable error", "code": "machine_readable_code" }Use code for branching in client code; use detail for the message you show a human.
Status codes
| Code | Meaning |
|---|---|
| 200 / 201 / 204 | Success |
| 400 | Bad request (malformed JSON, missing required field) |
| 401 | Missing or invalid Authorization header |
| 403 | Authenticated, but the credential lacks permission or scope |
| 404 | Resource not found in this workspace |
| 409 | Conflict (duplicate, state precondition not met) |
| 422 | Validation error from Pydantic |
| 429 | Rate limited; see Rate limits |
| 5xx | Server error; retry with exponential backoff |
How to handle errors well
A few patterns cover almost everything:
- On 401, re-authenticate. Don’t retry the same call with the same credential.
- On 403, surface the message; the user almost always needs an admin action (workspace role, missing connector grant).
- On 404, check that the resource ID came from the same workspace. Cross-workspace IDs always 404 by design.
- On 422, log the full
detailarray. Thelocfield tells you which field broke;msgtells you why. - On 429 and 5xx, retry with exponential backoff and jitter. Don’t retry tighter than 1s on 429.
Common error scenarios
These come up often enough to call out:
401 Missing or invalid Authorization headerusually means thetnx_key was rotated or the JWT expired. Mint a fresh credential.403 forbidden_scopemeans a workspace member tried to do something only an admin can do (e.g., mint API keys, change billing).409 conflicton lead creation usually means the email already exists; use the upsert path or search-then-update instead.422withloc: ["body", "segment_id"]means the segment doesn’t exist in your workspace. Cross-tenant IDs always validate as missing.
Last updated on