Errors and retries
Errors and retries
Error envelope
{
"request_id": "req_01J8Q…",
"error": {
"code": "CAPABILITY_NOT_ENABLED",
"message": "…",
"status": 403,
"capability": "routing.optimize",
"retry_after_seconds": null,
"details": [],
"doc_url": "https://open.superroute.ca/developer/errors"
}
}
Client logic must branch on code, which is never localized and never changes meaning. message
is always localized and varies with the caller's Accept-Language; it is intended for display, not
for control flow.
Retry classification
| Retry | Codes |
|---|---|
| Yes, with backoff | RATE_LIMITED, CONCURRENCY_LIMIT, ENGINE_UNAVAILABLE, OPEN_UNAVAILABLE, INTERNAL_ERROR |
| No — the request is invalid | VALIDATION_FAILED, MALFORMED_REQUEST, REQUEST_TOO_LARGE, SOLVE_INFEASIBLE, ENGINE_REJECTED |
| No — the account is not entitled | CAPABILITY_NOT_ENABLED, CAPABILITY_NOT_GRANTED_TO_KEY, ENGINE_NOT_ENABLED, OPEN_API_DISABLED, QUOTA_EXHAUSTED |
| No — the credential is invalid | TOKEN_MISSING, TOKEN_INVALID, KEY_REVOKED |
RATE_LIMITED and QUOTA_EXHAUSTED both carry Retry-After. Clients should honour the supplied
value rather than applying an independently chosen backoff.
Distinguishing the four refusals
The four refusal codes are deliberately distinguishable without inspecting the message, because each requires a different remedy:
NOT_AUTHORIZED(403) — the credential is valid but the operation is not permitted to it. This is returned for a session token narrowed to a smaller capability set.CAPABILITY_NOT_ENABLED(403) — the account does not subscribe to the capability. The response carriesupgrade_url.CAPABILITY_NOT_GRANTED_TO_KEY(403) — the account holds the capability but the presented key was not granted it. This is resolved in the portal and does not require a purchase.QUOTA_EXHAUSTED(402) — the included volume is exhausted and the policy is to block. The distinct HTTP status allows a billing failure to be identified without string matching.
Timeouts
Synchronous calls are budgeted well below typical gateway timeouts. SOLVE_TIMEOUT indicates that
the problem exceeded the synchronous path; resubmit with mode: "async" and collect the result
from the job. Repeating the same request synchronously will time out again and will be charged a
second time.