Errors
The API uses conventional HTTP status codes and returns a consistent JSON error body.
Error shape
Section titled “Error shape”Every error body is a flat object with a single error string:
{ "error": "Invalid request body" }Some errors carry one extra field alongside it — a 409 row_conflict on a
bulk upload lists the offending rows under conflicts, for example — but
error is always present and always a string, so body.error is the one
thing to branch on.
Status codes
Section titled “Status codes”| Code | Meaning | What to do |
|---|---|---|
200 |
Success | — |
201 |
Created — a new bulk job | — |
202 |
Accepted — the work is still running | Poll: a pending single verification or a just-committed bulk job. |
400 |
Bad request — the body is not JSON, or a field is missing, empty, or unknown | Fix the request. |
401 |
Unauthorized — missing, malformed, or revoked API key | Check your API key. |
402 |
Payment required — the account cannot spend a credit | Read error; top up or resolve billing, then retry. |
404 |
Not found — the resource does not exist or is not yours | Check the id. |
409 |
Conflict — the request contradicts the resource’s current state | Read error; see below. |
429 |
Too many requests | Back off; see Rate limits. |
5xx |
Server error | Retry with backoff; contact support if it persists. |
Error strings
Section titled “Error strings”error |
Status | When |
|---|---|---|
Request body must be valid JSON |
400 |
The body could not be parsed as JSON. |
Invalid request body |
400 |
The JSON is missing a required field, has an empty or over-long value, or carries a field the endpoint does not accept. |
Idempotency-Key is too long |
400 |
The header exceeds 200 characters. |
Invalid timeout |
400 |
The timeout query parameter on a single verification is not a positive whole number. |
Unauthorized |
401 |
The key is missing, malformed, revoked, or not one we issued. |
insufficient_credits |
402 |
The wallet is empty. Nothing was started and nothing was charged. The body also carries balance, required and shortfall. |
account_frozen |
402 |
The account is frozen and cannot spend credits. The body also carries reason: past_due, cancelled, or null when no reason was recorded. |
Job not found |
404 |
The bulk job id does not exist or belongs to another account. |
row_conflict |
409 |
A bulk upload reused a row_index with a different address. The body also carries conflicts: [{ row_index, email }]; nothing from the chunk was written. |
input_sealed |
409 |
Rows were sent to a bulk job that has already been committed. |