Skip to content

Account

Errors

The one error envelope, every error code, and whether to retry.

Every failure returns the same JSON envelope. Never an HTML page, never a bare string:

JSON
{ "error": { "code": "not_found", "message": "unknown metro 'boston'", "request_id": "req_7431b51e10ec2b77" } }
FieldMeaning
codeOne value from a closed list (below). Branch on this.
messageA human-readable explanation. It can change; do not parse it.
detailsOptional machine-readable context, such as the parameter that failed or the scopes your key has.
request_idThe id of this request. Quote it when you contact support.

Error codes

Branch on code, not the status alone: 403 and 429 each cover codes with different remedies.

StatuscodeRetry?What to do
400bad_requestNoFix the request; details usually names the parameter
401unauthorizedNoSend a valid, unrevoked key in X-API-Key
403forbiddenNoYour key is not scoped for this metro or type; details lists what it can read
403include_not_permittedNoDrop the include=, add include_mode=lenient, or use an entitled key
403feature_not_in_planNoThe endpoint needs a feature your plan does not include; details.feature names it
404not_foundOnly if the input changesCheck the metro, id or slug
405method_not_allowedNoUse GET; the API is read-only
429rate_limitedYes, after Retry-After secondsWait, then retry
429quota_exceededNoThe month's allowance is spent; Retry-After points at the start of next month
500internalOnce, with backoffIf it recurs, contact support with the request_id
501not_implementedNoThis feature is not available here; do not build on it
503unavailableYes, after Retry-AfterBack off and retry

New codes can be added over time, so treat an unknown code by its status.

Handling errors in code

JavaScript
const res = await fetch(url, { headers: { "X-API-Key": process.env.TAILEND_API_KEY } });
if (!res.ok) {
  const { error } = await res.json();
  if (error.code === "rate_limited" || error.code === "unavailable") {
    const wait = Number(res.headers.get("Retry-After") ?? 1);
    // wait `wait` seconds, then retry once
  } else {
    console.error(error.code, error.message, error.request_id);
  }
}

request_id

Every response, success or failure, carries a request id: in the X-Request-Id header, and in the body of an error. Log it next to your own request context and quote it when you contact support; it is how we find your request.

Checklist

  • Check error.code before deciding whether to retry.
  • On a 429, read Retry-After instead of guessing a backoff: the two codes mean very different waits.
  • Do not retry 400, 401, 403, 404 or 501 unchanged.