Docs · Concepts

Errors

Errors use the usual HTTP status codes, with a code your program can act on and a message you can log.

Preview: may change before launch · Updated

Preview

This is how the API is planned to work. Names and fields may change before launch. The APIs are in early access: join early access to get a key when they're ready.

The error format

An error comes back as JSON with an error object: code is fixed, so match on it; message says what went wrong in words, and may change.

Response · 400
{
  "error": {
    "code": "invalid_request",
    "message": "email is required"
  }
}

Codes

StatusCodeWhat happenedTry again?
400invalid_requestThe request is missing something or isn't valid.No: fix the request.
400invalid_jsonThe body isn't valid JSON.No: fix the request.
401unauthorizedThe API key is missing, wrong or revoked.No: check the key.
402out_of_creditsYour credits or emails for this period have run out.Not until you have more.
403account_suspendedThis account is suspended.No: contact us.
403feature_unavailableThis API isn't open to your account yet.No.
404not_foundThere's no such endpoint or record.No.
405method_not_allowedThis endpoint takes another method. Allow lists them.No: fix the request.
422domain_not_verifiedfrom isn't on a domain of yours that's ready.Once its DNS is set up.
422recipient_suppressedThis address has bounced, complained or opted out.No.
429rate_limitedToo many requests for your key.Yes, after Retry-After seconds.
429capacityWe're at our limit for email checks or sending for now.Yes, after Retry-After seconds.
429daily_send_limitYou've reached today's sending limit.Yes, after Retry-After seconds.
429poll_too_soonYou asked for a search's results too soon after asking before.Yes, after Retry-After seconds.
500internalSomething went wrong on our side.Yes, after a short wait.
503unavailableA service we rely on is down.Yes, after a short wait.

Every answer has an x-request-id header, and errors repeat it as request_id: send it to us if you need help with a call. A 5xx may come without the JSON body, such as when the request never reached the API, so don't count on one.

When to try again

  • 429: wait for the seconds in Retry-After, then try again.
  • 5xx: try again after a short wait, doubling it each time (1, 2, 4, then 8 seconds), and give up after a few tries.
  • 400, 401 and 402: the same request will fail the same way. Log it and fix the cause.
Trying again
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function withRetries(send) {
  for (let attempt = 1; ; attempt++) {
    const res = await send();
    const retry = res.status === 429 || res.status >= 500;
    if (!retry || attempt === 5) return res;
    // Retry-After when we're told; otherwise 1, 2, 4, then 8 seconds.
    const seconds = Number(res.headers.get("Retry-After")) || 2 ** (attempt - 1);
    await sleep(seconds * 1000);
  }
}

Pass withRetries (or with_retries) a function that makes the request, so each try sends it again.

Timeouts

A check asks another company's mail server, and some take up to a minute to answer. Give POST /verify and POST /find a client timeout of about 90 seconds; the examples on these pages do.

Be careful retrying POST /emails after a timeout: the send may have been accepted before the connection dropped. Send an Idempotency-Key header, and the same key sent again won't send the email twice.

Questions about the APIs? Email pele@magpiecrm.com.