Read an error response
Every failed request returns the same small object, and error tells you what to change rather than only what went wrong.
The envelope
{ "ok": false, "error": "invalid JSON" }
{ "ok": false, "error": "internal error", "ref": "3f9a1c22" }ok is always false. ref appears only on 500: it ties your request to the server log, so quote it when you ask about the failure. The one route that departs from this shape is POST /records/{site} when the run itself ends in 499 or 500: the body is the normal records response with ok: false, the records written so far and error filled in.
Status codes
| Code | When | Example message | What to do |
|---|---|---|---|
400 | The body cannot be used. | invalid JSONinput must be an object | Fix what the message names. A message starting invalid input: lists every field that failed the source's schema. |
401 | No active key matches the header. | invalid api key | Send the secret as x-api-key. See Authentication. |
402 | The key is valid; its account has no credit left, or a payment dispute holds it. | insufficient credits: this account's balance is used up. Buy credits at /account to continue | Buy credit under Credits on the account page. The key resumes as soon as the balance is positive. |
403 | This key may not use that source. | key not authorized for site "amazon" | Use a key that covers the source, or another source. |
422 | idempotency-key was already used, with a different request. | this Idempotency-Key was already used with a different request; a key may only be reused to retry the SAME request | Send a new idempotency-key value, or resend the exact same request to get the original job back. See Idempotency. |
404 | Unknown route, source or job. | unknown site; known: amazon, glassdoor, indeed, loopnet, realtor, reddit, rightmove, tiktok, youtube, zillow, zooplano such job | Check the path. A job answers 404 to any key but the one that submitted it, and after its retention window. |
413 | The body is over 64 KB, or maxItems is over 500 on POST /records. | body too largesync POST /records/amazon is capped at 500 items (requested 5000); use POST /jobs/amazon for larger runs | Send a smaller body, or submit the same body to POST /jobs/{site}. |
429 | A limit or quota is reached. | rate limit exceeded (120/min); retry in 4stoo many queued jobs for this key (10); wait for running jobs to finishunbilled bandwidth limit reached for this account (…); it resets at the start of the next UTC day | Wait the Retry-After seconds, or let running jobs finish. Rate limits lists every message. |
499 | POST /records only: the job behind the request was cancelled before it finished. | "ok": false with the records written so far and error set | Read error. The records in the response are yours and stay billed. |
500 | Something failed inside the API, or the run behind POST /records failed. | internal error with refdelivered 0 records; 3 request(s) failed: blocked | Retry once with the same idempotency-key. If it repeats, quote ref or the message when you write to support. |
503 | The service is not taking new work right now. | not accepting new jobs right now: retry in 60 secondsamazon is paused: retry later | Wait the Retry-After seconds (60 for maintenance, 300 for a paused source or exhausted capacity) and submit again. Jobs already queued keep waiting and start when the pause lifts. |
Messages are examples of the real wording; the site list, the numbers and the job ids vary with your key and request.
Errors on a job
A job that ends as failed or cancelled carries the reason in its error field, on GET /jobs/{id} and in the webhook body. A job you cancelled yourself has error: null.
| error | status | What it means |
|---|---|---|
cancelled before start: the API key was revoked or suspended | cancelled | The key changed between submission and start. Submit again with an active key. |
cancelled before start: amazon is no longer available to this key | cancelled | The source was withdrawn for this key. Nothing was charged. |
cancelled before start: not accepting new jobs right now: retry in 60 seconds | cancelled | A POST /records request waiting on a paused service is cancelled instead of held. Submit it as a job and it waits. |
job exceeded 1800000ms; returned partial results | cancelled | The run hit the service's duration limit. The records written so far are readable and billed; submit the rest with a smaller request. |
cancelled: the service restarted while this job ran — the records delivered before then are kept (and billed); resubmit to continue | cancelled | The API restarted cleanly for a release while the job was running. Resubmit the rest with a new idempotency-key. |
server restarted while the job was in progress | failed | A job left running by an unclean restart, recovered at the next boot. Submit the request again with a new idempotency-key. |
delivered 0 records; 3 request(s) failed: blocked | failed | Nothing came back and at least one request failed. stats.failures names each one. Nothing was charged. |
run failed: internal error (ref 0f0c4a18) | failed | Quote the ref when you write to support. |
Retrying safely
429and503: wait theRetry-Afterseconds, then send the same request. Both are safe to retry.500on a submission: retry once with the sameidempotency-key. If the first attempt did create the job, the retry returns it instead of a duplicate. See Idempotency.400,401,402,403,404and413: change the request or the account first. Retrying the same request returns the same answer.422: theidempotency-keyis already spoken for by a different request. Retrying with the same body never clears it; send a new value instead.
Next step
Rate limits explains each 429 and how to read your remaining allowance from GET /usage.