Open Application Platform Docs

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 carries upgrade_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.