Errors & status codes
AllAPI speaks one response shape everywhere: a JSON envelope with an ok boolean.
When a public source is reachable you get ok:true and real data. When it is walled, empty, or failing,
you get ok:false and a documented, honest error — never a fabricated success.
The response envelope
Every response — success or failure — is the same object. Read data when ok is true; read error when it is false.
// success { "ok": true, "data": { /* the real payload */ }, "error": null, "meta": { } } // error { "ok": false, "data": null, "error": { "code": "unauthorized", "message": "...", "detail": { "status_code": 404, "retriable": false } }, "meta": { } }
error.detail.status_code carries the upstream source's own status when the failure came from a public source;
error.detail.retriable tells you whether trying again may succeed.
The one rule: branch on ok, not on HTTP status
Most source-level problems — a walled page, a rate-limited upstream, an empty result — come back as
200 OK with ok:false. The HTTP status reflects our gateway; the field ok
reflects your data. Always check ok first. HTTP 4xx/5xx are reserved for gateway-level conditions
(auth, rate limits, unknown platform) described below.
HTTP status codes
What the gateway itself returns. Anything not in this list means the request reached a service and the outcome is in the envelope.
| Status | Meaning | Body |
|---|---|---|
| 200 | Request handled. Real data (ok:true) or an honest source error (ok:false). | envelope |
| 401 | Missing, unknown, or deactivated API key. | envelope · unauthorized |
| 404 | Unknown platform, or a route that does not exist on a known platform. | envelope / {"detail":"Not Found"} |
| 405 | Wrong HTTP method — most data routes are POST. | {"detail":"Method Not Allowed"} |
| 422 | Request body failed validation (missing/invalid field). | {"detail":[…]} |
| 429 | Rate limit or monthly quota exceeded. See Rate limits. | envelope · rate_limited |
| 503 | Temporary — the service is briefly unavailable. Retry after a short pause. | envelope |
Validation (422) and method (405) errors use FastAPI's native
{"detail":…} shape rather than the ok envelope. If ok is absent from a response, you hit one of these — check the HTTP status.
Error codes
When ok:false, error.code is a stable, machine-readable string you can switch on.
Gateway codes
| Code | When |
|---|---|
| unauthorized | API key missing, unknown, or deactivated. |
| rate_limited | Per-minute rate limit or monthly quota exceeded. |
| not_found | The requested platform or resource does not exist. |
| validation_error | Input failed a semantic check. |
| bad_input | The request was malformed. |
| upstream_walled | The public source blocked or challenged the request (login wall, anti-bot). |
| upstream_unreachable | The public source timed out or could not be reached. |
Source codes
Errors that originate at a specific platform use a namespaced code,
<platform>.<reason> — for example nasa.not_found,
spotify.rate_limited, or github.unavailable. The reason mirrors the source's own
status; error.detail.status_code gives the exact upstream code.
Rate limits & headers
Limits are per API key. Every response carries your live budget; a 429 includes Retry-After.
| Plan | Requests / minute |
|---|---|
| Free | 60 |
| Standard | 120 |
| Pro | 300 |
| Business | 600 |
| Enterprise | 1,200 |
| Max | Unmetered |
Response headers on every call: X-RateLimit-Limit, X-RateLimit-Remaining,
X-RateLimit-Reset. On a 429: Retry-After (seconds). Monthly credits are separate from the
per-minute rate and are set by your plan — see Pricing.
Composite & MCP responses
Composite endpoints fan out to several sources and merge the results. They are partial-tolerant:
ok:true as soon as at least one source returns real data. Sources that failed are still listed honestly inside
data, each with its own status, so nothing is silently dropped.
| Code | When |
|---|---|
| composite.all_upstream_failed | Every source was tried and all failed. |
| composite.no_subservice_applicable | No source matched the input, so nothing was attempted. |
Per-source badges inside data carry a status of real, empty,
timeout, transport_error, skipped_input, or unsupported.
Handling errors well
- Check
okfirst. Treatok:falseas the error path regardless of HTTP status. - Switch on
error.code, not on the humanmessage(which may change). - Respect
Retry-Afteron 429, and back off on upstream_unreachable (oftenretriable:true). - Do not retry unauthorized, validation_error, or upstream_walled — the outcome will not change without a different request.
const r = await fetch(url, { method: "POST", headers, body }).then(x => x.json()); if (!r.ok) { switch (r.error.code) { case "rate_limited": /* wait Retry-After, retry */ break; case "upstream_unreachable": /* backoff + retry */ break; default: /* unauthorized, walled, validation → surface it */ } } else { use(r.data); }
See also API Reference · Getting Started · All platforms · Status.