Errors & retries
Status codes, the error body, and which requests are safe to retry.
View as MarkdownError body#
Errors return a JSON body with an error string. Most also carry a message with more detail, and some add fields that help you fix the request (for example usage on a 429):
{
"error": "Missing API key",
"message": "Provide API key in X-API-Key header"
}
Branch on the HTTP status first, then on error. Treat message as human-readable text that can change.
Status codes#
| Status | Meaning | What to do |
|---|---|---|
200 |
OK | |
201 |
Created | The body is the new record |
202 |
Accepted | Work continues in the background, for example a measurement. Poll the status URL in the body |
204 |
No content | Success with no body, for example a delete |
400 |
Bad request | A required field is missing or a value is invalid. The body says which. Don't retry unchanged |
401 |
Unauthorized | The key is missing, wrong or revoked (Authentication) |
402 |
Payment required | The workspace's billing is past due or inactive |
403 |
Forbidden | The key lacks a permission, or the plan doesn't include this feature |
404 |
Not found | The record doesn't exist in this key's workspace. Records in other workspaces always look like 404 |
409 |
Conflict | The change conflicts with the record's current state, for example a duplicate |
413 |
Too large | The request body or upload is over the size limit |
422 |
Unprocessable | The request is well-formed but can't be done, for example an address that can't be found |
429 |
Too many requests | The key reached its call cap, or you're sending too fast. Back off (Limits & billing) |
500 |
Server error | Our fault. Safe to retry with backoff |
502 503 504 |
Upstream unavailable | A dependency such as an imagery provider is slow or down. Retry with backoff |
A 404 for a path that doesn't exist at all returns {"error": "Resource not found"}. If you see that on a documented endpoint, check the method and the path, including /api/v1.
Retries#
Retry on network errors, 429, 500, 502, 503 and 504, with exponential backoff and jitter: wait about 1, 2, 4, 8 seconds, up to five tries. Honor Retry-After when it's present.
Don't retry 400, 401, 402, 403, 404, 409 or 422 without changing something.
| Request | Safe to retry? |
|---|---|
GET |
Yes, always |
PATCH |
Yes: sending the same fields twice gives the same result |
DELETE |
Yes: a second delete returns 404, which you can treat as done |
POST that creates a record |
Use an external reference so a retry doesn't make a duplicate, and look the record up by that reference before retrying (Jobs) |
POST /detect/* |
Each accepted call starts a new measurement and counts as one. If a start call times out, check your recent results before trying again (Measure a site) |
Timeouts#
Use a client timeout of about 30 seconds for normal calls and 60 seconds for downloads. Measurements don't need long timeouts: the start call returns quickly with a job_id and you poll for the result.
Getting help with an error#
Email [email protected] with the method and path, the time of the call (with time zone), the status and response body, and your key's 11-character prefix. Never send the full key.