TOVRReference

Errors

The TOVR REST API error catalog — the error envelope, the six error types, every error code with its HTTP status and what to do about it, and retry guidance. Every error's doc_url links to an entry on this page.

Every /api/v1 error answers with a non-2xx status and the same JSON envelope. Each error's doc_url links to its entry on this page. The conventions shared by all three TOVR APIs are in API conventions; this page is the catalog for the TOVR REST API.

Response format

{
  "error": {
    "type": "invalid_request_error",
    "code": "validation_failed",
    "message": "The request did not match the expected shape.",
    "param": "contacts",
    "details": [{ "path": "contacts.0.email", "code": "invalid_string", "message": "Invalid email" }],
    "request_id": "req_…",
    "doc_url": "https://tovr.eu/docs/tovr/reference/errors#validation_failed"
  }
}
FieldAlways presentDescription
typeyesThe coarse bucket. It never gains a member without an API version bump.
codeyesThe specific cause, from the closed list below. Branch on this.
messageyesA human-readable explanation, in English. Do not parse it.
paramsometimesThe field or header at fault, when one can be named.
detailssometimesMachine-shaped specifics, such as validation issues.
request_idyesAlso sent as the X-Request-Id header. Quote it in a support request.
doc_urlyesA link to this page, at the entry for code.

type tells you what kind of action fixes the error. code tells you which one. A client that switches only on code should still have a fallback per type, because new codes can be added.

message is always English, in every locale, as it is with most public APIs. code is the contract and does not change. This page is translated.

Types

typeMeaning
authentication_errorThe credentials are missing or not valid.
permission_errorThe caller is authenticated but not allowed to do this.
invalid_request_errorThe request cannot be served as sent.
conflict_errorThe request conflicts with data that already exists.
rate_limit_errorReserved. Today the per-minute rate limit answers with rate_limited and the type invalid_request_error.
api_errorA fault on TOVR's side or in a service TOVR depends on.

Authentication errors

A 401 is answered before the request reaches the error envelope, so today its body is a plain {"error": "Unauthorized: …"}. Branch on the 401 status and the WWW-Authenticate: Bearer error="invalid_token" header, then get a new token as described in Authentication.

missing_credentials

401. The request has no Authorization: Bearer header. Send the access token with every request.

invalid_token

401. The token is not one TOVR issued, or it was revoked. Get a new token. Do not retry the same one.

expired_token

401. The token was valid but has expired. Tokens last one hour. Get a new token and retry.

Permission errors

insufficient_scope

403. The token does not have the scope this endpoint needs. The REST API overview lists the scope for each endpoint. Give the client application that scope, then get a new token. Retrying with the same token does not help.

forbidden

403. The token has the right scope, but this organization may not act on this object. Do not retry.

quota_exceeded

402, type permission_error. The organization has used its monthly API request quota. Waiting does not help until the month resets. Upgrade the plan to continue. See Rate limiting and quota.

Invalid request errors

validation_failed

422. The body, query or path parameters do not match the expected shape. details lists each issue with its path. A malformed Idempotency-Key header answers 400 with param: "Idempotency-Key". Fix the request. Do not retry it unchanged.

unknown_parameter

422. Reserved for a parameter the endpoint does not accept. No endpoint returns it today.

invalid_id

422. An id in the path is not a valid identifier. Check that you sent the id that TOVR returned.

invalid_cursor

422. The cursor value could not be decoded. Send the next_cursor from the previous page unchanged, or start again without a cursor.

contact_required

422, param: "contacts". A shipment must name at least one contact with a name and an email or phone, so that a carrier can reach someone. Add the contact to the request body.

org_not_reachable

422, param: "visibility". The organization cannot publish freight until its profile says how a carrier can reach it. The message lists what is missing. Complete the organization profile in Settings → General, or create the shipment with visibility: "private". Retrying the same request does not help.

insufficient_market_data

422. The request was valid, but there is not enough market data to price that lane. details.estimate contains the full estimate, with zero prices and quality_status: "INSUFFICIENT_DATA". Changing the request does not help. Try a different lane, or try again later when more data is available.

cursor_expired

410. The cursor points at events older than the 30-day retention window, so your copy of the data may have gaps. Read the current state again from the list endpoints, then resume from the next_cursor of a new GET /v1/events. See Events.

not_found

404. The object does not exist, or it is not visible to this organization. The two cases look the same on purpose.

rate_limited

429, type invalid_request_error. The client application sent more requests per minute than its limit allows. Wait for the number of seconds in the Retry-After header, then retry. See Rate limiting and quota.

Conflict errors

duplicate_external_id

409. Your organization already has an object with this external_id. Read the existing object instead of creating it again, or send a different external_id.

external_id_owned_by_another_org

409. Another organization already uses this external_id. Send a different external_id.

idempotency_key_reuse

409, param: "Idempotency-Key". This Idempotency-Key was already used for a different request. Use a new key for each operation. Use the same key only when you retry the same request. See Idempotency.

API errors

internal_error

500. A fault on TOVR's side. Retrying the same request does not help. Contact support and quote the request_id.

service_unavailable

503. A service that TOVR depends on is unavailable. Your request was valid. Retry with exponential backoff.

Retry strategy

  • 429 rate_limited: wait for the Retry-After seconds, then retry.
  • 503 service_unavailable: retry with exponential backoff (1 s, 2 s, 4 s), then stop after three attempts.
  • 500 internal_error: do not retry. Contact support and quote the request_id.
  • 402 quota_exceeded: do not retry until the month resets or the plan is upgraded.
  • 401: get a new token, then retry once.
  • Other 4xx: do not retry. Fix the request first.

Mutations that you retry should send an Idempotency-Key, so that a retry never creates the same object twice.

On this page