Errors & rate limits
Branch on `code`, never on the `error` sentence. Quote the `X-Request-Id` response header when you contact support.
Error response format
| Field | Type | Description |
|---|---|---|
| attempt_id | string | *_outcome_unknown: the attempt to quote to support. |
| code | string | Stable reason to branch on, where the table lists one. |
| error | string | Always present. A readable sentence. |
| limit / allowance_remaining | number | 429s: the ceiling reached, or free requests left. |
| message | string | Billing and limit refusals: text to show the account holder. |
| status | string | Order-state conflicts: the order's current status. |
{ "error": "missing X-API-Key" }
{ "error": "departure_date must not be in the past", "code": "date_out_of_range" }
{
"error": "the airline did not say whether this request took effect; it is being confirmed — do not send it again, and quote attempt_id to support",
"code": "booking_outcome_unknown",
"attempt_id": "5f0c2a3e-7b1d-4c9a-9e2f-1a2b3c4d5e6f"
}Error codes
A dash means the body has only `error`. *_outcome_unknown stands for booking_, cancel_, change_, commit_, extras_ and refund_outcome_unknown.
| HTTP | code | What to do |
|---|---|---|
| 400 | action_required | PUT /v1/orders/{id} without `action`. |
| 400 | date_out_of_range | Date in the past or more than 361 days ahead. |
| 400 | idempotency_key_required | A paying write needs an Idempotency-Key header. |
| 400 | infants_exceed_adults | More infants than adults. |
| 400 | invalid_contact_email | A contact email is not one plain address. |
| 400 | invalid_date | Date not YYYY-MM-DD, or multi-city legs out of order. |
| 400 | invalid_search | A search field is invalid; `error` names it. |
| 400 | passenger_cap | More passengers than one order may carry; `error` gives the limit. |
| 400 | payment_method_not_allowed | Payment without a card. Only card payments are accepted. |
| 400 | return_before_departure | return_date is before departure_date. |
| 400 | same_airport | Origin and destination are the same. |
| 400 | too_many_passengers | More than 9 passengers. |
| 400 | use_cancel_confirm | Cancel some flights with POST /v1/orders/{id}/cancel/confirm. |
| 400 | — | Any other invalid body or parameter; `error` names it. |
| 401 | — | Missing, invalid, revoked or expired key. See Authentication. |
| 402 | delinquent, past_due | Unpaid invoices. Settle them in the dashboard. |
| 402 | payment_method_required | This plan books in production only with a card on file. |
| 402 | payment_required | Free requests used up and no card on file. Add a card. |
| 403 | booking_limit_exceeded | Above the member's booking limit. An owner or admin can raise it. |
| 403 | booking_limit_unverifiable | The booking's currency cannot be compared with the member's limit. An owner or admin can book it. |
| 403 | carrier_agreement_required | Not yet approved for this airline in production. Apply from Go Live. |
| 403 | email_verification_required | Verify your email, or add a card. |
| 403 | unknown_plan | Contact support. |
| 403 | — | A key restriction or permission refused the call. See Authentication. |
| 404 | not_found | No such route. Check the path and the /v1 prefix. |
| 404 | offer_not_found | An order id was sent where an offer id is expected. |
| 404 | order_not_found | No such order in this key's environment. May carry `did_you_mean`. |
| 404 | seat_map_segment_not_found | No seat map for that segment; see `segments_available`. |
| 404 | — | Offer not found or no longer available. Search again. |
| 405 | method_not_allowed | Wrong method; the `Allow` header lists the right ones. |
| 409 | already_paid | The order is already paid. |
| 409 | attempt_settled | Support settled this request before it was sent. Nothing was sent; read the order. |
| 409 | idempotency_key_in_flight | A request with this key is still running. Retry after Retry-After. |
| 409 | idempotency_key_reused | Key already used with a different body. Use a new key. |
| 409 | illegal_transition | The order's status does not allow this. `status` gives it. |
| 409 | nothing_to_refund | The order was never paid. Cancel it instead. |
| 409 | offer_already_ordered | Same offer and travellers already booked. Read `order_id`. |
| 409 | offer_not_priced | Price the offer with POST /v1/offers/price before paying. |
| 409 | order_busy | Another write on this order is running. Retry after Retry-After, same key. |
| 409 | *_outcome_unknown | An earlier attempt with this key, or on this order, is still being confirmed. Do not resend. |
| 409 | refund_not_requested | Cancelled without a refund request. Ask the airline. |
| 409 | self_transfer_unavailable | The self-transfer trip no longer connects. Search again. |
| 409 | trip_not_made | This key names a self-transfer trip that was not made. Price again and book with a new key. |
| 413 | — | Body over 1 MiB. |
| 421 | misdirected_request | Call https://api.norba.io. |
| 422 | airline_refused | The airline declined the request. Nothing was booked or charged. |
| 422 | extra_not_priced | Seat or extra not in the seat map or service list. Fetch it first. |
| 422 | extras_not_supported | Seats or extras sent with a self-transfer trip. Add them to each order once booked. |
| 422 | flights_unavailable | The flights are no longer available. Pick another offer. |
| 422 | hold_expired | The unpaid hold has expired. Search again. |
| 422 | no_alternatives | No fares found for the requested change. |
| 422 | offer_expired | The offer has expired. Search and price again. |
| 422 | partial_cancel_unavailable | These flights cannot be cancelled alone. Cancel or change the whole order. |
| 422 | passenger_name_invalid | A first or last name has no Latin letter. Send it in Latin script, as on the passport. |
| 422 | — | `payment.authentication` is not supported on this airline. Send the payment without it. |
| 429 | allowance_burst | Too many free requests at once. Wait, or add a card. |
| 429 | *_limit_exceeded | daily_search_, monthly_order_ or monthly_search_limit_exceeded: a ceiling agreed for your account. `limit` gives it. |
| 429 | — | Too many requests with an invalid key from one address. Fix the key. |
| 500 | — | Norba-side failure. Retry; quote the X-Request-Id if it persists. |
| 501 | refund_not_supported | This airline's ticketed refunds are not available through the API. Ask the airline. |
| 501 | — | Seat map or service list qualifiers not supported on this airline. Send without them. |
| 502 | *_outcome_unknown | The write reached the airline but its answer was lost. Do not resend; check GET /v1/orders. |
| 502 | — | The airline could not answer. Safe to retry. |
| 503 | airline_unreachable | Nothing reached the airline. Retry after Retry-After, same key. |
| 503 | coming_soon | Booking is not enabled in this environment yet. Reads work. |
| 503 | ledger_unavailable, order_unreadable | Temporarily unavailable; nothing was sent. Retry after Retry-After, same key. |
| 503 | rls_unavailable | Temporarily unavailable. Retry after Retry-After. |
| 503 | service_restarting | The service is restarting. Retry after Retry-After. |
| 503 | — | Airline not available in this key's environment, or a temporary key check failure. |
Safe to retry: 429 and 503 after Retry-After, 500, and 502 without a code. Never resend a request answered *_outcome_unknown. Idempotency keys.
Aviation Data errors
/v1/aviation/* and /v1/reference/* answer `{ data: null, meta, errors: [{ code, message }] }`. Key and billing refusals keep the plain `{ error }` shape.
| HTTP | code | What to do |
|---|---|---|
| 400 | invalid_airline | airline is not a 2-character IATA code. |
| 400 | invalid_page | page is above 1000. A page past the data is an empty list. |
| 400 | invalid_route | origin and destination must both be 3-letter IATA codes. |
| 404 | not_found | No record with that id. |
| 500 | db_error | Retry. |
| 503 | db_not_configured | Retry later. |
Rate limits
Requests with a valid key are not rate-limited. A 429 comes only from a volume ceiling agreed for your account, the free-allowance burst guard, or repeated invalid keys from one address. Wait for Retry-After.
Billing refusals and the free allowance: Billing & Payments · Look-to-book: Pricing.