Errors
Every error has the same shape: a stable code to branch on, a message for people, and a request id to quote to support.
The error shape
JSON
{
"error": {
"code": "validation_failed",
"message": "Some fields are missing or invalid.",
"request_id": "req_0f3a9c1b2d4e5f60718293a4b5c6d7e8",
"fields": [
{
"field": "to.city",
"message": "Enter the city"
},
{
"field": "parcels.0.weight_grams",
"message": "Too small: expected number to be >=1"
}
],
"docs_url": "https://app.evipostal.com/docs/errors#validation_failed"
}
}codenever changes meaning. Branch on it, not on the message.fieldsappears onvalidation_failed: one entry per field, with a dotted path such asto.city.request_idis also in theX-Request-Idheader of every answer.- Errors never contain a carrier's own wording, internal details or another business's data.
Every code
| Code | Status | What it means and what to do |
|---|---|---|
| invalid_request | 400 | The request body could not be read. Send valid JSON with Content-Type: application/json. |
| validation_failed | 400 | One or more fields are missing or invalid. fields lists each one. |
| idempotency_key_required | 400 | This request moves money or books a shipment. Send an Idempotency-Key header. |
| request_too_large | 413 | The request body is larger than 256 KB. |
| authentication_required | 401 | No API key was sent. Send Authorization: Bearer <your secret key>. |
| invalid_api_key | 401 | The API key is not recognised. Check you copied the whole key. |
| api_key_revoked | 401 | The API key was revoked or has expired. Create or roll a key in the developer portal. |
| insufficient_scope | 403 | The API key does not have the scope this request needs. The message names the scope. |
| production_access_required | 403 | Production access is not enabled for this business yet. Use a sandbox key, or request production access. |
| application_disabled | 403 | The application this key belongs to is turned off in the developer portal. |
| not_found | 404 | No such object for this application and environment. |
| conflict | 409 | The object is not in a state that allows this request. The message says why. |
| rate_expired | 409 | The rate has expired. Request fresh rates and book one of them. |
| idempotency_key_in_use | 409 | A request with this Idempotency-Key is still being processed. Retry after a moment. |
| idempotency_key_reused | 422 | This Idempotency-Key was already used with a different request. Use a new key for a new request. |
| booking_failed | 422 | The carrier did not accept the booking. Nothing was charged. Request fresh rates and try again, or choose another rate. |
| label_not_ready | 409 | The label is still being prepared by the carrier. Retry after the Retry-After interval. |
| unsupported_operation | 422 | The carrier behind this shipment does not support this operation through EviPostal. |
| insufficient_funds | 402 | Your EviPostal wallet cannot cover this shipment. Add funds in the dashboard, then book again. |
| rate_limited | 429 | Too many requests. Wait for the Retry-After interval. |
| carrier_unavailable | 503 | The carriers did not respond. Nothing was booked or charged. Retry later. |
| internal_error | 500 | Something went wrong on our side. Retry, and quote the request_id if it keeps happening. |
Safe to retry as they are: rate_limited, idempotency_key_in_use, label_not_ready (after Retry-After), carrier_unavailable and internal_error. Retry bookings with the same Idempotency-Key.
