Error codes

Error object shape

Errors come back as one flat object with an HTTP statusCode, a stable machine code, a human message and a requestId. Branch on the code. The message is written for a person reading a log and may be reworded when it can be clearer.

An error means the request never produced a verdict, so it is not billed. That is different from an unknown result, which did run and which is refunded. If you reserved credits on a request that then failed, they are refunded.

Two of these deserve a different response from your code. A 429 means slow down and try again. A 422 CREDITS_INSUFFICIENT means the balance is too low, and retrying will not help until credits are added.

JSON
{
  "statusCode": 422,
  "code": "CREDITS_INSUFFICIENT",
  "message": "Not enough credits",
  "requestId": "req-2c8ff1"
}

Reference

HTTPcodeWhat went wrong and whether to retry
400VERIFY_TOO_MANYMore addresses than a synchronous call allows. Use a job instead.
400VERIFY_EMPTYThe request held no addresses to check.
400JOB_EMPTYThe list held no addresses.
400JOB_TOO_LARGEMore than 50,000 addresses in one job. Split the list.
400JOB_NOT_CANCELLABLEThe job has already finished, so there is nothing to cancel.
400IDEMPOTENCY_KEY_INVALIDIdempotency-Key must be 8 to 128 characters.
401UNAUTHORIZEDNo key, a wrong key or a revoked key.
403(permission)The key lacks the scope for this route. Create a key with the scope you need.
404JOB_NOT_FOUNDNo job with that id on your account.
422CREDITS_INSUFFICIENTThe balance is too low for the request. Add credits, then resubmit.
422NO_CAPACITYEvery verification node is busy or unavailable. Retry shortly; nothing was billed.
422NO_NODESNo verification node is available yet. Contact support if this persists.
429RATE_LIMITEDToo many requests. Back off for the window, then continue.

requestId is on every error and matches the X-Request-Id response header. Quoting it turns a support thread into a two-minute lookup.

Three piles: wait, fix, or call a person

Sort every code into one of three piles and your error handling gets short. Wait and retry covers 429 RATE_LIMITED and 422 NO_CAPACITY. Fix the request covers the 400 codes and 404 JOB_NOT_FOUND, where sending the same thing again can't work. Call a person covers 401 and 403, because no code change or pause will help.

Say your nightly cleaning job hits CREDITS_INSUFFICIENT at 2 a.m. The wrong design retries fifty times and gives up with the list dropped. A better one keeps the list queued and alerts whoever buys credits, so the job picks up where it left off after the top-up.

A 401 right after a key rotation deserves the same treatment. Something is still holding the old key, and only a person can find out which service it is.

What to log, and what to leave out

Log four things for every error: the HTTP statusCode, code, requestId, and your own job name. With those, a support thread becomes a lookup. Leave out the request headers, since a log line holding your key turns a small bug into a rotation.

Keep BAD_SYNTAX out of your error counts. It's a result for one address and says nothing about the request, meaning the string wasn't shaped like an address. Run a basic shape check before you call, and if these keep arriving, read a sample of the strings. You'll often find a column mix-up behind them.

New codes can appear over time, so give your handler a default branch. One sensible fallback is to go by the status class when you don't know the code. A 4xx other than 429 means don't retry, and a 5xx means retry with backoff. Your client keeps working on the day we add one.

Questions developers ask

Do errors cost credits?

No. A failed request produces no verdict, and credits reserved for it are refunded.

Is the message string stable?

No, so do not parse it. code is the contract.

What is the difference between an error and an unknown?

An error means we could not run the check. An unknown means we ran it and the receiving server would not answer clearly. Neither costs a credit.

Try it against a sandbox key

Scripted verdicts, no SMTP connections, no credits. Live keys come with 100 free checks a month and no card.