Skip to content

Error codes

Every error is application/problem+json (RFC 9457). The code is the contract: it does not change, even when the wording of title or detail does. Branch on code, never on title.

{
"type": "https://cargofollow.com/errors/validation_failed",
"title": "Validation failed",
"status": 422,
"detail": "The body does not match the schema.",
"code": "validation_failed",
"request_id": "req_01M2FP3S65WEANPZF49VGJRATH",
"errors": [{ "path": "goods.0.gross_weight_kg", "message": "Expected number, received string" }],
"warnings": []
}
  • code — the stable error code from the table below.
  • request_id — quote this to support; it is how we find your exact request.
  • errors — what is wrong per field, on validation_failed and rule findings.
  • warnings — findings that did not block the request.
  • title — English by default, translated when you send Accept-Language: nl.

The table comes from the register in @freightapi/core/errors; what the API can return is here, and nothing else.

CodeStatusMeaning
bad_request400Bad request
The request is malformed: a wrong parameter, a missing header or a combination that does not exist.
invalid_cursor400Invalid cursor
The `cursor` did not come from an earlier list response, or it expired. Start the list again without a cursor.
invalid_id400Invalid identifier
An identifier in the path or the body does not have the expected shape.
malformed_json400Malformed JSON body
The body is not valid JSON. Check the content type and the encoding.
invalid_api_key401Invalid API key
The API key does not exist, was revoked, or belongs to another environment.
unauthorized401Authentication required
No API key was sent. Put it in the `Authorization: Bearer` header.
forbidden403Forbidden
The key is valid but is not allowed to see or change this resource.
insufficient_scope403Insufficient scope
The key lacks the scope this route requires. Create a key with the right scopes.
live_not_enabled403Live mode is not enabled for this organisation
The organisation is not cleared for live yet. Work with an `sk_test_` key in the sandbox.
test_mode_only403Only available in test mode
This route only exists in the sandbox, for example the simulation endpoints.
turnstile_failed403Turnstile verification failed
The Turnstile check of the public validator did not pass: the token is missing, expired or already used. Fetch a new token and try again.
two_factor_required403Two-factor authentication is required
The console session has not shown a second factor yet, or the account has none while the organisation requires one. Only the console sees this code; an API key has no second factor.
invoice_not_available404The invoice is not available yet
The shipment has not been delivered yet, so there is no invoice: an invoice follows the proof of delivery.
not_found404Not found
The resource does not exist, or not within this organisation and this mode.
pod_not_available404The proof of delivery is not available yet
The shipment has not been delivered yet, so there is no proof of delivery to fetch.
already_signed409Already signed
A signature was already recorded for this role.
conflict409Conflict
The request conflicts with the current state of the resource.
field_frozen409Field is frozen in the current status
The field is frozen in the current status; after issuing, the consignment note fields are fixed.
idempotency_in_progress409A request with this idempotency key is still running
An earlier request with this `Idempotency-Key` is still running. Wait and retry.
idempotency_key_reused409Idempotency key reused with a different request
The same `Idempotency-Key` was used for a different body. Use a fresh key per request.
invalid_state409The shipment is in the wrong state for this operation
The shipment is in a status in which this operation has no meaning.
invalid_transition409Invalid state transition
The state machine forbids this transition, for example `delivered` after `cancelled`.
shipment_immutable409The shipment can no longer be changed
The shipment is finished or cancelled and no longer changes.
token_expired410The link has expired
The inspection or signing link expired.
token_revoked410The link was withdrawn
The sign link was withdrawn by the party that sent it. Ask for a new link.
token_rotated410The link was replaced by a newer one
The link was replaced by a newer one; the old one no longer works.
payload_too_large413Payload too large
The body or the file exceeds the limit of the route.
unsupported_media_type415Unsupported media type
The `Content-Type` is not supported on this route.
identification_invalid422The identification is unknown, already used or expired
The `identification_token` is unknown, already used, older than fifteen minutes or belongs to another sign link. One identification signs once. Ask for a new one.
identification_required422This signature needs an identification at the trust service provider
This sign link asks for `ades` or `qes`. Identify the signer first with `POST /v1/sign/:token/identification` and send the `identification_token` along. Not a failure but a step: the sign PWA renders it as a screen, not as an error.
invoice_incomplete422The invoice misses something EN 16931 requires
The shipment or the query lacks a fact EN 16931 requires — `charges.carriage`, the VAT rate of a domestic run, or the payee account of a Dutch seller. `detail` names which one.
otp_invalid422The one-time password is wrong or expired
The one-time password is wrong, expired or already used. Ask for a new one with `POST /v1/sign/:token/otp`. The same answer covers an `otp_verified_token` that was already spent.
subset_unknown422Unknown eFTI subset
The requested `subset` is not an eFTI subset this platform projects. `GET /v1/shipments/:id/efti` without `subset` returns the common data set.
two_factor_invalid422The two-factor code is wrong, expired or already used
The six digits or the recovery code are wrong, expired or already used. One answer for all three: which of the three it was is exactly what an attacker wants to learn.
validation_failed422Validation failed
The body parses but does not validate. The `errors` array names the problem per field.
otp_locked429Too many wrong one-time passwords
Five wrong codes in a row: this recipient is locked until the ten-minute window passes. `Retry-After` says how long.
rate_limited429Too many requests
Too many requests. Respect `Retry-After` and the `RateLimit-*` headers.
internal_error500Internal error
An unexpected error on our side. Report the `request_id` to support.
pdf_render_failed500The consignment note PDF could not be rendered
The consignment note PDF could not be built. Retry, and report the `request_id` if it keeps failing.
not_implemented501Not implemented
The route is declared but not filled in yet.
provider_unavailable502The eCMR provider is unavailable
The eCMR provider behind this route is not answering. Try again later.
billing_not_configured503Billing is not configured for this organisation
This deployment has no billing provider, so there is no customer portal and nothing is charged. Usage is still visible through `GET /v1/usage`.
qtsp_unavailable503The trust service provider is unavailable
The trust service that signs `ades` and `qes` is absent or refused. Without the binding `QTSP_PROVIDER` this deployment has none — the default in production, because a test certificate is not a qualified signature. Signing at `platform_auth` is unaffected.
service_unavailable503Service unavailable
The API is temporarily unavailable. Try again later.