# Create a checkout session (/en/api-reference/checkout-sessions/createCheckoutSession)

Creates a new checkout session for hosted or embedded checkout. Returns a session with a URL to redirect customers for payment.

## POST /checkout/sessions

### Request body (required)

Content type: `application/json`

- `afterCompletion` (AfterCompletion, required) — Behavior after the purchase is complete. **type=redirect** (default): Redirect customer to your URL after payment. Requires `afterCompletion.redirect.url`. **type=hosted_confirmation**: Show a built-in XPay-hosted success page. Optionally provide `afterCompletion.hostedConfirmation.customMessage` and `afterCompletion.hostedConfirmation.returnUrl`. Example (redirect): `{ type: 'redirect', redirect: { url: 'https://example.com/success' } }` Example (hosted): `{ type: 'hosted_confirmation', hostedConfirmation: { customMessage: 'Thanks!' } }`
  - `type` (enum("redirect" | "hosted_confirmation"), required) — The behavior after the purchase is complete. - **redirect**: Customer is redirected to the URL specified in `redirect.url`. The `redirect` object is required when using this type. Cannot be combined with `hostedConfirmation`. - **hosted_confirmation**: Customer sees a built-in confirmation page hosted by XPay with a success animation, thank you message, and optional custom message. The `hostedConfirmation` object is optional. Cannot be combined with `redirect`. Not available when `uiMode` is `embedded` or `custom` — those integrations run on your own page, and there is no XPay page to show the customer.
  - `redirect` (AfterCompletionRedirect) — Configuration when type=redirect. **Required** when type is 'redirect'. Must not be provided when type is 'hosted_confirmation'.
    - `url` (string, required) — Where we hand the browser back to you. Required when afterCompletion.type is 'redirect'. - **hosted**: the customer is redirected here after a successful payment. A failed payment keeps them on the checkout page so they can retry. - **embedded**: the customer is returned here when a bank verification has to take over the whole tab. That return happens whatever the outcome, so read the session's status on arrival rather than assuming success. - **custom**: the destination `redirect: "always"` sends the customer to after a successful payment. Include `{CHECKOUT_SESSION_ID}` anywhere in the URL and we substitute the session id before the customer ever reaches it.
  - `hostedConfirmation` (AfterCompletionHostedConfirmation) — Configuration when type=hosted_confirmation. Optional — if not provided, a default confirmation page is shown. Must not be provided when type is 'redirect'.
    - `customMessage` (string) — Custom message displayed to the customer on the hosted confirmation page after payment. If not provided, a default message is shown: 'A payment to {merchant} will appear on your statement.' Max 500 characters.
    - `returnUrl` (string) — Optional URL for a "Return to {merchant}" button on the confirmation page. If not provided, no return button is shown.
- `mode` (enum("payment" | "setup" | "subscription")) — Session mode: payment, subscription, or setup
- `uiMode` (enum("hosted" | "embedded" | "custom")) — The UI mode of the Session. Defaults to hosted. - **hosted**: Customer is redirected to XPay's hosted checkout page. - **embedded**: Full checkout embedded in merchant's site via SDK drop-in modal. - **custom**: Merchant builds their own checkout form using the Elements SDK (Payment Element, Card Element).
- `submitType` (enum("PAY" | "SUBSCRIBE" | "BOOK" | "DONATE")) — Describes the type of transaction to customize button text (e.g., 'Pay', 'Subscribe'). You can't set this parameter if uiMode is custom.
- `currency` (enum("EGP" | "USD" | "EUR" | "GBP" | "SAR" | "AED" | "QAR" | "KWD" | "JOD" | "OMR" | "BHD" | "LYD" | "AUD" | "CAD" | "CNY")) — ISO 4217 currency code
- `lineItems` (Array<LineItemInput>) — Line items for the checkout
  - `price` (string) — Existing price ID (mutually exclusive with priceData)
  - `priceData` (PriceData) — Inline price data (mutually exclusive with price)
    - `currency` (enum("EGP" | "USD" | "EUR" | "GBP" | "SAR" | "AED" | "QAR" | "KWD" | "JOD" | "OMR" | "BHD" | "LYD" | "AUD" | "CAD" | "CNY"), required) — Currency (required)
    - `unitAmount` (number, required) — Unit amount in smallest currency unit (required)
    - `productData` (ProductData, required) — Inline product data (required - at least name)
    - `recurring` (RecurringData) — Recurring configuration (for subscriptions)
    - `metadata` (object) — Custom metadata
  - `quantity` (number, required) — Quantity. May be 0 only when adjustableQuantity is enabled with minimum 0 (optional item).
  - `adjustableQuantity` (AdjustableQuantityInput) — Adjustable quantity settings
    - `enabled` (boolean, required) — Enable customer quantity adjustment
    - `minimum` (number) — Minimum quantity. Set to 0 to make the item optional (customer can remove it).
    - `maximum` (number) — Maximum quantity
- `cancelUrl` (string) — URL to redirect if customer cancels (back button during checkout). This parameter is not allowed if uiMode is embedded or custom.
- `customerId` (string) — Existing customer ID. If provided, customer data will be used to prefill checkout fields. IMPORTANT: Cannot be used together with customerDetails - you must choose one: - Use customerId to checkout with an existing customer - Use customerDetails to provide prefill data for a new customer
- `customerDetails` (CustomerDetailsInput) — Customer details for prefill and collection. Used to: - Prefill checkout form fields - Create a new customer (if customerCreation is 'always') IMPORTANT: Cannot be used together with customerId - you must choose one.
  - `name` (string) — Customer name
  - `email` (string) — Customer email
  - `phone` (string) — Customer phone
  - `billingDetails` (BillingDetailsInput) — Billing details including cardholder name and address
    - `name` (string) — Cardholder name (name on card)
    - `email` (string) — Billing email
    - `phone` (string) — Billing phone
    - `address` (AddressInput) — Billing address
  - `shipping` (ShippingInput) — Shipping details (if different from billing)
    - `name` (string) — Recipient name
    - `phone` (string) — Recipient phone
    - `address` (AddressInput) — Shipping address
- `customerUpdate` (CustomerUpdate) — Controls which customer fields to update when customerId is provided. IMPORTANT: Only valid when customerId is provided. Will be ignored otherwise. Each field can be 'auto' (update customer) or 'never' (don't update, default).
  - `address` (enum("auto" | "never")) — Whether to save billing address to customer.address. Defaults to 'never'.
  - `name` (enum("auto" | "never")) — Whether to save name to customer.name. Defaults to 'never'.
  - `shipping` (enum("auto" | "never")) — Whether to save shipping info to customer.shipping. Defaults to 'never'.
- `customerCreation` (enum("always" | "if_required")) — When to create customer
- `allowPromotionCodes` (boolean) — Allow promotion codes
- `discounts` (Array<CheckoutDiscountInput>) — Discounts to apply to this session. Each must reference either a coupon ID or promotion code ID. Max 1 discount per session.
  - `coupon` (string) — Coupon ID to apply directly. Mutually exclusive with promotionCode.
  - `promotionCode` (string) — Promotion code ID to apply. Mutually exclusive with coupon.
- `nameCollection` (boolean) — Collect customer name. You can't set this parameter if uiMode is custom.
- `billingAddressCollection` (boolean) — Collect billing address. You can't set this parameter if uiMode is custom.
- `shippingAddressCollection` (boolean) — Collect shipping address. You can't set this parameter if uiMode is custom.
- `phoneNumberCollection` (boolean) — Collect phone number. You can't set this parameter if uiMode is custom.
- `customFields` (Array<CustomFieldInput>) — Custom fields to collect
  - `label` (string, required) — Field label
  - `type` (enum("TEXT" | "NUMBER" | "DROPDOWN" | "CHECKBOX"), required) — Field type
  - `isOptional` (boolean) — Whether the field is optional
  - `hasLimits` (boolean) — Whether validation limits are enabled
  - `limitType` (enum("AT_MOST" | "BETWEEN" | "AT_LEAST" | "EXACTLY")) — Type of validation limit
  - `minCharacters` (number) — Minimum number of characters
  - `maxCharacters` (number) — Maximum number of characters
  - `dropdownOptions` (Array<DropdownOptionInput>) — Dropdown options (only for DROPDOWN type)
    - `label` (string, required) — Option label
- `metadata` (object) — Custom key-value metadata
- `feeConfig` (FeeConfigInput) — Fee configuration override for this session. If not provided, merchant's default fee config will be used. - feesPassThrough: Customer pays platform fee instead of merchant - vatCollectionEnabled: Collect merchant's product VAT from customer - vatCollectionRate: VAT rate in basis points (e.g., 1400 = 14%)
  - `feesPassThrough` (boolean, required) — Whether customer pays platform fee instead of merchant. When true, platform fee is added to customer payment.
  - `vatCollectionEnabled` (boolean, required) — Whether to collect merchant's product VAT from customer. When enabled, VAT is added to customer payment.
  - `vatCollectionRate` (number) — VAT collection rate in basis points (e.g., 1400 = 14%). Required when vatCollectionEnabled is true.
- `brandingSettings` (BrandingSettingsInput) — UI customization settings for the checkout page. Allows customization of colors, spacing, border styles, input styles, etc. Merged server-side with the merchant's `defaultBrandingSettings` — anything set here wins.
  - `colorMode` (enum("light" | "dark" | "system")) — Dark mode preference
  - `borderStyle` (enum("rounded" | "sharp" | "pill")) — Border style for inputs, buttons, cards
  - `spacing` (enum("condensed" | "normal" | "spacious")) — Spacing density
  - `inputSize` (enum("small" | "medium" | "large")) — Input field size
  - `inputStyle` (enum("flat" | "outlined" | "filled")) — Input field style
  - `formLayout` (enum("compact" | "spacious")) — Form layout density
  - `colors` (ColorCustomizationInput) — Color customization options
    - `primary` (string) — Primary brand color (buttons, links, accents). Hex only, e.g. `#635bff`.
    - `primaryForeground` (string) — Primary foreground (text on primary background). Hex only.
    - `background` (string) — Page background color. Hex only.
    - `foreground` (string) — Main text color. Hex only.
    - `border` (string) — Border color. Hex only.
    - `input` (string) — Input, button, and dropdown border color. Hex only.
    - `ring` (string) — Focus ring color. Hex only.
    - `muted` (string) — Muted/secondary background. Hex only.
    - `mutedForeground` (string) — Muted text color. Hex only.
    - `accent` (string) — Accent background. Hex only.
    - `accentForeground` (string) — Accent text color. Hex only.
    - `destructive` (string) — Destructive/error color. Hex only.
  - `fontFamily` (string) — Font family override (CSS font-family value, e.g. 'Inter, sans-serif')
- `locale` (enum("en" | "ar")) — Language the checkout page is displayed in. Falls back to your account's `defaultLocale` when omitted, then to `en`.
- `paymentMethodTypes` (Array<enum("card" | "fawry" | "aman" | "valu" | "sympl" | "tabby" | "tamara" | "vodafone_cash" | "etisalat_cash" | "orange_cash" | "we_pay" | "apple_pay" | "google_pay" | "samsung_pay" | "instapay" | "bank_transfer" | "cash_on_delivery")>) — Restrict this session to specific payment method types. Most integrations omit this and manage methods from the dashboard under Settings > Payment methods. Every type must already be enabled on your account, or the request is rejected. Mutually exclusive with paymentMethodConfigurationId. Omit both to use your default configuration. Example: ["card", "valu"]
- `paymentMethodConfigurationId` (string) — ID of a payment method configuration to use for this session. Find IDs in your dashboard under Settings > Payment methods. Preferred over `paymentMethodTypes`: the list stays editable in the dashboard. Mutually exclusive with `paymentMethodTypes`. Omit both to use your default configuration.
- `expiresAfterMinutes` (number) — Session expiration in minutes (default: 1440 = 24 hours)

### Responses

#### 201 — Checkout session created successfully

Content type: `application/json`

- `id` (string) — Checkout session ID. Absent on the SSR hosted-view payload derived from a payment link (before the first mutation materializes the session).
- `object` (string, required) — Object type
- `createdAt` (string, required) — Created timestamp (ISO 8601)
- `updatedAt` (string) — Updated timestamp (ISO 8601)
- `mode` (enum("payment" | "setup" | "subscription"), required) — Session mode
- `uiMode` (enum("hosted" | "embedded" | "custom"), required) — UI mode
- `submitType` (enum("PAY" | "SUBSCRIBE" | "BOOK" | "DONATE"), required) — Submit type
- `customerCreation` (enum("always" | "if_required"), required) — Customer creation mode
- `status` (enum("open" | "complete" | "expired"), required) — Session status
- `paymentStatus` (enum("paid" | "unpaid" | "no_payment_required"), required) — Payment status
- `currency` (enum("EGP" | "USD" | "EUR" | "GBP" | "SAR" | "AED" | "QAR" | "KWD" | "JOD" | "OMR" | "BHD" | "LYD" | "AUD" | "CAD" | "CNY")) — Currency code (ISO 4217)
- `amountSubtotal` (number) — Subtotal before discounts/taxes
- `amountTotal` (number) — Total amount due
- `totalDetails` (TotalDetailsResponse) — Amount breakdown
  - `amountDiscount` (number, required) — Discount amount
  - `amountShipping` (number) — Shipping amount
  - `amountTax` (number, required) — Tax amount
  - `amountPlatformFee` (number) — Platform fee amount (only when feesPassThrough is enabled)
  - `amountCollectedVat` (number) — Collected VAT amount (only when vatCollectionEnabled is enabled)
- `presentmentDetails` (SessionPresentmentDetails) — Customer-facing view of the session — full mirror of subtotal/total/discount/VAT/fees in the presentment currency. Populated only when the merchant prices in a currency different from processing. Uses a rate locked at session creation.
  - `amount` (number, required) — Amount in the customer's currency (smallest unit — e.g. fils for KWD, cents for USD)
  - `currency` (enum("EGP" | "USD" | "EUR" | "GBP" | "SAR" | "AED" | "QAR" | "KWD" | "JOD" | "OMR" | "BHD" | "LYD" | "AUD" | "CAD" | "CNY"), required) — Customer's currency code (ISO 4217)
  - `exchangeRate` (number, required) — Locked exchange rate: presentment_major × rate = processing_major. Reused for refunds/disputes. Stored as numeric(15,6) — frontend can call `.toFixed(6)` to render the full 6-decimal string when needed.
  - `exchangeRateId` (string, required) — Reference to the immutable ExchangeRate record used — audit trail for FX reconciliation
  - `amountSubtotal` (number, required) — Subtotal before discounts/fees, in presentment smallest unit
  - `amountTotal` (number, required) — Final total the customer sees, in presentment smallest unit
  - `amountDiscount` (number, required) — Discount applied, in presentment smallest unit (0 when no discount)
  - `amountCollectedVat` (number) — Collected VAT in presentment smallest unit (only when VAT collection is enabled)
  - `amountPlatformFee` (number) — Platform fee in presentment smallest unit (only when feesPassThrough is enabled)
  - `amountTax` (number) — Tax in presentment smallest unit (only when tax is charged)
- `afterCompletion` (object, required) — What happens after payment: redirect to merchant URL or show hosted confirmation page
- `cancelUrl` (string) — Cancel redirect URL (back button during checkout)
- `url` (string) — Checkout page URL (hosted mode)
- `clientSecret` (string) — Client secret for frontend access
- `expiresAt` (string) — Expiration timestamp (ISO 8601)
- `isExpired` (boolean, required) — Whether this session can no longer be paid because it has expired (either swept/expired by status, or past `expiresAt`). Clients MUST render from this flag and MUST NOT re-derive expiry by comparing `expiresAt` against the local clock — a customer device running fast reads a live session as dead.
- `customerId` (string) — Customer ID (when existing customer linked)
- `customer` (CheckoutSessionCustomer) — Customer object (when customerId is provided). Contains existing customer data for prefill.
  - `id` (string, required) — Customer ID
  - `type` (enum("guest" | "registered"), required) — Customer type. `registered` is a permanent merchant-managed record; `guest` is a session-scope dedup unit created automatically when `customerCreation` is `if_required`.
  - `name` (string) — Customer name
  - `email` (string) — Customer email
  - `phone` (string) — Customer phone
  - `address` (AddressResponse) — Customer address
    - `line1` (string) — Address line 1
    - `line2` (string) — Address line 2
    - `city` (string) — City
    - `state` (string) — State/Province
    - `postalCode` (string) — Postal code
    - `country` (string) — Country code
  - `shipping` (ShippingResponse) — Customer shipping details
    - `name` (string) — Recipient name
    - `phone` (string) — Recipient phone
    - `address` (AddressResponse) — Shipping address
  - `metadata` (object) — Customer metadata
- `customerDetails` (CustomerDetailsResponse) — CustomerDetails - unified prefill/collection object. Contains name, email, phone, address (billing), shipping.
  - `name` (string) — Customer name
  - `email` (string) — Customer email
  - `phone` (string) — Customer phone
  - `billingDetails` (BillingDetailsResponse) — Billing details including cardholder name and address
    - `name` (string) — Cardholder name (name on card)
    - `email` (string) — Billing email
    - `phone` (string) — Billing phone
    - `address` (AddressResponse) — Billing address
  - `shipping` (ShippingResponse) — Shipping details
    - `name` (string) — Recipient name
    - `phone` (string) — Recipient phone
    - `address` (AddressResponse) — Shipping address
- `paymentIntentId` (string) — Payment Intent ID
- `paymentIntent` (NestedPaymentIntentResponse, required) — The PaymentIntent for this session, or `null` if no payment has been started yet. The PaymentIntent's own `checkoutSession` field is not included here to keep the response self-contained.
  - `id` (string, required) — Unique identifier for this PaymentIntent. Always prefixed with `pi_`.
  - `object` (string, required) — String identifying the object type. Always `payment_intent` for this resource.
  - `checkoutSessionId` (string | null) — ID of the CheckoutSession that created this PaymentIntent. `null` for PaymentIntents created directly via the API without a session.
  - `amount` (number, required) — Amount the customer is being charged, in the smallest currency unit of `currency` (e.g. piasters for EGP — `10000` = 100 EGP).
  - `amountCapturable` (number, required) — Amount that can still be captured for this PaymentIntent, in the smallest currency unit. Non-zero only when `captureMethod` is `manual` and the payment has been authorized but not yet captured. Drops to `0` once captured (fully or partially).
  - `amountReceived` (number, required) — Amount actually received from the customer so far, in the smallest currency unit. Equals `amount` after a successful capture; `0` for payments that haven't reached SUCCEEDED.
  - `currency` (enum("EGP" | "USD" | "EUR" | "GBP" | "SAR" | "AED" | "QAR" | "KWD" | "JOD" | "OMR" | "BHD" | "LYD" | "AUD" | "CAD" | "CNY"), required) — ISO 4217 currency code this payment is denominated in.
  - `status` (enum("REQUIRES_PAYMENT_METHOD" | "REQUIRES_CONFIRMATION" | "REQUIRES_ACTION" | "PROCESSING" | "UNCAPTURED" | "CANCELED" | "SUCCEEDED" | "FAILED" | "REFUNDED" | "PARTIALLY_REFUNDED" | "AMOUNT_CAPTURABLE_UPDATED"), required) — Lifecycle status. Combines the raw processor state with refund state, so values like `REFUNDED`, `PARTIALLY_REFUNDED`, `UNCAPTURED`, and `FAILED` may appear in addition to the base processor states.
  - `createdAt` (string, required) — Created timestamp (ISO 8601)
  - `updatedAt` (string, required) — Updated timestamp (ISO 8601)
  - `clientSecret` (string, required) — Secret used by the SDK to confirm the payment from the customer's browser. Do NOT log this or share it with any party other than the customer. Each PaymentIntent has one client secret for its lifetime.
  - `captureMethod` (enum("automatic" | "manual"), required) — When to capture funds from the customer. `automatic` (default) captures immediately on successful confirmation. `manual` only authorizes — call the capture endpoint later (within 7 days) to actually move the money.
  - `confirmationMethod` (enum("automatic" | "manual"), required) — How the PaymentIntent moves out of `REQUIRES_CONFIRMATION`. `automatic` (default) confirms as soon as a payment method is attached. `manual` requires you to call confirm explicitly.
  - `description` (string | null) — Arbitrary description you can attach when creating the PaymentIntent. Shown in the dashboard and useful for reconciling with your own systems. `null` if not provided.
  - `receiptEmail` (string | null) — Email to send the receipt to once the payment succeeds. `null` if no receipt email was set.
  - `canceledAt` (string | null) — ISO 8601 timestamp of when this PaymentIntent was canceled. `null` if it was never canceled.
  - `shipping` (Shipping) — Shipping address and recipient details for this payment. `null` if no shipping was collected.
    - `address` (Address, required) — Shipping address.
    - `name` (string | null) — Recipient name as provided by the customer.
    - `phone` (string | null) — Recipient phone number as provided by the customer.
  - `amountDetails` (AmountDetails) — Breakdown of `amount` into product amount, tax, platform fees, tip, and discount. `null` for legacy payments without itemized breakdown.
    - `productAmount` (number, required) — Amount that pays for the product/service itself, in the smallest currency unit. Excludes tax, platform fees, tip, and discount.
    - `tax` (AmountDetailsTax) — Tax breakdown for this payment. `null` if no tax was collected.
    - `platformFees` (AmountDetailsPlatformFees) — Platform fee breakdown for this payment. `null` if not surfaced to the customer.
    - `tip` (number | null) — Tip amount included in this payment, in the smallest currency unit. `null` if no tip.
    - `discount` (number | null) — Discount amount applied, in the smallest currency unit. `null` if no discount.
  - `presentmentDetails` (PresentmentDetails) — Mirror of `amount` / `currency` in the currency the customer actually saw at checkout, when different from the settlement currency. `null` when customer paid in the same currency.
    - `amount` (number, required) — Amount in the customer's currency (smallest unit — e.g. fils for KWD, cents for USD)
    - `currency` (enum("EGP" | "USD" | "EUR" | "GBP" | "SAR" | "AED" | "QAR" | "KWD" | "JOD" | "OMR" | "BHD" | "LYD" | "AUD" | "CAD" | "CNY"), required) — Customer's currency code (ISO 4217)
    - `exchangeRate` (number, required) — Locked exchange rate: presentment_major × rate = processing_major. Reused for refunds/disputes. Stored as numeric(15,6) — frontend can call `.toFixed(6)` to render the full 6-decimal string when needed.
    - `exchangeRateId` (string, required) — Reference to the immutable ExchangeRate record used — audit trail for FX reconciliation
  - `latestCharge` ([Charge](/en/api-reference/objects/charge)) — The most recent Charge attempt for this PaymentIntent. `null` if no Charge has been attempted yet.
  - `charges` (Array<[Charge](/en/api-reference/objects/charge)>, required) — All Charge attempts for this PaymentIntent, sorted by creation time ascending (oldest first). Each retry adds a new Charge. Empty array if no attempts have been made yet.
  - `paymentMethod` (PaymentMethodObject) — Payment method attached to this PaymentIntent. `null` before a method is attached or after a failure clears it.
    - `id` (string, required)
    - `object` (string, required)
    - `card` (PaymentMethodCard, required)
    - `valu` (ValuDetails) — ValU details (if type is 'valu')
    - `billingDetails` (BillingDetails, required)
    - `type` (enum("card" | "fawry" | "aman" | "valu" | "sympl" | "tabby" | "tamara" | "vodafone_cash" | "etisalat_cash" | "orange_cash" | "we_pay" | "apple_pay" | "google_pay" | "samsung_pay" | "instapay" | "bank_transfer" | "cash_on_delivery"), required)
    - `createdAt` (string, required) — Created timestamp (ISO 8601)
  - `customer` (Customer) — The Customer this payment belongs to. `null` if no Customer is associated.
    - `id` (string, required) — ID of the Customer associated with this payment.
    - `name` (string | null) — Customer's name as captured for this payment. Prefers the billing-details snapshot from the latest charge (immutable) over the Customer entity's current name.
    - `email` (string | null) — Customer's email captured for this payment. Falls back to the Customer entity's email if no billing-details email was provided.
    - `phone` (string | null) — Customer's phone captured for this payment, in E.164 format when available.
  - `nextAction` (NextActionDetail) — Action the customer must take to advance the payment (e.g. complete 3-D Secure). `null` when no further action is needed.
    - `type` (string, required) — Kind of action the customer must take next. Today the only value is `redirect_to_url`; future payment methods may add new types.
    - `redirectToUrl` (NextActionRedirect) — Redirect details when `type` is `redirect_to_url`. `null` for any other action type.
  - `metadata` (object, required) — Custom key/value pairs you attached when creating or updating the PaymentIntent. Useful for reconciling with your own systems. Empty object if none.
  - `lastPaymentError` (LastPaymentErrorDetail) — Details of the most recent failed payment attempt for this PaymentIntent. `null` if no attempts have failed.
    - `code` (string | null) — Short machine-readable error code describing what failed (e.g. `card_declined`, `expired_card`, `incorrect_cvc`). `null` if no code applies.
    - `declineCode` (string | null) — More specific reason for a decline (e.g. `insufficient_funds`, `generic_decline`). Present when `code` is `card_declined`; otherwise `null`.
    - `networkDeclineCode` (string | null) — Decline code returned by the card network itself, when different from `declineCode`. `null` if the network did not provide one.
    - `docUrl` (string | null) — Link to documentation explaining this error and how to recover from it.
    - `message` (string, required) — Customer-safe message describing what went wrong. Safe to display in your UI.
    - `merchantMessage` (string | null) — Internal message for the merchant with more detail than `message`. Do NOT show this to customers. `null` if no merchant-only context is available.
    - `adviceCode` (enum("confirm_card_data" | "do_not_try_again" | "try_again_later")) — Advice on whether and how to retry. One of `confirm_card_data`, `do_not_try_again`, `try_again_later`. `null` if no specific advice applies.
    - `param` (string | null) — Name of the request parameter that caused the error (e.g. `amount`, `payment_method`). `null` when the failure isn't tied to a specific parameter.
    - `chargeId` (string | null) — ID of the failed Charge that triggered this error. `null` if no charge was created.
    - `paymentMethod` (object | null) — Snapshot of the payment method as it existed at the time of failure (brand, last 4, billing details, etc.). `null` if no payment method was attached when the error occurred.
    - `paymentMethodType` (string | null) — Type of the payment method that failed (e.g. `card`, `valu`, `fawry`). `null` if unknown.
    - `type` (enum("card_error" | "payment_method_error" | "api_error" | "invalid_request_error"), required) — Error category. One of `card_error`, `payment_method_error`, `api_error`, `invalid_request_error`. Use this for high-level branching in your error handling.
    - `processorCode` (string | null) — Raw error code returned by the upstream processor, unmapped. Useful for support tickets and processor-specific debugging. Most applications should rely on `code` and `declineCode` instead.
    - `processorMessage` (string | null) — Raw error message returned by the upstream processor, unmapped. Useful for support tickets and processor-specific debugging. Most applications should rely on `message` instead.
- `lineItems` (Array<LineItem>) — Line items with full price and product details
  - `id` (string, required) — Line item ID
  - `quantity` (number, required) — Quantity
  - `price` (Price, required) — Price information
    - `id` (string, required) — Price ID
    - `unitAmount` (number) — Price amount in smallest currency unit
    - `currency` (enum("EGP" | "USD" | "EUR" | "GBP" | "SAR" | "AED" | "QAR" | "KWD" | "JOD" | "OMR" | "BHD" | "LYD" | "AUD" | "CAD" | "CNY"), required) — Currency
    - `type` (enum("ONE_TIME" | "RECURRING" | "CUSTOM"), required) — Price type
    - `recurring` (Recurring) — Recurring configuration (for recurring prices)
    - `customUnitAmount` (CustomUnitAmount) — Custom unit amount configuration — present for CUSTOM-type prices
    - `createdAt` (string, required) — Creation timestamp (ISO 8601)
    - `active` (boolean, required) — Whether the price is active. `false` means the merchant archived it.
    - `stock` (number | null) — Remaining stock. `null` means unlimited. Decremented on PaymentIntent success. May go negative under race conditions (oversold).
    - `startDate` (string | null) — Start date (before which the price is not usable in checkout), ISO 8601
    - `expirationDate` (string | null) — Expiration date (at/after which the price is not usable in checkout), ISO 8601
    - `product` (Product, required) — Product associated with this price
  - `adjustableQuantity` (AdjustableQuantity) — Adjustable quantity settings
    - `enabled` (boolean, required) — Whether adjustable quantity is enabled
    - `minimum` (number) — Minimum quantity allowed
    - `maximum` (number) — Maximum quantity allowed
  - `amountSubtotal` (number) — Total before any discounts or taxes (unitAmount × quantity)
  - `amountTotal` (number) — Total after discounts and taxes
  - `amountDiscount` (number) — Discount amount applied to this item
  - `amountTax` (number) — Tax amount applied to this item
  - `currency` (enum("EGP" | "USD" | "EUR" | "GBP" | "SAR" | "AED" | "QAR" | "KWD" | "JOD" | "OMR" | "BHD" | "LYD" | "AUD" | "CAD" | "CNY")) — Currency for the amounts (ISO 4217)
  - `description` (string) — Description from price/product
  - `presentmentDetails` (LineItemPresentmentDetails) — Customer-facing view of this line item. Populated on checkout-session snapshots when the merchant prices in a currency different from processing. Uses the session's locked exchange rate.
    - `unitAmount` (number, required) — Unit amount in presentment smallest unit
    - `amountSubtotal` (number, required) — Line subtotal (unitAmount × quantity) in presentment smallest unit
    - `amountDiscount` (number, required) — Line discount allocated to this item, in presentment smallest unit
    - `amountTotal` (number, required) — Line total after discount + tax, in presentment smallest unit
    - `currency` (enum("EGP" | "USD" | "EUR" | "GBP" | "SAR" | "AED" | "QAR" | "KWD" | "JOD" | "OMR" | "BHD" | "LYD" | "AUD" | "CAD" | "CNY"), required) — Presentment currency for this line — matches session.presentmentDetails.currency
- `customFields` (Array<CustomFieldResponse>) — Custom fields with configuration and collected values (Stripe-aligned). Values are populated after customer submits.
  - `key` (string, required) — Unique key for the field
  - `label` (string, required) — Field label
  - `type` (enum("TEXT" | "NUMBER" | "DROPDOWN" | "CHECKBOX"), required) — Field type
  - `isOptional` (boolean, required) — Whether the field is optional
  - `hasLimits` (boolean) — Whether validation limits are enabled
  - `limitType` (enum("AT_MOST" | "BETWEEN" | "AT_LEAST" | "EXACTLY")) — Type of validation limit
  - `minCharacters` (number) — Minimum number of characters
  - `maxCharacters` (number) — Maximum number of characters
  - `dropdownOptions` (Array<DropdownOptionResponse>) — Dropdown options
    - `label` (string, required) — Option label
  - `text` (CustomFieldTextValue) — Text value (populated after collection)
    - `value` (string, required) — Text value
  - `numeric` (CustomFieldNumericValue) — Numeric value (populated after collection)
    - `value` (string, required) — Numeric value
  - `dropdown` (CustomFieldDropdownValue) — Dropdown value (populated after collection)
    - `value` (string, required) — Selected dropdown value
- `discounts` (Array<[Discount](/en/api-reference/objects/discount)>) — Applied discounts on this session
- `allowPromotionCodes` (boolean, required) — Allow promotion codes
- `nameCollection` (boolean, required) — Collect customer name
- `billingAddressCollection` (boolean, required) — Collect billing address
- `shippingAddressCollection` (boolean, required) — Collect shipping address
- `phoneNumberCollection` (boolean, required) — Collect phone number
- `feeConfig` (FeeConfigResponse) — Fee configuration (tells checkout whether to track BIN and display fees)
  - `feesPassThrough` (boolean, required) — Whether customer pays platform fee (false = merchant pays)
  - `vatCollectionEnabled` (boolean, required) — Whether to collect VAT from customer
  - `vatCollectionRate` (number) — VAT collection rate in basis points (e.g., 1400 = 14%)
  - `source` (enum("session" | "merchant" | "system"), required) — Where this config came from
- `brandingSettings` (BrandingSettingsResponse) — UI customization settings for checkout (colors, spacing, borders, etc.). Fully resolved: merchant defaults merged with session-level overrides. Callers can apply this object directly — no client-side merging required.
  - `colorMode` (enum("light" | "dark" | "system")) — Dark mode preference
  - `borderStyle` (enum("rounded" | "sharp" | "pill")) — Border style for inputs, buttons, cards
  - `spacing` (enum("condensed" | "normal" | "spacious")) — Spacing density
  - `inputSize` (enum("small" | "medium" | "large")) — Input field size
  - `inputStyle` (enum("flat" | "outlined" | "filled")) — Input field style
  - `formLayout` (enum("compact" | "spacious")) — Form layout density
  - `colors` (ColorCustomizationResponse) — Color customization options
    - `primary` (string) — Primary brand color (buttons, links, accents). Hex only, e.g. `#635bff`.
    - `primaryForeground` (string) — Primary foreground (text on primary background). Hex only.
    - `background` (string) — Page background color. Hex only.
    - `foreground` (string) — Main text color. Hex only.
    - `border` (string) — Border color. Hex only.
    - `input` (string) — Input, button, and dropdown border color. Hex only.
    - `ring` (string) — Focus ring color. Hex only.
    - `muted` (string) — Muted/secondary background. Hex only.
    - `mutedForeground` (string) — Muted text color. Hex only.
    - `accent` (string) — Accent background. Hex only.
    - `accentForeground` (string) — Accent text color. Hex only.
    - `destructive` (string) — Destructive/error color. Hex only.
  - `fontFamily` (string) — Font family override
- `locale` (enum("en" | "ar")) — Language the checkout page is displayed in. Resolved from `session.locale`, falling back to your account's `defaultLocale`, then to `en`.
- `paymentMethodTypes` (Array<PaymentMethodTypeResponse>) — Available payment method types with fee estimates
  - `type` (string, required) — Concrete payment method type (e.g., 'card', 'fawry', 'valu')
  - `displayName` (string, required) — Display name for the payment method
  - `category` (string) — UI grouping category (e.g., 'card', 'bnpl', 'kiosk')
  - `minTransactionAmount` (string | null) — Minimum transaction amount in piasters
  - `maxTransactionAmount` (string | null) — Maximum transaction amount in piasters
  - `requiredCustomerFields` (Array<string> | null) — Required customer fields for this payment method
  - `supportsRefund` (boolean) — Whether this payment method supports refunds
  - `supportsPartialRefund` (boolean) — Whether partial refunds are supported
  - `supportsPartialCapture` (boolean) — Whether partial capture is supported
  - `paymentConfirmation` (string) — Whether payment resolves immediately or asynchronously
- `paymentMethodConfigurationId` (string) — ID of the PaymentMethodConfiguration used for this session
- `fees` (FeesResponse) — Fee breakdown (only populated when feesPassThrough or vatCollectionEnabled, and after /update with BIN for cards)
  - `paymentMethodType` (string, required) — Payment method type (e.g., card, fawry, valu)
  - `feeAmount` (number, required) — Platform fee amount (only if feesPassThrough is true)
  - `feePercentage` (number, required) — Fee percentage
  - `vatAmount` (number) — VAT amount (only if vatCollectionEnabled is true)
  - `totalAmount` (number, required) — Total amount customer will pay
  - `cardInfo` (CardInfoResponse) — Card info (only for card payments with BIN)
    - `brand` (string, required) — Card brand (e.g., Visa, Mastercard)
    - `isOnUs` (boolean, required) — Whether this is an on-us transaction (same bank)
    - `isInternational` (boolean, required) — Whether this is an international card
- `customerUpdate` (CustomerUpdateResponse) — Controls which customer fields to update when customerId is provided
  - `address` (enum("auto" | "never")) — Whether to save address to customer.address
  - `name` (enum("auto" | "never")) — Whether to save name to customer.name
  - `shipping` (enum("auto" | "never")) — Whether to save shipping to customer.shipping
- `metadata` (object) — Custom metadata
- `merchantId` (string, required) — Merchant ID
- `merchantName` (string) — Merchant display name
- `merchantLogo` (string) — Merchant logo URL
- `paymentLinkId` (string) — Payment Link ID (if created from link)
- `livemode` (boolean, required) — Whether this is a live mode session

#### 400 — Invalid checkout session payload: missing or invalid line items, currency mismatch across line items, or both `customerId` and `customerDetails` provided.

Content type: `application/json`

- `error` (ApiErrorBody, required) — The structured error body. See `ApiErrorBody` for field semantics.
  - `type` (enum("invalid_request_error" | "authentication_error" | "rate_limit_error" | "api_error" | "card_error" | "idempotency_error"), required) — High-level error category. Use this for branching at the top level of your error handler (e.g. retry on `api_error`, surface a card decline on `card_error`).
  - `code` (enum("invalid_request" | "parameter_out_of_range" | "parameter_invalid" | "parameter_missing" | "parameter_unknown" | "parameters_exclusive" | "parameter_requires_another" | "validation_error" | "resource_missing" | "resource_invalid_state" | "resource_already_exists" | "resource_in_use" | "authentication_required" | "invalid_api_key" | "api_key_inactive" | "invalid_signature" | "merchant_not_activated" | "permission_denied" | "two_factor_required" | "checkout_session_expired" | "invalid_client_secret" | "creation_failed" | "payment_still_confirming" | "payment_already_completed" | "payment_link_inactive" | "payment_link_expired" | "amount_invalid" | "currency_invalid" | "product_archived" | "price_inactive" | "price_not_yet_active" | "price_expired" | "price_sold_out" | "price_date_range_invalid" | "price_stock_invalid" | "price_recurring_not_supported" | "price_immutable_while_used" | "line_item_missing_price" | "checkout_empty_cart" | "promotion_codes_not_allowed" | "promotion_code_not_found" | "promotion_code_inactive" | "promotion_code_expired" | "promotion_code_max_redemptions" | "promotion_code_customer_mismatch" | "promotion_code_minimum_amount" | "promotion_code_first_time_only" | "coupon_invalid" | "coupon_currency_mismatch" | "coupon_minimum_amount" | "coupon_customer_max_redemptions" | "too_many_discounts" | "payment_method_corrupted" | "payment_method_customer_mismatch" | "payment_intent_customer_mismatch" | "payment_method_mismatch" | "charge_not_captured" | "merchant_no_balance" | "insufficient_balance" | "charge_missing_balance_transaction" | "charge_missing_fee_data" | "charge_incomplete_fee_data" | "cannot_rename_default" | "must_have_enabled_method" | "cannot_delete_default" | "configuration_in_use" | "unsupported_currency" | "exchange_rate_not_found" | "coupon_in_use" | "promotion_code_exists" | "rate_limit" | "idempotency_key_in_use" | "internal_error" | "request_timeout")) — Stable, machine-readable code identifying the specific failure (e.g. `resource_missing`, `parameter_invalid`, `authentication_required`). Always present on documented errors. See the API Error Codes reference for the full list.
  - `message` (string, required) — Human-readable description of what went wrong. Safe to log or display, but not stable — use `code` for programmatic branching.
  - `param` (string) — Name of the request parameter that caused the error, when applicable (e.g. `amount`, `currency`).
  - `doc_url` (string) — URL to the documentation page for this specific error code. Deep-linked into the API Error Codes reference.
- `request_id` (string) — Unique identifier for this request, propagated to logs and traces. Include it when contacting support.

#### 401 — Authentication is required and the request did not present a valid API key.

Content type: `application/json`

- `error` (ApiErrorBody, required) — The structured error body. See `ApiErrorBody` for field semantics.
  - `type` (enum("invalid_request_error" | "authentication_error" | "rate_limit_error" | "api_error" | "card_error" | "idempotency_error"), required) — High-level error category. Use this for branching at the top level of your error handler (e.g. retry on `api_error`, surface a card decline on `card_error`).
  - `code` (enum("invalid_request" | "parameter_out_of_range" | "parameter_invalid" | "parameter_missing" | "parameter_unknown" | "parameters_exclusive" | "parameter_requires_another" | "validation_error" | "resource_missing" | "resource_invalid_state" | "resource_already_exists" | "resource_in_use" | "authentication_required" | "invalid_api_key" | "api_key_inactive" | "invalid_signature" | "merchant_not_activated" | "permission_denied" | "two_factor_required" | "checkout_session_expired" | "invalid_client_secret" | "creation_failed" | "payment_still_confirming" | "payment_already_completed" | "payment_link_inactive" | "payment_link_expired" | "amount_invalid" | "currency_invalid" | "product_archived" | "price_inactive" | "price_not_yet_active" | "price_expired" | "price_sold_out" | "price_date_range_invalid" | "price_stock_invalid" | "price_recurring_not_supported" | "price_immutable_while_used" | "line_item_missing_price" | "checkout_empty_cart" | "promotion_codes_not_allowed" | "promotion_code_not_found" | "promotion_code_inactive" | "promotion_code_expired" | "promotion_code_max_redemptions" | "promotion_code_customer_mismatch" | "promotion_code_minimum_amount" | "promotion_code_first_time_only" | "coupon_invalid" | "coupon_currency_mismatch" | "coupon_minimum_amount" | "coupon_customer_max_redemptions" | "too_many_discounts" | "payment_method_corrupted" | "payment_method_customer_mismatch" | "payment_intent_customer_mismatch" | "payment_method_mismatch" | "charge_not_captured" | "merchant_no_balance" | "insufficient_balance" | "charge_missing_balance_transaction" | "charge_missing_fee_data" | "charge_incomplete_fee_data" | "cannot_rename_default" | "must_have_enabled_method" | "cannot_delete_default" | "configuration_in_use" | "unsupported_currency" | "exchange_rate_not_found" | "coupon_in_use" | "promotion_code_exists" | "rate_limit" | "idempotency_key_in_use" | "internal_error" | "request_timeout")) — Stable, machine-readable code identifying the specific failure (e.g. `resource_missing`, `parameter_invalid`, `authentication_required`). Always present on documented errors. See the API Error Codes reference for the full list.
  - `message` (string, required) — Human-readable description of what went wrong. Safe to log or display, but not stable — use `code` for programmatic branching.
  - `param` (string) — Name of the request parameter that caused the error, when applicable (e.g. `amount`, `currency`).
  - `doc_url` (string) — URL to the documentation page for this specific error code. Deep-linked into the API Error Codes reference.
- `request_id` (string) — Unique identifier for this request, propagated to logs and traces. Include it when contacting support.

#### 403 — The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.

Content type: `application/json`

- `error` (ApiErrorBody, required) — The structured error body. See `ApiErrorBody` for field semantics.
  - `type` (enum("invalid_request_error" | "authentication_error" | "rate_limit_error" | "api_error" | "card_error" | "idempotency_error"), required) — High-level error category. Use this for branching at the top level of your error handler (e.g. retry on `api_error`, surface a card decline on `card_error`).
  - `code` (enum("invalid_request" | "parameter_out_of_range" | "parameter_invalid" | "parameter_missing" | "parameter_unknown" | "parameters_exclusive" | "parameter_requires_another" | "validation_error" | "resource_missing" | "resource_invalid_state" | "resource_already_exists" | "resource_in_use" | "authentication_required" | "invalid_api_key" | "api_key_inactive" | "invalid_signature" | "merchant_not_activated" | "permission_denied" | "two_factor_required" | "checkout_session_expired" | "invalid_client_secret" | "creation_failed" | "payment_still_confirming" | "payment_already_completed" | "payment_link_inactive" | "payment_link_expired" | "amount_invalid" | "currency_invalid" | "product_archived" | "price_inactive" | "price_not_yet_active" | "price_expired" | "price_sold_out" | "price_date_range_invalid" | "price_stock_invalid" | "price_recurring_not_supported" | "price_immutable_while_used" | "line_item_missing_price" | "checkout_empty_cart" | "promotion_codes_not_allowed" | "promotion_code_not_found" | "promotion_code_inactive" | "promotion_code_expired" | "promotion_code_max_redemptions" | "promotion_code_customer_mismatch" | "promotion_code_minimum_amount" | "promotion_code_first_time_only" | "coupon_invalid" | "coupon_currency_mismatch" | "coupon_minimum_amount" | "coupon_customer_max_redemptions" | "too_many_discounts" | "payment_method_corrupted" | "payment_method_customer_mismatch" | "payment_intent_customer_mismatch" | "payment_method_mismatch" | "charge_not_captured" | "merchant_no_balance" | "insufficient_balance" | "charge_missing_balance_transaction" | "charge_missing_fee_data" | "charge_incomplete_fee_data" | "cannot_rename_default" | "must_have_enabled_method" | "cannot_delete_default" | "configuration_in_use" | "unsupported_currency" | "exchange_rate_not_found" | "coupon_in_use" | "promotion_code_exists" | "rate_limit" | "idempotency_key_in_use" | "internal_error" | "request_timeout")) — Stable, machine-readable code identifying the specific failure (e.g. `resource_missing`, `parameter_invalid`, `authentication_required`). Always present on documented errors. See the API Error Codes reference for the full list.
  - `message` (string, required) — Human-readable description of what went wrong. Safe to log or display, but not stable — use `code` for programmatic branching.
  - `param` (string) — Name of the request parameter that caused the error, when applicable (e.g. `amount`, `currency`).
  - `doc_url` (string) — URL to the documentation page for this specific error code. Deep-linked into the API Error Codes reference.
- `request_id` (string) — Unique identifier for this request, propagated to logs and traces. Include it when contacting support.

#### 404 — One or more referenced resources (price, product, customer, coupon) do not exist.

Content type: `application/json`

- `error` (ApiErrorBody, required) — The structured error body. See `ApiErrorBody` for field semantics.
  - `type` (enum("invalid_request_error" | "authentication_error" | "rate_limit_error" | "api_error" | "card_error" | "idempotency_error"), required) — High-level error category. Use this for branching at the top level of your error handler (e.g. retry on `api_error`, surface a card decline on `card_error`).
  - `code` (enum("invalid_request" | "parameter_out_of_range" | "parameter_invalid" | "parameter_missing" | "parameter_unknown" | "parameters_exclusive" | "parameter_requires_another" | "validation_error" | "resource_missing" | "resource_invalid_state" | "resource_already_exists" | "resource_in_use" | "authentication_required" | "invalid_api_key" | "api_key_inactive" | "invalid_signature" | "merchant_not_activated" | "permission_denied" | "two_factor_required" | "checkout_session_expired" | "invalid_client_secret" | "creation_failed" | "payment_still_confirming" | "payment_already_completed" | "payment_link_inactive" | "payment_link_expired" | "amount_invalid" | "currency_invalid" | "product_archived" | "price_inactive" | "price_not_yet_active" | "price_expired" | "price_sold_out" | "price_date_range_invalid" | "price_stock_invalid" | "price_recurring_not_supported" | "price_immutable_while_used" | "line_item_missing_price" | "checkout_empty_cart" | "promotion_codes_not_allowed" | "promotion_code_not_found" | "promotion_code_inactive" | "promotion_code_expired" | "promotion_code_max_redemptions" | "promotion_code_customer_mismatch" | "promotion_code_minimum_amount" | "promotion_code_first_time_only" | "coupon_invalid" | "coupon_currency_mismatch" | "coupon_minimum_amount" | "coupon_customer_max_redemptions" | "too_many_discounts" | "payment_method_corrupted" | "payment_method_customer_mismatch" | "payment_intent_customer_mismatch" | "payment_method_mismatch" | "charge_not_captured" | "merchant_no_balance" | "insufficient_balance" | "charge_missing_balance_transaction" | "charge_missing_fee_data" | "charge_incomplete_fee_data" | "cannot_rename_default" | "must_have_enabled_method" | "cannot_delete_default" | "configuration_in_use" | "unsupported_currency" | "exchange_rate_not_found" | "coupon_in_use" | "promotion_code_exists" | "rate_limit" | "idempotency_key_in_use" | "internal_error" | "request_timeout")) — Stable, machine-readable code identifying the specific failure (e.g. `resource_missing`, `parameter_invalid`, `authentication_required`). Always present on documented errors. See the API Error Codes reference for the full list.
  - `message` (string, required) — Human-readable description of what went wrong. Safe to log or display, but not stable — use `code` for programmatic branching.
  - `param` (string) — Name of the request parameter that caused the error, when applicable (e.g. `amount`, `currency`).
  - `doc_url` (string) — URL to the documentation page for this specific error code. Deep-linked into the API Error Codes reference.
- `request_id` (string) — Unique identifier for this request, propagated to logs and traces. Include it when contacting support.

#### 500 — Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.

Content type: `application/json`

- `error` (ApiErrorBody, required) — The structured error body. See `ApiErrorBody` for field semantics.
  - `type` (enum("invalid_request_error" | "authentication_error" | "rate_limit_error" | "api_error" | "card_error" | "idempotency_error"), required) — High-level error category. Use this for branching at the top level of your error handler (e.g. retry on `api_error`, surface a card decline on `card_error`).
  - `code` (enum("invalid_request" | "parameter_out_of_range" | "parameter_invalid" | "parameter_missing" | "parameter_unknown" | "parameters_exclusive" | "parameter_requires_another" | "validation_error" | "resource_missing" | "resource_invalid_state" | "resource_already_exists" | "resource_in_use" | "authentication_required" | "invalid_api_key" | "api_key_inactive" | "invalid_signature" | "merchant_not_activated" | "permission_denied" | "two_factor_required" | "checkout_session_expired" | "invalid_client_secret" | "creation_failed" | "payment_still_confirming" | "payment_already_completed" | "payment_link_inactive" | "payment_link_expired" | "amount_invalid" | "currency_invalid" | "product_archived" | "price_inactive" | "price_not_yet_active" | "price_expired" | "price_sold_out" | "price_date_range_invalid" | "price_stock_invalid" | "price_recurring_not_supported" | "price_immutable_while_used" | "line_item_missing_price" | "checkout_empty_cart" | "promotion_codes_not_allowed" | "promotion_code_not_found" | "promotion_code_inactive" | "promotion_code_expired" | "promotion_code_max_redemptions" | "promotion_code_customer_mismatch" | "promotion_code_minimum_amount" | "promotion_code_first_time_only" | "coupon_invalid" | "coupon_currency_mismatch" | "coupon_minimum_amount" | "coupon_customer_max_redemptions" | "too_many_discounts" | "payment_method_corrupted" | "payment_method_customer_mismatch" | "payment_intent_customer_mismatch" | "payment_method_mismatch" | "charge_not_captured" | "merchant_no_balance" | "insufficient_balance" | "charge_missing_balance_transaction" | "charge_missing_fee_data" | "charge_incomplete_fee_data" | "cannot_rename_default" | "must_have_enabled_method" | "cannot_delete_default" | "configuration_in_use" | "unsupported_currency" | "exchange_rate_not_found" | "coupon_in_use" | "promotion_code_exists" | "rate_limit" | "idempotency_key_in_use" | "internal_error" | "request_timeout")) — Stable, machine-readable code identifying the specific failure (e.g. `resource_missing`, `parameter_invalid`, `authentication_required`). Always present on documented errors. See the API Error Codes reference for the full list.
  - `message` (string, required) — Human-readable description of what went wrong. Safe to log or display, but not stable — use `code` for programmatic branching.
  - `param` (string) — Name of the request parameter that caused the error, when applicable (e.g. `amount`, `currency`).
  - `doc_url` (string) — URL to the documentation page for this specific error code. Deep-linked into the API Error Codes reference.
- `request_id` (string) — Unique identifier for this request, propagated to logs and traces. Include it when contacting support.