Errors & acknowledgements
NDC reports problems in-band as XML, not (only) via HTTP status codes. There are three related constructs.
Error, Warning, Acknowledgement
Error— the request could not be fulfilled. Carries a type code, an owner, and a human-readable description. May appear inside an otherwise-typed response (e.g. anAirShoppingRScontaining only anError) or inside anIATA_Acknowledgement.Warning— the request succeeded but something needs attention (e.g. a fare rule caveat). Non-fatal; the response still carries results.IATA_Acknowledgement— the generic envelope used to acknowledge receipt or to return errors/warnings when a typed response is not applicable (common for notification messages).
What a failure looks like on the wire
A failed request is answered with the message's own response (OrderViewRS for an
OrderCreateRQ, AirShoppingRS for an AirShoppingRQ, …) carrying one or more Error
elements instead of a Response — the schema's Error | Response choice. The HTTP
status mirrors the error, and the X-NDC-Error header repeats the stable code so a
client can branch without parsing XML:
<IATA_OfferPriceRS xmlns="http://www.iata.org/IATA/2015/EASD/00/IATA_OffersAndOrdersMessage">
<Error>
<Code>490</Code> <!-- PADIS 9321 application error code -->
<DescText>The offer has expired or is no longer available — shop again.</DescText>
<LangCode>en</LangCode>
<StatusText>NotProcessed</StatusText>
<TypeCode>offer_stale</TypeCode> <!-- stable Retailaer code (table below) -->
</Error>
<PayloadAttributes>
<CorrelationID>…your CorrelationID…</CorrelationID>
<TrxID>…your TrxID…</TrxID>
<VersionNumber>24.4</VersionNumber>
</PayloadAttributes>
</IATA_OfferPriceRS>
Codeis from IATA's PADIS code list 9321 ("Application error, coded"), as the 24.4 schema prescribes for this element.TypeCodeis the stable Retailaer code — branch on this one. The schema leavesTypeCode"bilaterally agreed"; the table below is that agreement.PayloadAttributeson every response (success or failure) echoes yourCorrelationIDandTrxIDand statesVersionNumber24.4.
Messages with no typed response (notifications, an unknown message name) answer with an
IATA_Acknowledgement whose
Notification carries StatusCode FAILED and the stable code in WarningCode.
Error codes
TypeCode | HTTP | PADIS 9321 Code | Meaning | What to do |
|---|---|---|---|---|
invalid_credentials | 401 | 368 | Missing or invalid credentials. | Fetch a fresh token / check the API key. Do not retry blindly. |
insufficient_scope | 403 | 368 | The credentials are not authorised for this message. | Ask the airline to grant the scope this message needs. |
seller_not_authorised | 403 | 368 | These credentials may not sell as the seller named in the distribution chain. | Name your own agency as Seller; an aggregator names an agency it was granted. |
distribution_chain_invalid | 400 | 914 | The distribution chain is invalid for this airline. | The Carrier link must name this airline. |
unknown_message | 404 | 915 | Unknown NDC message. | Check the message name in the path. |
response_only_message | 405 | 915 | This is a response message; it cannot be sent as a request. | Send the paired request message instead. |
message_name_mismatch | 400 | 914 | The IATA-Message-Name header does not match the request path. | Make IATA-Message-Name match the path. |
invalid_xml | 400 | 903 | The request is not well-formed NDC XML. | Fix the payload; validate it against the 24.4 XSD. |
doctype_forbidden | 400 | 903 | DOCTYPE declarations are not accepted. | Remove the DOCTYPE declaration. |
pan_not_accepted | 400 | 708 | Card numbers and security codes are not accepted: pay with a PSP token (TokenizedCardID). | Tokenise the card with your PSP and send TokenizedCardID; never send CardNumber or CardSecurityCode. |
not_implemented | 501 | 915 | This message is not implemented by this airline yet. | See the capability badge on the message page. |
capability_not_entitled | 404 | 915 | This airline does not offer this message. | Use only the messages this airline's documentation lists. |
capability_servicing_only | 409 | 915 | This airline takes no new sales over NDC; orders already made can still be serviced. | Retrieve, change, cancel and settle existing orders as before; make new bookings through another channel. |
internal_error | 500 | 911 | Unable to process - system error. | Retry idempotently (same CorrelationID / TrxID) with backoff. |
upstream_unavailable | 502 | 304 | A system this request depends on is temporarily unavailable. | Retry idempotently with backoff. |
missing_offer_id | 400 | 912 | The request names no offer. | Send the OfferRefID / OfferID you were given. |
missing_order_id | 400 | 912 | The request names no order. | Send the OrderID. |
invalid_id | 400 | 914 | An id in the request was not issued by this airline or has been altered. | Use ids exactly as this API issued them. |
validation_failed | 422 | 914 | The request data was rejected. | Correct the request data named in DescText. |
shopping_criteria_unsupported | 422 | 915 | These shopping criteria are not supported (use FlightRequestOriginDestinationsCriteria). | Shop by origin-destination criteria; affinity and specific-OD shopping are not offered. |
identity_document_type_unknown | 422 | 718 | The identity document type is not an identity-document type code of IATA PADIS code list 7365. | Send IdentityDoc/IdentityDocTypeCode from PADIS 7365 (PT passport, IP passport card, 709 national ID, VI visa, …). Travel documents are stored in full, so a type this airline cannot name is refused rather than guessed. |
identity_document_country_invalid | 422 | 109 | An identity document country code is not an ISO 3166-1 alpha-2 country code. | Send CitizenshipCountryCode / IssuingCountryCode / ResidenceCountryCode as ISO 3166-1 alpha-2 (GB, SE). |
identity_document_invalid | 422 | 914 | The identity document was rejected: it is missing its number or the holder surname, a date or gender code is malformed, or a value is longer than the document schema allows. | IdentityDocID and Surname are mandatory; dates are YYYY-MM-DD; GenderCode is F, M, U or X (ICAO Doc 9303). Lengths follow IdentityDocType: names 64 (up to 5 GivenName, 3 MiddleName), SuffixName / TitleName 16, BirthplaceText 200, IdentityDocID 60. |
identity_document_not_updatable | 422 | 915 | Travel documents are taken with the order (OrderCreateRQ) and cannot be added or changed on a booked order over NDC; ask the airline to update them. | Send Pax/IdentityDoc in OrderCreateRQ. It is refused rather than ignored on a change message, so you are never left believing the airline holds a document it does not. |
offer_not_found | 404 | 490 | Unable to retrieve offer. | Shop again. |
offer_stale | 409 | 490 | The offer has expired or is no longer available — shop again. | Shop again (or re-price) to get a bindable offer. |
fare_not_found | 404 | 913 | No fare of the named offer matches this fare reference. | In OrderRulesRQ FareRef, send this airline's code, the OfferID the fare was quoted in as FareRefText, and that offer's FareBasisCode with the origin (Dep) and destination (Arrival) of its outbound journey. |
service_not_found | 422 | 914 | The service is not offered with this offer. | Take service ids from this offer's ServiceListRS. |
seat_not_found | 422 | 914 | The seat does not exist on this flight. | Take seats from this offer's SeatAvailabilityRS. |
seat_unavailable | 409 | 911 | The seat is no longer available — choose another seat. | Re-read the seat map and pick a free seat. |
seat_map_unavailable | 422 | 915 | This offer has no flight with a seat map. | Rail legs have no seat map; seats are assigned with the ticket. |
currency_mismatch | 422 | 914 | The selection is priced in more than one currency. | Price services and seats from the same offer and currency. |
order_not_ticketed | 422 | 76H | Extras are sold once the order is ticketed. | Pay the order (and name every passenger) first; then list its extras. |
offers_unavailable | 503 | 496 | No offers could be produced right now. | Retry shortly; nothing is sold on a degraded shop. |
payment_declined | 402 | 466 | The payment was declined; nothing was charged. | Ask for another card or form of payment and retry with a new TrxID. |
authentication_required | 402 | 466 | The card needs 3-D Secure: authenticate the payer and send the results. | Run 3-D Secure 2 and send the results in PaymentCard/SecurePaymentVersion2. |
payment_amount_mismatch | 422 | 466 | The payments do not add up to the order total in its currency. | Make the PaymentProcessingDetails amounts add up to the priced total. |
payment_token_required | 422 | 466 | A card is paid with a PSP token (TokenizedCardID). | Tokenise the card with your PSP; send TokenizedCardID. |
payment_method_unsupported | 422 | 915 | This form of payment is not accepted over NDC yet. | Pay by card token (see the capability badge on OrderCreate). |
payment_unavailable | 503 | 304 | The payment provider is temporarily unavailable; nothing was charged. | Retry idempotently with backoff. |
voucher_invalid | 422 | 466 | The voucher cannot be used. | Check the voucher's validity and currency; pay another way. |
voucher_insufficient | 422 | 466 | The voucher holds less than the payment asks for. | Pay the rest with another form of payment. |
settlement_not_available | 422 | 466 | The seller has no active settlement account for this form of payment. | Use the form of payment of your settlement account (CA BSP, DP ARC, MS direct bill). |
credit_limit_exceeded | 402 | 466 | The payment is more than the seller's remaining settlement credit. | Pay part by card or voucher, or ask the airline to raise the limit. |
sale_not_recorded | 503 | 304 | The order's sale could not be put on the agency's books just now, so a settlement-plan charge cannot be recorded against it; nothing was charged — retry shortly, or pay by card or voucher. | Retry idempotently with backoff, or pay the change by card or voucher. |
commission_rule_undefined | 422 | 466 | The seller's commission agreement states no rule for a settlement-plan charge made after the sale; pay this change by card or voucher. | Pay the change by card or voucher (a flat-amount agreement states no rule for a charge made after the sale). |
commission_currency_mismatch | 422 | 466 | The seller's tiered commission agreement is stated in another currency than this change, so its commission cannot be priced; pay this change by card or voucher. | Pay the change by card or voucher, or ask the airline to state the tiers in the order's currency. |
loyalty_account_invalid | 422 | 753 | The loyalty account is not a member of this airline's programme who can redeem points. | Check the member's account number (LoyaltyProgramAccount/AccountNumber); only this airline's programme is accepted. |
loyalty_certificate_invalid | 422 | 706 | The redemption certificate is not valid for this loyalty account and payment. | Ask the member for a current redemption certificate (they issue it in their loyalty account) that covers the points; send it as LoyaltyRedemption/CertificateNumber. |
loyalty_points_insufficient | 422 | 423 | The loyalty account holds fewer points than this payment needs. | Pay less with points and the rest another way. |
pay_later_unavailable | 422 | 76H | This order cannot be held unpaid; pay it now. | Send PaymentFunctions with the OrderCreateRQ. |
payment_time_limit_expired | 409 | 918 | The payment time limit has passed; the order can no longer be paid. | Shop and book again. |
order_already_paid | 409 | 902 | The order is already paid. | Retrieve the order; nothing more is owed. |
order_not_payable | 409 | 76H | The order is not awaiting payment. | Retrieve the order to see its status. |
order_not_found | 404 | 913 | Order not found. | Check the OrderID (orders of other sellers are not visible). |
invalid_cursor | 400 | 914 | The order list cursor was not issued by this airline for this list. | Start again without a cursor, then follow each next-cursor: remark. |
order_conflict | 409 | 495 | Order not created. | Re-price and retry with a new TrxID. |
idempotency_conflict | 409 | 902 | This transaction id was already used for a different request. | Use a fresh TrxID for a different request. |
member_pricing_not_eligible | 422 | 753 | The offer was priced for loyalty members: every fare-paying passenger must carry the loyalty account it was priced for, in the account holder's name. Shop again without the accounts for a guest price. | Send each fare-paying passenger with the same LoyaltyProgramAccount/AccountNumber as in AirShoppingRQ and the account holder's Individual name — or re-shop without accounts. Nothing was booked or charged. |
change_not_eligible | 422 | 76H | This change is not available for the order. | Retrieve the order rules (OrderRulesRQ) and pick an eligible change. |
change_not_supported | 422 | 915 | This kind of change is not supported over NDC yet. | See the capability badge; use the airline channel meanwhile. |
change_params_required | 422 | 912 | The change request is missing the data it needs. | Add the missing change data. |
not_eligible | 422 | 76H | The order is not eligible for this action. | The order state does not allow this action. |
invalid_params | 422 | 914 | The change parameters were rejected. | Correct the change parameters. |
unknown_action | 422 | 915 | Unknown servicing action. | Use a documented change. |
channel_not_allowed | 403 | 368 | This action is not available on this channel. | This action is only available through the airline. |
quote_not_found | 404 | 490 | The reshop offer was not found. | Reshop the order. |
quote_expired | 409 | 499 | The reshop offer has expired — reshop the order. | Reshop the order — reshop offers live 15 minutes. |
quote_committed | 409 | 902 | The reshop offer was already accepted. | Retrieve the order; the change is already applied. |
stale_version | 409 | 499 | The order changed since it was reshopped — reshop the order. | Retrieve the order, then reshop. |
pending_approval | 409 | 76H | The change is waiting for approval. | Wait for the approval outcome. |
execute_failed | 502 | 911 | The change could not be completed. | Retrieve the order before retrying. |
rules_unavailable | 503 | 304 | Pricing rules are temporarily unavailable. | Retry shortly — the airline never defaults to a free change. |
payment_required | 402 | 466 | This change costs money: pay the amount due in the same OrderChangeRQ (PaymentFunctions). | Send PaymentFunctions for the amount due the reshop offer states (DueToAirlineAmount). |
order_unpaid | 409 | 76H | The order is unpaid: pay it, or release it with CancelUnpaidOrder. | Pay the order (OrderChangeRQ PaymentFunctions) before changing it, or cancel it unpaid. |
order_not_unpaid | 409 | 76H | The order is paid: cancel it through a reshop. | Reshop the cancel (OrderReshopRQ CancelOrderRef) and accept its offer. |
passenger_not_found | 422 | 914 | That passenger is not on this order. | Use a PaxID from the order (OrderRetrieveRQ). |
past_cutoff | 422 | 76H | Too close to departure for this change. | The order rules (OrderRulesRQ) state each cutoff; contact the airline. |
passenger_checked_in | 422 | 76H | A passenger has checked in; the order can no longer be cancelled. | Contact the airline. |
requires_all_passengers | 422 | 76H | This change cannot be made for only some of the passengers. | Change the whole party, or contact the airline. |
bound_not_separable | 422 | 76H | This trip has no direction that can be changed or cancelled on its own. | Change or cancel the whole trip. |
fare_not_changeable | 422 | 76H | The fare is not changeable: its flights and dates cannot be changed. | The order rules (OrderRulesRQ) state each fare's conditions; cancel it (by its refund terms) or contact the airline. |
attempts_exhausted | 422 | 76H | The free name corrections for this passenger are used up. | Contact the airline for further name changes. |
assisted_channel_only | 422 | 76H | This change needs the airline's contact centre. | Contact the airline. |
order_not_active | 422 | 76H | The order is no longer active. | Retrieve the order to see its status. |
offer_expired | 409 | 499 | The replacement flight offer has expired — reshop the order. | Reshop the order for current flights. |
already_delivered | 422 | 76H | The partner's product has already been delivered, so it cannot be cancelled for a refund. | The item stays on the order; cancel the other items. |
supplier_terms_forbid | 422 | 76H | The supplier's terms do not allow this item to be cancelled for a refund. | The item stays on the order; cancel the other items. |
partner_pending | 409 | 304 | A partner's booking is still being confirmed — try again shortly. | Retry the reshop later. |
marketplace_unavailable | 503 | 304 | The partner-product system is temporarily unavailable — try again shortly. | Retry later; nothing was changed. |
Settlement (PaymentClearance)
The 2022.1 PaymentClearance messages carry IATA's clearance error codes (CEC) in Code, not PADIS 9321. A clearance the Clearance Manager refuses is not an error: it comes back StatusCode RJCTD with a FailureReasonCode (CFRC — TRNNOUN already cleared, CLIDDUP ClearanceID reused, PARPAEN no SwO terms for the payment, SNDNVLD not the caller's).
TypeCode | HTTP | Code | Meaning | What to do |
|---|---|---|---|---|
clearance_count_mismatch | 400 | CLRNCNT | Message is rejected due to incorrect Clearance Count value. | Set ClearanceCount to the number of Clearance elements. |
clearance_amount_mismatch | 422 | MSGRJCT | A clearance's amount matches no uncleared settlement payment of its commitment; nothing was cleared. | Clear each settlement payment for exactly its amount (DescText lists what is uncleared). |
clearance_not_found | 404 | MSGRJCT | No clearance of this seller matches the request. | Check the ClearanceID / CommitmentID or widen the criteria. |
clearing_not_found | 404 | MSGRJCT | No clearing of this seller matches the request. | Check the ClearingID or widen the date window. |
Warning codes
Warnings never fail a request. Each names what the result depends on.
TypeCode | Meaning |
|---|---|
simulated_inventory | Inventory for this response is simulated (sandbox supply): prices and availability are not bookable with a real carrier. |
simulated_payment | Payment was processed by a simulated payment service provider: no real funds moved. |
simulated_settlement | Settlement and clearance are simulated: no real BSP/ARC or clearing-house exchange took place. |
simulated_operations | Operational status (check-in, boarding, flown) comes from a simulated operations clock. |
promotion_invalid | The promotion code is not valid; offers are shown without it. |
promotion_not_applicable | The promotion code is valid but does not apply to these offers. |
promotion_unavailable | Promotions could not be checked right now; offers are shown without the promotion code. |
pricing_degraded | Some prices were converted with an exchange rate older than 24 hours and may change when re-priced. |
price_adjustments_unavailable | Promotions and surcharges could not be applied right now; offers are priced without them and may change when re-shopped. |
loyalty_pricing_unavailable | The loyalty accounts could not be checked right now; offers are priced as for travellers without them. |
member_pricing_applied | Offers are priced for the loyalty members named: OrderCreate must carry the same accounts, each on the traveller whose name is the account holder's, or the order is refused (member_pricing_not_eligible). |
member_pricing_not_applied | Member pricing applies only when every fare-paying passenger carries this airline's loyalty account with the account holder's name; offers are priced as for travellers without accounts. |
price_adjustment_currency_not_applied | A price adjustment defined in another currency than these offers was not applied. |
program_criteria_not_applied | Only ProgramCriteria of programmes owned by this airline, with a ProgamContract/ContractID, are applied; the others were not. |
program_account_not_applied | ProgramCriteria/ProgramAccount is not used for pricing: the contract is priced for the authenticated seller, and loyalty accounts go on the passenger (LoyaltyProgramAccount). |
transport_unavailable | Ground transport timed to this flight could not be fully shopped right now; the airline services and any rides found are listed. |
services_unavailable | The à-la-carte services of some offers could not be listed right now; those offers are shown without them — ask ServiceListRQ for them. |
services_limited | À-la-carte services are listed for the first offers of this response only; ask ServiceListRQ for the services of the others. |
services_refused | The airline could not list the à-la-carte services of some offers (not a temporary outage — ServiceListRQ for them will be refused too); those offers are shown without them. |
service_criteria_partly_applied | An excluding ServiceCriteria was applied to the bags a fare brand includes as structured data; anything else a brand bundles (its benefit text, a bag without a stated count or classification) was not filtered. |
price_changed | The offer price changed since it was shopped; the new price is shown. |
identity_document_masked | The travel document is stored in full as sensitive personal data — encrypted at rest and read back only by airline staff, under audit; every NDC response shows its number masked. |
identity_document_not_shown | A travel document on this order is held under a document type this airline cannot name, so it is not listed: the order has a document even though none is shown. Ask the airline. |
origin_destination_without_offers | No offers were found for one of the requested origin-destinations. |
order_divided | Some passengers left this order: they are on the divided order shown beside it (OriginalOrderID names this one). |
travel_credit_issued | The refund was kept as travel credit: the voucher is in PaymentFunctions; its code is shown in this response only. |
nonstandard_cancel_placement | The cancel was read from outside Request/ChangeOrderChoice; send CancelUnpaidOrder or AcceptCancelledOffer there. |
partner_products_unavailable | Partner products could not be listed right now; only the airline's own services are shown. |
fare_conditions_supplier | Some offers carry the supplier's fare conditions: the airline's fare-brand policy could not be read. OrderRulesRQ (FareRef) states the terms that apply once booked. |
content_language_fallback | Some content is not available in the requested language and is shown in English. DescText names what: the fare-brand names and benefits and station names the airline has not translated into that language (or, when translations could not be read, all of them). Processing/LangUsage lists the languages the content is in — the requested one first, then en. |
Simulated supply
Parts of the supply behind this API are simulated today — flight inventory, the card
processor, settlement and the operations clock. The contract you integrate against is
the production contract; only the supplier behind it is simulated. Whenever a response
depends on simulated supply it carries one of the simulated_* warnings above, driven
by the airline's own systems (never assumed by the gateway). Treat them as "sandbox
data" markers: they disappear as real suppliers are connected, with no change to the
messages you send.
Every response that rests on simulated supply also names it in the X-NDC-Simulated
HTTP header (inventory, payment, settlement, operations, comma-separated). The
2022.1 PaymentClearance messages have no Warning element, so for them — clearance is
cleared by a simulated Clearance Manager today — the header is the only marker.
Handling guidance
| Situation | Do |
|---|---|
HTTP 401 / 403 | Refresh the OAuth token / check the API key. Don't retry blindly. |
HTTP 429 | Back off exponentially; honour Retry-After. |
HTTP 5xx | Retry idempotently (same correlation id) with backoff. |
200 with an Error body | Inspect the type code — usually a business error (expired offer, sold-out fare). Re-shop or re-price rather than retrying verbatim. |
Warning present | Surface to the user/agent; the result is still valid. |
Offers are time-bounded. If shopping → pricing → ordering takes too long you'll see an
offer/price error. Re-run OfferPriceRQ (or re-shop) to obtain a fresh, bindable offer.