Docs
Request an API key

Handle errors and retries

Decide what to do from the error code, and retry only the failures that can succeed later.

/docs/guides/errors-and-retries.md

Every /v2 error has a JSON body with a code. Branch on code. The text of message is for people and can change.

Choose what to do

Kind of failure Codes What to do
Your request is wrong 400 codes, 401, 403, 404, 413, 415 Fix the request. Retrying unchanged can't help.
The points don't work point_not_snapped, out_of_coverage, no_route, reference_not_found Change the input, or tell the user.
Too many requests rate_limited Wait for Retry-After, then retry.
Monthly data cap reached data_cap_exceeded Don't retry. Email contact@sieitz.com to raise it.
A temporary failure engine_unavailable, unavailable, engine_timeout Retry with backoff, then give up.
An unexpected reply internal_error Retry once, then report it.
Not offered here capability_unavailable Don't retry. Read capabilities from GET /v2/info.

Both rate_limited and data_cap_exceeded are 429, so check code before you retry. data_cap_exceeded has no Retry-After, and retrying can't help until the cap is raised or the month ends.

Errors lists every code.

Retry with backoff

Wait longer after each attempt, add some randomness, and stop after a few tries. This example retries only the codes that can succeed later.

javascript
const RETRY = new Set(["rate_limited", "engine_unavailable", "unavailable", "engine_timeout"]);

async function callWithRetry(url, init, attempts = 4) {
  for (let attempt = 0; ; attempt++) {
    const res = await fetch(url, init);
    if (res.ok) return res.json();
    const error = await res.json();
    if (!RETRY.has(error.code) || attempt === attempts - 1) throw error;
    const retryAfter = Number(res.headers.get("Retry-After")) || 0;
    const backoff = 2 ** attempt + Math.random();
    await new Promise((resolve) => setTimeout(resolve, Math.max(retryAfter, backoff) * 1000));
  }
}

Find the point that failed

point_not_snapped and out_of_coverage include details.point_index, the zero-based position of the point that failed. For a matrix, out_of_coverage counts the sources first and then the destinations: with 3 sources, point_index: 4 is the second destination.

Handle a failure that isn't JSON

Check the status before you rely on the body. A network failure or a proxy between you and the API may not return JSON, so treat a body you can't parse as a temporary failure.