Errors
HTTP status codes, error bodies and what to do about each one.
The API uses standard HTTP status codes. The body is JSON.
Error body#
Endpoint errors have a machine-readable error code and a message for people:
400
{ "error": "validation_failed", "message": "companyNumber or companyName is required" }Two shapes today
Errors from the authentication and quota layers put a sentence in error rather than a code, and quota errors add a code field. Branch on the HTTP status first, then on code if present, then on error. We plan to make every error use the same shape.
401
{ "error": "Invalid or revoked API key" }429 (quota)
{ "error": "...", "code": "QUOTA_EXCEEDED", "metric": "...", "limit": 100, "used": 100, "resetsAt": "2026-11-01T00:00:00.000Z" }Status codes#
| Status | Meaning | Retry? |
|---|---|---|
| 200 / 201 | Success. | - |
| 204 | Success with no body, for example after a delete. | - |
| 400 | The request is invalid. The message says what to fix. | No. Fix the request. |
| 401 | Missing, invalid, revoked or expired API key. | No. |
| 403 | Not allowed: IP allow-list, unverified email, unapproved account, a test key managing webhooks, or a plan without this feature (plan_upgrade_required, subscription_required). | No. |
| 404 | Not found for your account. | No. |
| 409 | Conflict, for example the wrong report type for a check. | No. |
| 413 | The body is over 10 MB. | No. Send smaller images. |
| 429 | Rate limit (rate_limit_exceeded) or monthly quota. | Rate limit: yes, after Retry-After. Quota: after resetsAt. |
| 500 | An error on our side. | Yes, with backoff. |
| 501 | The feature is not enabled on this deployment. | No. |
| 503 | A dependency is unavailable, or your plan could not be read (plan_unavailable). Nothing was charged. | Yes, with backoff. |