Skip to content
ApiqDevelopers
API v1.64.0Open console
API referencepayments

Create payment intent

POST/v1/payments/intent
Accepts X-Api-Key · oauthClientCredentials · bearer

Create a payment intent from a repriceRef, or on the tenant's own provider account

Returns PSP client secret or Pix QR payload.Show moreReturns PSP client secret or Pix QR payload. Provider behind the seam is config. With paymentSource the intent runs on the tenant's OWN account at the provider, registered as a tenant-owned credential set: the caller states amount, sends no repriceRef, and must send an Idempotency-Key; the intent never pays an Apiq order and the response carries paymentSource instead of fork. Production external API never accepts PAN; SANDBOX/UAT accept a card sealed to the platform key on POST /v1/orders, never on this route. CREDIT_LINE and BR installments ride the same intent object. A deployment with no payment provider configured (provider=none) answers 501 NOT_IMPLEMENTED on every payment route.

Headers

  • Idempotency-KeystringOptional
    OPTIONAL on intent create — except with paymentSource, where it is REQUIRED (400 VALIDATION details.reason IDEMPOTENCY_KEY_REQUIRED) because it keys the provider's own idempotency.Show moreOPTIONAL on intent create — except with paymentSource, where it is REQUIRED (400 VALIDATION details.reason IDEMPOTENCY_KEY_REQUIRED) because it keys the provider's own idempotency. A replay returns the STORED answer, so its `checkout` (the hosted session an intent may carry) may since have been consumed or expired: re-read the intent (GET /v1/payments/{paymentId}) for the live session.

Request body

  • repriceRefstringOptional
    Required unless paymentSource is present
  • amountMoneyOptional
    Integer minor units + ISO-4217, never floats (platform law)
    5 child attributes
    • amountintegerRequired
      Minor units
    • currencystringRequired
      ISO-4217
    • fxAppliedbooleanOptional
      True when the amount was converted from the supplier's currency.
    • fxSnapshotIdstringOptional
      The exchange-rate snapshot the amount was converted with, fixed when the price was quoted.
    • breakdownarray of PriceBreakdownLineOptional
      Sell-side component lines summing to amount; the platform may send it empty.Show moreSell-side component lines summing to amount; the platform may send it empty. One line shape everywhere — the same PriceBreakdownLine the rule simulation answers. Never carries a supplier net.
      13 child attributes
      • typestringRequired
        The kind of line, for example BASE, TAX, FEE or DISCOUNT.
      • amountintegerRequired
        Minor units
      • feeTypestringOptional
        For FEE lines produced by a FEE_LINE rule — the tenant's fee label
      • labelstringOptional
        Display label in the request locale
      • taxComponentstringOptional
        For GST / TAX lines — CGST | SGST | IGST | UTGST | CESS | VAT | SALES_TAX | OCCUPANCY_TAX; open string
      • taxCodeTaxCodeOptional
        The statutory classification of a taxed line (SAC/HSN in India, VAT codes elsewhere)
        2 child attributes
        • schemestringRequired
          SAC | HSN | VAT | GST | OTHER; open string
        • codestringRequired
          The tax code, for example a SAC or HSN code in India or a VAT code elsewhere.
      • rateBasisPointsintegerOptional
        The tax or fee rate in basis points when the line is rate-based (1800 = 18%)
      • collectedBystringOptional
        PLATFORM | SUPPLIER | PROPERTY — who takes the money; a non-PLATFORM line outside Offer.price is a pay-at-property disclosure
      • payableAtstringOptional
        BOOKING | PROPERTY | DESK | AFTER_SERVICE
      • includedbooleanOptional
        True when the line is inside the enclosing amount (default); false for a disclosed line outside it
      • quantityintegerOptional
        How many units the line covers, when more than one.
      • unitAmountintegerOptional
        Minor units per unit when quantity is given
      • currencystringOptional
        ISO-4217 code of this line's amount and unitAmount.Show moreISO-4217 code of this line's amount and unitAmount. Set ONLY on a disclosed line (included false) that is NOT in the enclosing price's currency, for example a resort fee payable at the property in its local currency. Absent means the enclosing price's currency, as before; a line inside the total never carries it.
  • paymentSourcePaymentSourceOptional
    v1.49.0: the tenant's OWN account at a payment provider, registered as a tenant-owned credential set through POST /admin/v1/credential-sets.Show morev1.49.0: the tenant's OWN account at a payment provider, registered as a tenant-owned credential set through POST /admin/v1/credential-sets. The set is validated on first use (the key's mode against the set's environment, then a read-only provider call); a set that cannot serve payments is 409 CONFLICT details.reason PAYMENT_SOURCE_NOT_READY, an unknown one (or another tenant's) 404 NOT_FOUND details.reason PAYMENT_SOURCE_NOT_FOUND, a supplier with no source on this deployment 400 VALIDATION details.reason PAYMENT_SOURCE_NOT_OFFERED, and a deployment without payment sources 501 NOT_IMPLEMENTED details.reason PAYMENT_SOURCES_NOT_ENABLED. When the provider cannot be asked whether a new set's key works, the create is 502 UPSTREAM_UNAVAILABLE details.reason PAYMENT_SOURCE_UNVERIFIED (retryable) and the set is left as it was.
    2 child attributes
    • supplierstringRequired
      The provider's supplier id, e.g.
    • credentialSetstringOptional
      The tenant's credential set id; absent = the tenant's own set for the supplier
  • methodstringOptional
    CARD (hosted fields) | PIX | UPI | CREDIT_LINE | INSTALLMENTS | BNPL | ACH | NETBANKING | WALLET | EMI | APM.Show moreCARD (hosted fields) | PIX | UPI | CREDIT_LINE | INSTALLMENTS | BNPL | ACH | NETBANKING | WALLET | EMI | APM. Open string; a method the provider cannot run is 400 VALIDATION details.reason UNKNOWN_METHOD. NETBANKING, WALLET and EMI are the India rails; EMI carries its plan in installmentPlan.
  • captureModelstringOptional
    MANUAL_CAPTURE | SALE_ONLY | BNPL_AUTH; absent = the provider's default for the method.Show moreMANUAL_CAPTURE | SALE_ONLY | BNPL_AUTH; absent = the provider's default for the method. A model the provider cannot run is 400 VALIDATION details.reason CAPTURE_MODEL_NOT_SUPPORTED.
  • installmentPlanobjectOptional
    BR installments
  • sessionPaymentSessionOptional
    Optional order context some providers need to open a payment session.Show moreOptional order context some providers need to open a payment session. Amounts are integer minor units in the intent currency. A bad field is 400 VALIDATION details {field: session.*, reason: INVALID_SESSION}; a card number in any text field is 400 VALIDATION details.reason INSTRUMENT_DATA_REFUSED.
    5 child attributes
    • countrystringOptional
    • localestringOptional
    • orderRefstringOptional
    • taxAmountMoneyOptional
      Integer minor units + ISO-4217, never floats (platform law)
      5 child attributes
      • amountintegerRequired
        Minor units
      • currencystringRequired
        ISO-4217
      • fxAppliedbooleanOptional
        True when the amount was converted from the supplier's currency.
      • fxSnapshotIdstringOptional
        The exchange-rate snapshot the amount was converted with, fixed when the price was quoted.
      • breakdownarray of PriceBreakdownLineOptional
        Sell-side component lines summing to amount; the platform may send it empty.Show moreSell-side component lines summing to amount; the platform may send it empty. One line shape everywhere — the same PriceBreakdownLine the rule simulation answers. Never carries a supplier net.
        13 child attributes
        • typestringRequired
          The kind of line, for example BASE, TAX, FEE or DISCOUNT.
        • amountintegerRequired
          Minor units
        • feeTypestringOptional
          For FEE lines produced by a FEE_LINE rule — the tenant's fee label
        • labelstringOptional
          Display label in the request locale
        • taxComponentstringOptional
          For GST / TAX lines — CGST | SGST | IGST | UTGST | CESS | VAT | SALES_TAX | OCCUPANCY_TAX; open string
        • taxCodeTaxCodeOptional
          The statutory classification of a taxed line (SAC/HSN in India, VAT codes elsewhere)
        • rateBasisPointsintegerOptional
          The tax or fee rate in basis points when the line is rate-based (1800 = 18%)
        • collectedBystringOptional
          PLATFORM | SUPPLIER | PROPERTY — who takes the money; a non-PLATFORM line outside Offer.price is a pay-at-property disclosure
        • payableAtstringOptional
          BOOKING | PROPERTY | DESK | AFTER_SERVICE
        • includedbooleanOptional
          True when the line is inside the enclosing amount (default); false for a disclosed line outside it
        • quantityintegerOptional
          How many units the line covers, when more than one.
        • unitAmountintegerOptional
          Minor units per unit when quantity is given
        • currencystringOptional
          ISO-4217 code of this line's amount and unitAmount.Show moreISO-4217 code of this line's amount and unitAmount. Set ONLY on a disclosed line (included false) that is NOT in the enclosing price's currency, for example a resort fee payable at the property in its local currency. Absent means the enclosing price's currency, as before; a line inside the total never carries it.
    • orderLinesarray of objectOptional
      4 child attributes
      • namestringRequired
      • quantityintegerRequired
      • unitPriceMoneyRequired
        Integer minor units + ISO-4217, never floats (platform law)
        5 child attributes
        • amountintegerRequired
          Minor units
        • currencystringRequired
          ISO-4217
        • fxAppliedbooleanOptional
          True when the amount was converted from the supplier's currency.
        • fxSnapshotIdstringOptional
          The exchange-rate snapshot the amount was converted with, fixed when the price was quoted.
        • breakdownarray of PriceBreakdownLineOptional
          Sell-side component lines summing to amount; the platform may send it empty.Show moreSell-side component lines summing to amount; the platform may send it empty. One line shape everywhere — the same PriceBreakdownLine the rule simulation answers. Never carries a supplier net.
      • taxAmountMoneyOptional
        Integer minor units + ISO-4217, never floats (platform law)
        5 child attributes
        • amountintegerRequired
          Minor units
        • currencystringRequired
          ISO-4217
        • fxAppliedbooleanOptional
          True when the amount was converted from the supplier's currency.
        • fxSnapshotIdstringOptional
          The exchange-rate snapshot the amount was converted with, fixed when the price was quoted.
        • breakdownarray of PriceBreakdownLineOptional
          Sell-side component lines summing to amount; the platform may send it empty.Show moreSell-side component lines summing to amount; the platform may send it empty. One line shape everywhere — the same PriceBreakdownLine the rule simulation answers. Never carries a supplier net.

Responses

  • 200Intent with client-side handoff materialPaymentIntentResponse
  • 400
    VALIDATION or UNKNOWN_DOMAIN. details.reason CAPTURE_MODEL_NOT_SUPPORTED (the provider cannot run the named captureModel), INVALID_SESSION (a bad session.* field, details.field names it) or…Show moreVALIDATION or UNKNOWN_DOMAIN. details.reason CAPTURE_MODEL_NOT_SUPPORTED (the provider cannot run the named captureModel), INVALID_SESSION (a bad session.* field, details.field names it) or INSTRUMENT_DATA_REFUSED (a card number in a text field). v1.49.0 (paymentSource): AMOUNT_FROM_REPRICE_ONLY (an amount without a source), REPRICE_REF_WITH_PAYMENT_SOURCE, AMOUNT_REQUIRED, AMOUNT_NOT_POSITIVE, IDEMPOTENCY_KEY_REQUIRED, PAYMENT_SOURCE_NOT_OFFERED.
    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 — the provider refused to create the intent.Show morePAYMENT_FAILED — the provider refused to create the intent. details.reason PROVIDER_REFUSED_CREATE with declineCode, paymentId and psp.
    ApiErrorResponse
  • 403
    PERMISSION_DENIED | TAB_DISABLED | OUT_OF_SCOPE | TENANT_MISMATCH, exactly as Forbidden, plus TENANT_SUSPENDED — declared on the verbs that start new business: search and poll, detail, schedules,…Show morePERMISSION_DENIED | TAB_DISABLED | OUT_OF_SCOPE | TENANT_MISMATCH, exactly as Forbidden, plus TENANT_SUSPENDED — declared on the verbs that start new business: search and poll, detail, schedules, seatmap, ancillaries, rules, reprice, hold and order create, and on the payments routes (intent, confirm, 3ds-callback, checkout-session). While the caller's tenant is SUSPENDED every such request is refused TENANT_SUSPENDED, except an idempotent replay of an answer completed before the suspension (see hold / createOrder), before the entitlement and permission checks, and it is not retryable: the answer changes only when platform ops reinstates the tenant. The post-booking verbs (cancel-quote, cancel, amend), the order reads, and capture and refund on an existing payment intent (whose 403 is PaymentForbidden) stay up, so no traveller is stranded. On the production deployment the same requests are refused PERMISSION_DENIED with details.reason TENANT_NOT_LIVE while the tenant's production activation has not been approved, whichever credential is presented, console session or API key; use the sandbox deployment until activation. Not retryable; the post-booking verbs stay up.
    ApiErrorResponse
  • 404
    NOT_FOUND — details.reason PAYMENT_SOURCE_NOT_FOUND: the tenant has no such credential set for the supplier.Show moreNOT_FOUND — details.reason PAYMENT_SOURCE_NOT_FOUND: the tenant has no such credential set for the supplier. A set of another tenant answers the same.
    ApiErrorResponse
  • 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
    CONFLICT: details.reason PAYMENT_SOURCE_NOT_READY — the named credential set cannot serve payments (its key was refused, or it is revoked or disabled).Show moreCONFLICT: details.reason PAYMENT_SOURCE_NOT_READY — the named credential set cannot serve payments (its key was refused, or it is revoked or disabled). QUOTE_EXPIRED | IDEMPOTENCY_CONFLICT | IDEMPOTENCY_IN_PROGRESS. QUOTE_EXPIRED: the repriceRef expired or was spent, or it has no sell price the platform can charge — details.reason NO_SELL_PRICE_STAMP or SELL_PRICE_STAMP_MISMATCH, or REPRICE_REF_HELD when a live intent already holds this RP- with a different method or capture model — reuse that intent or reprice again. Reprice again and create the intent from the new RP-. IDEMPOTENCY_IN_PROGRESS also answers a second create on the same RP- while the first is still being created (details.reason INTENT_CREATE_IN_PROGRESS, retryable).
    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
  • 429
    RATE_LIMITED — the API key or its tenant is over a rate limit; wait for Retry-After, then retry.Show moreRATE_LIMITED — the API key or its tenant is over a rate limit; wait for Retry-After, then retry. Every routed request is counted against two token buckets, the key's and the tenant's (all its keys together): 50 requests a second with a burst of 100 on the standard plan. Every travel verb except polling a search also spends from a supplier budget, per key and per tenant: 10 requests a second with a burst of 20, and a plan may add a daily quota of supplier calls. Answers carry the IETF RateLimit header fields for the tightest bucket consulted (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, RateLimit-Policy); a refusal adds Retry-After and details.scope (KEY or TENANT), details.budget (PLATFORM or SUPPLIER), details.reason (RATE or DAILY_QUOTA), details.tier and details.retryAfterMs. A sandbox may run with the limiter off, in which case none of these headers is sent. A search that is still warming is a different answer with a different meaning (keep polling). with the key-velocity check on, also details.reason VELOCITY_LIMIT, a soft breach of the API key's own scope (components/responses/VelocityLimited), nextAction slow_down.
    ApiErrorResponse
  • 500INTERNAL — a bug, and traceId is the support handle.ApiErrorResponse
  • 501
    NOT_IMPLEMENTED — this deployment serves no payments: no payment provider is configured (provider=none), so every payment route answers 501.Show moreNOT_IMPLEMENTED — this deployment serves no payments: no payment provider is configured (provider=none), so every payment route answers 501. Not a capabilities-doc bug: payments are deployment configuration.
    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.checkOut must be after message.intent.checkIn
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
The payment provider refused to create the payment.
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
404NOT_FOUNDnot retryable
405VALIDATION
This method is not served.
not retryable
409QUOTE_EXPIRED
The repriceRef has expired or been spent. Reprice again, then create the intent from the new RP-.
not retryable
409IDEMPOTENCY_IN_PROGRESS
A payment intent for this repriceRef is still being created. Retry shortly.
retryable
409IDEMPOTENCY_CONFLICT
Idempotency-Key 7f0c33d1-9a1e-4d2c-9f77-1c0f2b3a4d55 was used with a different body; never executed
not retryable
409CONFLICT
The payment source cannot serve payments: Example Pay refused the key.
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
429RATE_LIMITED
Too many requests for this key on the supplier budget. Wait for the Retry-After interval before trying again.
retryable
500INTERNAL
An unexpected error occurred. Quote the traceId to support.
retryable
501NOT_IMPLEMENTED
This deployment serves no payments: no payment provider is configured.
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