Skip to content
ApiqDevelopers
API v1.64.0Open console

Create order

POST/v1/orders
Idempotency-Key requiredAccepts X-Api-Key · oauthClientCredentials · bearer

The one booking write

Replaces /v1/book, /v1/bookings (write) and /v1/taxi/book.Show moreReplaces /v1/book, /v1/bookings (write) and /v1/taxi/book. Book never re-quotes — price movement at commit is 409 PRICE_CHANGED, never a silent swap. Ambiguous supplier outcome is 202 AMBIGUOUS_RESULT with the order in PENDING_RECONCILIATION. While the tenant is SUSPENDED a new order is refused 403 TENANT_SUSPENDED, with one exception: a same-key, same-body retry of an order request this tenant completed before the suspension is served its stored answer (Idempotency-Replayed true) — nothing new is booked. A fresh, expired or still in-flight key is 403 TENANT_SUSPENDED, a different body under the key 409 IDEMPOTENCY_CONFLICT. Payment check: when payments are served and message.intent.payment.paymentRef names an intent, the platform checks it covers THIS order before the write-ahead row and before any supplier byte. Anything but a funded intent for this tenant, this repriceRef and this total is 409 CONFLICT with details.field message.intent.payment.paymentRef and details.reason one of NOT_FOUND (unknown ref, or another tenant's — the same bytes for both), OTHER_QUOTE (the intent was created from a different repriceRef), AMOUNT_MISMATCH (details.detail AMOUNT or CURRENCY), WRONG_STATE (details.detail is the intent's state: CREATED, REQUIRES_ACTION, CANCELED, FAILED, or PENDING_RECONCILIATION while a payment operation is unresolved), REFUNDED, AUTH_EXPIRED (an uncaptured authorization past its validity), ALREADY_USED (another order already booked on this payment; that order is never named). Nothing was sent to a supplier and the Idempotency-Key is released, so the client fixes the payment and retries. retryable is true only for WRONG_STATE with detail PENDING_RECONCILIATION, and false for every other reason. A second order on a repriceRef that is already spent is 409 CONFLICT with details.field message.intent.repriceRef and details.reason REPRICE_REF_SPENT; when a payment is attached the payment check answers first. A same-key retry of an order that already booked is answered from its stored result without re-checking. Two-step round trip: an order on an OUTBOUND_FIRST FLT offer whose journey is not complete (extension.air.journey.complete false) is 409 CONFLICT with details.reason JOURNEY_INCOMPLETE and details.nextSliceIndex, not retryable; nothing is sent to a supplier and the Idempotency-Key is released. Choose the remaining slices through POST /v1/flights/returns and reprice first. Card-secured slots: message.intent.payment.paymentMethod carries a payment-method token the client obtained from Spreedly; the platform hands the supplier the token and never a card number or security code, and none can be sent: PaymentMethodToken has no such field and a card-number-shaped value anywhere is refused (INSTRUMENT_DATA_REFUSED). Single use, retried with the same Idempotency-Key. Human sessions and system keys are exempt; an ai key and every service token are the AI channel. Wallet: with message.intent.payment.mode WALLET the total is held on the tenant's wallet inside the write-ahead flow before any supplier byte, settled at ticketing or confirmation and released when the supplier fails; an ambiguous outcome keeps the hold until reconciliation, never debiting twice. Too little available is 402 PAYMENT_FAILED with details.reason WALLET_INSUFFICIENT and details.available (Money), and no supplier is called (sandbox scenario Test wallet_insufficient). A tier cap is 403 PERMISSION_DENIED details.reason TIER_CAP_REACHED with details.cap and details.resetAt. TIER_CAP_REACHED is un-reserved. An order of a LIVE_CAPPED tenant that is not a sandbox twin (on any rung) whose total would take today's spend past the daily cap is 403 PERMISSION_DENIED details.reason TIER_CAP_REACHED with details.cap, details.usedToday (Money) and details.resetAt, checked before any payment is taken, any wallet hold is placed or any supplier byte is sent; nothing is written. The cap currency is INR when the activation country is IN, else USD; usedToday counts the tenant's non-cancelled orders since 00:00 UTC, converted to the cap currency at each order's FX snapshot; resetAt is the next 00:00 UTC. The check is per order against today's confirmed and in-flight spend and is SOFT under concurrency: concurrent orders, each under the cap, may together exceed it by at most the orders in flight. An order whose currency the FX snapshot cannot convert to the cap currency is 500 INTERNAL details.reason FX_SNAPSHOT_UNAVAILABLE (the money verbs' existing sub-reason; retryable) and nothing is charged, held or sent. A sandbox twin's orders and tenants of other tiers are never capped. With payment.mode SAVED_METHOD while aikonic.payment-methods.enabled is off the order is 501 NOT_IMPLEMENTED details.reason PAYMENT_METHODS_UNAVAILABLE. payment.mode SAVED_METHOD with payment.methodId charges a saved payment method (POST /v1/payments/methods); a decline is 402 PAYMENT_FAILED details.reason CARD_DECLINED.

Headers

  • TeststringOptional
    Sandbox scenario simulation: price_changed | sold_out | ambiguous | hold_expired | payment_declined | supplier_timeout | partial_search | duplicate_order (case-insensitive).Show moreSandbox scenario simulation: price_changed | sold_out | ambiguous | hold_expired | payment_declined | supplier_timeout | partial_search | duplicate_order (case-insensitive). Read on every travel verb before the permission wall and idempotency; a scenario sent on a verb it does not apply to has no effect. Every simulated error carries details.simulated true and details.scenario. price_changed (reprice, hold, orders) → 409 PRICE_CHANGED; sold_out → 422 SOLD_OUT; hold_expired (orders) → 409 HOLD_EXPIRED; duplicate_order (orders) → 409 DUPLICATE_ORDER existingOrderRef MO-SIM-DUPLICATE; payment_declined (orders, POST /v1/payments/{paymentId}/confirm) → 402 PAYMENT_FAILED; supplier_timeout → 502 UPSTREAM_UNAVAILABLE; partial_search (search) → two SUPPLIER_DROPPED warnings; ambiguous (orders) → 202 PENDING_RECONCILIATION on an MO-SIM- ref. wallet_insufficient → 402 PAYMENT_FAILED details.reason WALLET_INSUFFICIENT.
  • Idempotency-KeystringRequired
    Mandatory on mutations: **48h TTL**; replay with same body-hash returns the original response with Idempotency-Replayed true; same key + different body is 409 IDEMPOTENCY_CONFLICT; in-flight duplicate…Show moreMandatory on mutations: **48h TTL**; replay with same body-hash returns the original response with Idempotency-Replayed true; same key + different body is 409 IDEMPOTENCY_CONFLICT; in-flight duplicate is 409 IDEMPOTENCY_IN_PROGRESS.
  • X-Approval-TokenstringOptional
    Redeemed by the payment verbs and by POST /v1/orders (orders.create), cancel (orders.cancel) and amend COMMIT (amend.commit).Show moreRedeemed by the payment verbs and by POST /v1/orders (orders.create), cancel (orders.cancel) and amend COMMIT (amend.commit). Human sessions and system keys are exempt. Single use, ~2 min TTL, bound to tenant + action + resource + amount; any drift fails closed and burns the token.

Request body

  • contextMondeeContextRequired
    Request context envelope. domain selects the product; URL carries the verb.
    13 child attributes
    • domainstringRequired
      Canonical code or alias per the domain registry; unknown = 400 UNKNOWN_DOMAIN.Show moreCanonical code or alias per the domain registry; unknown = 400 UNKNOWN_DOMAIN. APTSVC (airport services: meet and assist, porter, buggy, wheelchair, concierge bundles) is registered by this release beside FASTTRK. FNB (dining: restaurant reservations; aliases REST, DINING, RESTAURANT, RESTAURANTS; category DO, money model FREE, artifact CONF_NUMBER, served under the dining service key with base path /v1/dining) is registered since v1.7.0. GIFT (gift cards; category SUPPORT, money model MERCHANT, artifact VOUCHER, served under the gift-cards service key with base path /v1/gift-cards) is described from v1.31.0: until the backend seam change merges, domain GIFT answers 400 UNKNOWN_DOMAIN. AICONT (the Example Content experience-scraping service's operations; category DO, money model MERCHANT, artifact NONE, served under the aicont service key with base path /v1/aicont; a content supplier) has its typed intent from v1.39.0; it answers only where its supplier set is landed and ACTIVE. PARK (airport and cruise-port parking; aliases PRK and PARKING; category SUPPORT, money model MERCHANT, artifact CONF_NUMBER — the supplier's gate barcode is the order's BARCODE document — served under the parking service key with base path /v1/parking) has its typed intent and its verb book from v1.55.0.
    • actionstringOptional
      Mirrors the verb; optional (server sets from route)
    • enricharray of stringOptional
      Opt-in enrichment on shopping answers: EMISSIONS | RATINGS | AMENITIES | ROUTE.Show moreOpt-in enrichment on shopping answers: EMISSIONS | RATINGS | AMENITIES | ROUTE. Absent = the tenant's configured default. Decoration reads cache or the pre-warmed store only and never delays the verb.
    • session_idstringOptional
      Your own id for the user session the call belongs to.
    • transaction_idstringOptional
      Constant across one shop-to-book journey
    • currencystringOptional
      ISO-4217; absent = tenant default; blank/invalid = 400
    • localestringOptional
      The language and region for text in the answer, as a BCP 47 tag (for example en-US).
    • posstringOptional
      Point-of-sale market, orthogonal to tenant
    • clientReferencestringOptional
      Caller's own id; searchable; the reconciliation primitive
    • fareSourcePolicystringOptional
      BYOC tenants only; narrows, never widens, the configured strategy
      • DEFAULT
      • OWN_ONLY
      • MONDEE_ONLY
      • BLEND
    • includeUpstreambooleanOptionalDefault false
      Ask for the supplier's own answer, verbatim, beside what the platform read from it: Offer.upstream on every offer of a search, poll, detail or flight-returns answer, AirReturnOption.upstream on each…Show moreAsk for the supplier's own answer, verbatim, beside what the platform read from it: Offer.upstream on every offer of a search, poll, detail or flight-returns answer, AirReturnOption.upstream on each listed return, RepriceResponse.message.upstream and OrderItem.upstream. Served only where the deployment enables upstream pass-through; elsewhere a true value is 400 VALIDATION details.reason UPSTREAM_PASS_THROUGH_DISABLED, details.field context.includeUpstream, before any supplier call. Absent or false, nothing changes. The block is informational: offerRef, repriceRef and price stay the only handles and the only price of record.
    • selectionSelectionPreferencesOptional
      context.selection: the caller's offer-selection preferences for this search.Show morecontext.selection: the caller's offer-selection preferences for this search. Each field set here replaces the tenant's and the platform's for this search, within the caller's entitlements and the platform's ceilings, unless the tenant has locked request overrides. It never widens reach: a preferred supplier the caller may not reach is ignored with context.warnings[] SELECTION_PREFERENCE_IGNORED. Ignored where selection is off.
      4 child attributes
      • viewstringOptional
        SELECTED (one entry per item, alternatives under the winner) or ALL (the flat list, tagged)
        • SELECTED
        • ALL
      • objectivestringOptional
        How the winner of an item is picked. CHEAPEST is the lowest comparison total; REFUNDABLE_FIRST the lowest total among offers free to cancel now (else CHEAPEST); PREFERRED_SUPPLIERS the first of…Show moreHow the winner of an item is picked. CHEAPEST is the lowest comparison total; REFUNDABLE_FIRST the lowest total among offers free to cancel now (else CHEAPEST); PREFERRED_SUPPLIERS the first of preferSuppliers with an offer inside the tenant's preference band (else CHEAPEST); PLATFORM_DEFAULT defers to the tenant and platform policies. Any other value is 400 VALIDATION details.field context.selection.objective.
        • CHEAPEST
        • REFUNDABLE_FIRST
        • PREFERRED_SUPPLIERS
        • PLATFORM_DEFAULT
      • preferSuppliersarray of stringOptional
        Supplier codes as in fareSource.supplier, most preferred first (PREFERRED_SUPPLIERS)
      • excludeSuppliersarray of stringOptional
        Supplier codes whose offers this search does not show; narrows only
    • onBehalfOfOnBehalfOfOptional
      Who a desk or agent books FOR: stamped into the audit actor and the clientReference lineage of the order.Show moreWho a desk or agent books FOR: stamped into the audit actor and the clientReference lineage of the order. Send customerId (a customer or traveller id the tenant knows) or traveler (a free-text identity), or both. Attribution only: it grants nothing, and the credential's own actor is still what authorises the call. Audit mapping: the audit actor.onBehalfOf (a string) is customerId when present, otherwise "traveler:<redacted-hash>" (a stable hash of traveler, never the text).
      2 child attributes
      • customerIdstringOptional
        A customer or traveller id your own system knows.
      • travelerstringOptional
        Free-text traveller identity when there is no customer id.Show moreFree-text traveller identity when there is no customer id. Personal data: it is logged redacted, never in clear. A card number in it is 400 VALIDATION details.reason INSTRUMENT_DATA_REFUSED.
  • messageobjectRequired
    1 child attribute
    • intentobjectRequired
      The booking intent. Required as built: travelers[] and one of repriceRef or holdRef (backend IntentSchemaRegistry).Show moreThe booking intent. Required as built: travelers[] and one of repriceRef or holdRef (backend IntentSchemaRegistry). payment.mode: PSP_TOKEN | CREDIT_LINE | PAY_LATER | SUPPLIER_HOSTED | NONE | PAYMENT_METHOD_TOKEN | OPENTABLE_SMS_LINK | WALLET | SAVED_METHOD. WALLET pays from the tenant's prepaid wallet in the order's currency: no paymentRef; the platform holds the total at book (WALLET_HOLD), settles it at ticketing or confirmation and releases it when the booking fails. Too little available is 402 PAYMENT_FAILED details.reason WALLET_INSUFFICIENT with details.available, and nothing is sent to a supplier. A card-secured dining slot (DiningExtension.creditCardRequired) needs payment.paymentMethod, a Spreedly payment-method token: without it the order is 400 VALIDATION details.reason PAYMENT_METHOD_REQUIRED and nothing is sent. A supplier that demands 3-D Secure refuses the order with 400 VALIDATION details.reason SCA_REQUIRED (nothing booked); the client retries with paymentMethod.threeDs. An In-House slot (cardCapture OPENTABLE_SMS_LINK) takes no token: Example Dining texts the diner, so requiredInfoAnswers.smsOptIn must be true. ENCRYPTED_CARD pays a supplier that charges the card itself (a flight supplier: PaymentType CC, ticketed at book) with a card the caller sealed to GET /v1/payments/card-key: payment.encryptedCard {kid, jwe}, and the lead traveller's billingAddress as the card's billing address. It excludes paymentRef, paymentMethod and checkoutSignature (400 VALIDATION details.reason PAYMENT_MODE_CONFLICT). Refused before the approval grant is redeemed and before anything is written or sent: an envelope that does not open (CARD_ENVELOPE_INVALID), an unusable card (CARD_VALIDATION_FAILED, details.field names the field, never the value), a card not on the rung's test-card list (CARD_NOT_A_TEST_CARD), a missing billing address (BILLING_ADDRESS_REQUIRED), an intent naming the supplier account (Customer, UserInfo, customerId, dkNumber, consolidatorId: CUSTOMER_NOT_CALLER_SUPPLIED), and a supplier that takes no card (501 NOT_IMPLEMENTED CARD_PAYMENT_NOT_SUPPORTED). The card is opened in memory for the one booking call and stored, logged or echoed nowhere. A retry must resend the identical bytes: a re-sealed card under the same Idempotency-Key is 409 IDEMPOTENCY_CONFLICT. SAVED_METHOD charges a method the tenant saved at POST /v1/payments/methods: payment.methodId names it (absent, the default method); the platform charges its stored PSP token through the payments seam inside the write-ahead flow, before any supplier byte, and no card data travels in the order. An unknown or another tenant's methodId is 400 VALIDATION details.field message.intent.payment.methodId; a decline is 402 PAYMENT_FAILED details.reason CARD_DECLINED and nothing is sent to a supplier. SAVED_METHOD excludes paymentRef, paymentMethod and encryptedCard: any of them with it is 400 VALIDATION details.reason PAYMENT_MODE_CONFLICT (the ENCRYPTED_CARD rule), refused before anything is written or sent. WALLET and PSP_TOKEN are unchanged.
      12 child attributes
      • repriceRefstringOptional
      • holdRefstringOptional
      • clientReferencestringOptional
        The tenant's own reference, echoed on the order
      • travelersarray of TravelerOptional
        19 child attributes
        • typestringOptional
          ADT | CHD | INF (backend PassengerType); absent = ADT
        • ageintegerOptional
          Required when type is CHD or INF
        • titlestringOptional
        • firstNamestringRequired
        • middleNamestringOptional
        • lastNamestringRequired
        • emailstring · emailOptional
        • phoneNumberstringOptional
          E.164
        • dateOfBirthstring · dateOptional
        • genderstringOptional
          M | F | X | U; open string
        • nationalitystringOptional
        • residenceCountrystringOptional
          Country of residence (ISO 3166-1); what entry requirements and insurance rating key on
        • residenceAddressPostalAddressOptional
          One postal address
        • billingAddressPostalAddressOptional
          One postal address
        • shippingAddressPostalAddressOptional
          One postal address
        • documentsarray of TravelerDocumentOptional
        • loyaltyarray of objectOptional
        • answersobjectOptional
          PER_TRAVELER requiredInfo answers keyed by RequiredInfo.field; a FILE answer is an uploadId
        • leadbooleanOptional
          The lead booker (contact for the order); at most one traveller
      • requiredInfoAnswersobjectOptional
        PER_BOOKING answers keyed by RequiredInfo.field; a FILE answer is an uploadId.Show morePER_BOOKING answers keyed by RequiredInfo.field; a FILE answer is an uploadId. FNB diner answers live HERE, never on the traveller: phoneCountry (ISO 3166 alpha-2 of the diner's phone), phone (the diner's phone number as the restaurant should call it, national digits with phoneCountry, or E.164; absent = travelers[lead].phoneNumber), specialRequest (at most 75 characters; longer is 400 VALIDATION details.field message.intent.requiredInfoAnswers.specialRequest), restaurantEmailOptIn, opentableEmailOptIn and smsOptIn (booleans, absent = false: an opt-in is never defaulted to true; smsOptIn must be true for an OPENTABLE_SMS_LINK card capture).
      • consentsarray of ConsentOptional
        The consents this order was placed under; a RequiredInfo row with consentRequired is refused 400 VALIDATION details.reason CONSENT_REQUIRED without the matching entry
        7 child attributes
        • consentIdstringRequired
          HEALTH_DATA_SHARING | CROSS_BORDER_TRANSFER | THIRD_PARTY_HANDLER | INSURER_TERMS | MARKETING | SUPPLIER_TERMS; open string
        • versionstringRequired
        • acceptedAtstring · date-timeRequired
        • scopestringOptional
          ORDER | TRAVELER; absent = ORDER
        • travelerIndexintegerOptional
          When scope is TRAVELER
        • actorstringOptional
          Who accepted — TRAVELER, LEAD_BOOKER or AGENT (then onBehalfOf applies); open string
        • supplierstringOptional
          The supplier the consent is for, when supplier-specific
      • addOnsarray of AddOnSelectionOptional
        Selected add-ons from Offer.addOns[]; must match what the RP- priced
        4 child attributes
        • codestringRequired
        • quantityintegerOptional
        • choicestringOptional
          The chosen value for a choice-shaped add-on
        • meetSignTextstringOptional
          MEET_GREET only — the text on the sign
      • optionsarray of objectOptional
        Experience option choices (ExperienceOption) when not already fixed at reprice
        2 child attributes
        • optionIdstringRequired
        • valuestringRequired
      • taxQuoteSignaturestringOptional
        The tax-quote signature from the reprice, echoed so the order binds to it (an event-ticket supplier)
      • experienceSelectionDiningExperienceSelectionOptional
        Which experience and how many diners take each of its price options.Show moreWhich experience and how many diners take each of its price options. An experience with several prices (e.g. a tasting menu and a wine pairing, or adult and child) is priced per diner: the counts must add up to the party size. On search it narrows the offers to that experience; on reprice, hold and order it fixes the price split the offer is firmed, locked and booked with (Example Dining experience total and reservation `experience` block). A selection whose version is not the experience's current one is 409 CONFLICT details.reason EXPERIENCE_VERSION_CHANGED (re-read the detail); counts that do not add up to the party are 400 VALIDATION details.field message.intent.experienceSelection.
        3 child attributes
        • experienceIdinteger · int64Required
        • versionintegerOptional
          The experience version the client showed (DiningExperience.version)
        • pricesarray of objectRequired
      • paymentobjectOptional
        6 child attributes
        • modestringOptional
        • paymentRefstringOptional
          The paymentId of POST /v1/payments/intent, checked before any supplier byte
        • checkoutSignatureCheckoutSignatureOptional
          The signed triple a hosted checkout hands the browser.Show moreThe signed triple a hosted checkout hands the browser. The platform verifies it against ITS stored provider order id, then reads the provider — the triple is a hint, never the truth. Token references only; never instrument data.
        • paymentMethodPaymentMethodTokenOptional
          A card the CLIENT tokenised with the payment-method vault.Show moreA card the CLIENT tokenised with the payment-method vault. TOKEN ONLY: this object has no field for a card number, an expiry or a security code, and the platform never receives, stores or logs one. The client collects the card in the vault's own iframe (Spreedly iFrame or Express), receives a payment-method token and sends it here; the platform passes the token to the supplier (Example Dining's credit_card object) and keeps only provider, brand and last4 on the order. A digit run that looks like a card number in ANY field of the request is 400 VALIDATION details.reason INSTRUMENT_DATA_REFUSED (PanGuard), and the token itself is never echoed or logged. threeDs is sent only on the RETRY of an order the supplier refused with details.reason SCA_REQUIRED: the same token plus the result of the 3-D Secure challenge the client ran with the vault.
        • encryptedCardEncryptedCardEnvelopeOptional
          v1.36.0. A card sealed by the caller to the key of GET /v1/payments/card-key — byte-compatible with the upstream platform's contract A3.Show morev1.36.0. A card sealed by the caller to the key of GET /v1/payments/card-key — byte-compatible with the upstream platform's contract A3. jwe is a compact JWE (five base64url segments, no padding): protected header exactly {"alg":"RSA-OAEP-256","enc":"A256GCM","kid":"<kid>"}, a random 32-byte CEK wrapped with RSA-OAEP (SHA-256 hash and MGF1), AES-256-GCM content with a 96-bit IV and 128-bit tag, the protected-header segment's ASCII as AAD. The plaintext is UTF-8 JSON, all strings: {"number":"<13-19 digits>","cvv":"<3-4 digits>","expMonth":"MM","expYear":"YYYY","holderName":"<2-60>"}. kid here and in the header must match each other and a live key.
        • methodIdstringOptional
          with mode SAVED_METHOD, the saved payment method to charge (SavedPaymentMethod.id); absent, the tenant's default method.
      • ancillariesarray of objectOptional

Responses

  • 201Order created; state per DOMAIN-CONTRACTS C1 FSM (or PENDING_SUPPLIER for on-request)OrderResponse
  • 202
    AMBIGUOUS_RESULT: book timed out upstream; order persisted PENDING_RECONCILIATION; poll the order or await order.state_changed.Show moreAMBIGUOUS_RESULT: book timed out upstream; order persisted PENDING_RECONCILIATION; poll the order or await order.state_changed. Never re-book on a different key.
    OrderResponse
  • 307
    HOME_REGION_REDIRECT: this tenant's writer region is not the region that received the request.Show moreHOME_REGION_REDIRECT: this tenant's writer region is not the region that received the request. Nothing was executed at this region. There is no body. Clients MUST NOT auto-follow this redirect: a cross-origin redirect makes most HTTP stacks drop the Authorization header, and some drop Location altogether. The client MUST re-send the same request (method and body unchanged) to Location WITH its credentials and the SAME Idempotency-Key. Follow-up sends are deduplicated on the Idempotency-Key in the home region.
  • 400
    VALIDATION or UNKNOWN_DOMAIN. A message.intent.payment.paymentRef shaped like a card number is VALIDATION with details.reason INSTRUMENT_DATA_REFUSED and the digits are never echoed: card data never…Show moreVALIDATION or UNKNOWN_DOMAIN. A message.intent.payment.paymentRef shaped like a card number is VALIDATION with details.reason INSTRUMENT_DATA_REFUSED and the digits are never echoed: card data never passes through the platform. Dining: details.reason PAYMENT_METHOD_REQUIRED (a card-secured slot without a token) and SCA_REQUIRED (the supplier demands 3-D Secure; nothing was booked; details.subCode, details.intent, details.paymentMethod and details.retryWith say how to retry: run the challenge, then resend with paymentMethod.threeDs and a NEW Idempotency-Key). payment.mode SAVED_METHOD with paymentRef, paymentMethod or encryptedCard is VALIDATION details.reason PAYMENT_MODE_CONFLICT.
    ApiErrorResponse
  • 401
    UNAUTHENTICATED — missing or expired token.Show moreUNAUTHENTICATED — missing or expired token. Declared on every operation because `security` is declared globally at the document root: every route is authenticated, so every route can answer 401.
    ApiErrorResponse
  • 402
    PAYMENT_FAILED — PSP decline reason in details.Show morePAYMENT_FAILED — PSP decline reason in details. On POST /v1/orders with payment.mode WALLET also details.reason WALLET_INSUFFICIENT with details.required, the order total, and details.available, the wallet's available amount; nothing was sent to a supplier. With payment.mode SAVED_METHOD a declined saved method is details.reason CARD_DECLINED with details.declineCode and details.methodId; nothing was sent to a supplier.
    ApiErrorResponse
  • 403ApiErrorResponse
  • 405
    VALIDATION — the public edge serves GET, POST, PUT, PATCH and DELETE only; any other method is refused before the platform sees it (details.reason METHOD_NOT_ALLOWED, details.source edge).Show moreVALIDATION — the public edge serves GET, POST, PUT, PATCH and DELETE only; any other method is refused before the platform sees it (details.reason METHOD_NOT_ALLOWED, details.source edge). Not retryable as sent.
    ApiErrorResponse
  • 409
    OFFER_EXPIRED | PRICE_CHANGED | QUOTE_EXPIRED | HOLD_EXPIRED | IDEMPOTENCY_CONFLICT | IDEMPOTENCY_IN_PROGRESS | DUPLICATE_ORDER | CONFLICT.Show moreOFFER_EXPIRED | PRICE_CHANGED | QUOTE_EXPIRED | HOLD_EXPIRED | IDEMPOTENCY_CONFLICT | IDEMPOTENCY_IN_PROGRESS | DUPLICATE_ORDER | CONFLICT. QUOTE_EXPIRED carries details.reason NO_SELL_PRICE_STAMP or SELL_PRICE_STAMP_MISMATCH when the repriceRef has no sell price the platform can book. CONFLICT is the payment check, a spent repriceRef or an incomplete FLT journey; its details.reason values, and which one is retryable, are listed in the operation description.
    ApiErrorResponse
  • 413
    VALIDATION — the request body is larger than the surface's limit.Show moreVALIDATION — the request body is larger than the surface's limit. Not retryable as sent: shrink the body. Declared on every operation that takes a request body. details carries exactly one key, maxBodyBytes (integer): the limit that applies to this surface, in bytes.
    ApiErrorResponse
  • 414
    VALIDATION — the request URI (path and query string) is longer than 8 KiB; the public edge refuses it before the platform sees it (details.reason URI_TOO_LONG, details.source edge).Show moreVALIDATION — the request URI (path and query string) is longer than 8 KiB; the public edge refuses it before the platform sees it (details.reason URI_TOO_LONG, details.source edge). Not retryable as sent: send long input in the body of a POST.
    ApiErrorResponse
  • 415
    VALIDATION — a request body that is not JSON (application/json or application/*+json; a form body only on the OAuth token routes).Show moreVALIDATION — a request body that is not JSON (application/json or application/*+json; a form body only on the OAuth token routes). The public edge refuses it before the platform sees it (details.reason UNSUPPORTED_MEDIA_TYPE, details.source edge). Not retryable as sent: send Content-Type application/json. Declared on every operation that takes a JSON request body.
    ApiErrorResponse
  • 422SOLD_OUT or TRAVELER_MISMATCHApiErrorResponse
  • 423
    PERMISSION_DENIED with details.reason KEY_PAUSED: the API key is PAUSED and every call with it is refused until an Owner or Admin resumes it (POST /v1/keys/{keyPrefix}:resume, a person only); or…Show morePERMISSION_DENIED with details.reason KEY_PAUSED: the API key is PAUSED and every call with it is refused until an Owner or Admin resumes it (POST /v1/keys/{keyPrefix}:resume, a person only); or details.reason LOOP_DETECTED on the call whose loop paused the key (20 identical requests in 60 s, or 50 holds without a booking or release in 10 min; replays of one Idempotency-Key never count). Not retryable; nextAction stop — the agent stops using the key and tells the person; details carry resumeBy (owner), consoleLink and evidence (ApiKeyPauseEvidence). Nothing was charged, held or sent; holds and orders already made are untouched. A key whose ancestor (the key that minted it, or that key's minter) is PAUSED answers the same 423 KEY_PAUSED, and resuming the ancestor resumes it, so a child never outlasts a pause of its parent. The MCP plane answers the identical body as an isError result. Any key-authenticated route may answer it; it is declared on the order and hold writes, search, reprice and the key routes.
    ApiErrorResponse
  • 429
    RATE_LIMITED with details.reason VELOCITY_LIMIT: a soft breach of the API key's own scope (reqPerSec, holdsPerHour, cancelsPerDay, lookToBook, spendPerDay) — the first two in 24 hours; the third, or a…Show moreRATE_LIMITED with details.reason VELOCITY_LIMIT: a soft breach of the API key's own scope (reqPerSec, holdsPerHour, cancelsPerDay, lookToBook, spendPerDay) — the first two in 24 hours; the third, or a burst above 5× the limit, pauses the key instead (423 KeyPaused). Retryable after retryAfterMs (mirrored by Retry-After); nextAction slow_down; details carry limit, windowSeconds and the dimension in details.field. The tenant quota of RateLimited and the key's velocity are separate limits. Every call of a minted key also counts against each ancestor key's velocity and spend windows, so minting N children never multiplies the blast radius; spendPerDay is reserved atomically before the order is placed and released if it fails.
    ApiErrorResponse
  • 500
    INTERNAL. Also raised when the payment check passed but the platform could not record that this order uses the payment: details.field names message.intent.payment.paymentRef and carries no reason.Show moreINTERNAL. Also raised when the payment check passed but the platform could not record that this order uses the payment: details.field names message.intent.payment.paymentRef and carries no reason. Nothing was sent to a supplier and the Idempotency-Key is released, so a retry under the same key is safe.
    ApiErrorResponse
  • 501
    NOT_IMPLEMENTED — honest fallback, as components/responses/NotImplemented.Show moreNOT_IMPLEMENTED — honest fallback, as components/responses/NotImplemented. also payment.mode SAVED_METHOD while saved payment methods are off on the deployment (aikonic.payment-methods.enabled), details.reason PAYMENT_METHODS_UNAVAILABLE; nothing is charged, written or sent to a supplier.
    ApiErrorResponse
  • 502Also the order read routes (getOrder, listOrderDocuments, listOrderEvents, searchOrders) when the order store times out: details.store names the store, retryable true.ApiErrorResponse
  • 503ApiErrorResponse

Errors you should handle

Branch on code and honour retryable — never on the HTTP status alone.

400VALIDATION
message.intent.repriceRef or message.intent.holdRef is required
not retryable
400UNKNOWN_DOMAIN
Unknown domain 'HOTELS'. Did you mean HTL?
not retryable
401UNAUTHENTICATED
The bearer token is expired. Re-authenticate and retry.
not retryable
402PAYMENT_FAILED
Card declined by the issuer
not retryable
403PERMISSION_DENIED
Role lacks the required scope: booking:write
not retryable
403TAB_DISABLED
Tenant acme-travel is not entitled to sell CRU
not retryable
403OUT_OF_SCOPE
The token's scope ladder does not reach this customer subtree
not retryable
403TENANT_MISMATCH
orderRef MO-8KD-2FQ-9XT does not belong to tenant acme-travel
not retryable
403TENANT_SUSPENDED
This tenant is suspended: new searches, quotes, holds, orders and payments are refused until it is reinstated. Existing orders can still be read, cancelled and amended.
not retryable
405VALIDATION
This method is not served.
not retryable
409CONFLICT
This payment has already been used by another order. Create a new payment intent for this booking.
not retryable
409PRICE_CHANGED
The supplier repriced at commit. The order was not created and nothing was captured.
not retryable
409QUOTE_EXPIRED
The repriceRef has no sell price this platform can book. Reprice again, then book the new RP-.
not retryable
409OFFER_EXPIRED
repriceRef RP-H-2ab91c expired at 2026-09-14T17:14:00Z
not retryable
409HOLD_EXPIRED
holdRef HD-M-4419ab expired at 2026-09-14T17:05:41Z; the seats were released
not retryable
409IDEMPOTENCY_CONFLICT
Idempotency-Key 7f0c33d1-9a1e-4d2c-9f77-1c0f2b3a4d55 was already used with a different body
not retryable
409IDEMPOTENCY_IN_PROGRESS
A request with this Idempotency-Key is still executing
retryable
409DUPLICATE_ORDER
An order already exists for clientReference acme-91827 on this itinerary
not retryable
413VALIDATION
The request body is larger than this API accepts (262144 bytes).
not retryable
414VALIDATION
The request URI is longer than 8 KiB.
not retryable
415VALIDATION
Send application/json.
not retryable
422SOLD_OUT
The selected fare class is no longer available at the supplier
not retryable
422TRAVELER_MISMATCH
Supplier rejected traveler[0]: passport expiry precedes the return date
not retryable
423PERMISSION_DENIED
This API key is paused: 212 holds in 9 min. An Owner or Admin must resume it in the console.
not retryable
429RATE_LIMITED
This API key exceeded its rate: 10 requests a second. Retry after 1.2 s.
retryable
500INTERNAL
An unexpected error occurred. Quote the traceId to support.
retryable
501NOT_IMPLEMENTED
seatmap is NOT_APPLICABLE for HTL; GET /v1/capabilities says so
not retryable
502UPSTREAM_UNAVAILABLE
Every supplier for HTL is circuit-open; no fan-out was attempted
retryable
503PROVIDER_DOWN
EXAMPLEHOTELS is unavailable; the order was not attempted and nothing was captured
retryable