# Payment Intent (/en/api-reference/objects/payment-intent)

A PaymentIntent tracks the full lifecycle of collecting one payment from your customer: from creation, through authorization and 3-D Secure, to capture and final outcome. We recommend creating one PaymentIntent per order: you can inspect its history of Charge attempts, watch its `status` as it transitions, and reference the successful Charge it ultimately produces. PaymentIntents are the object that the hosted Checkout and xpay.js drive on the client to complete a payment.

## Fields

- `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.
- `checkoutSession` (NestedCheckoutSessionResponse) — The CheckoutSession that created this payment, or `null` if the payment was not created via a session. The session's own `paymentIntent` field is not included here to keep the response self-contained.
  - `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
    - `shipping` (ShippingResponse) — Customer shipping details
    - `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
    - `shipping` (ShippingResponse) — Shipping details
  - `paymentIntentId` (string) — Payment Intent ID
  - `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
    - `adjustableQuantity` (AdjustableQuantity) — Adjustable quantity settings
    - `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.
  - `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
    - `text` (CustomFieldTextValue) — Text value (populated after collection)
    - `numeric` (CustomFieldNumericValue) — Numeric value (populated after collection)
    - `dropdown` (CustomFieldDropdownValue) — Dropdown value (populated after collection)
  - `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
    - `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)
  - `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
- `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.
    - `city` (string, required)
    - `country` (string, required)
    - `line1` (string, required)
    - `line2` (string, required)
    - `postalCode` (string, required)
    - `state` (string, required)
  - `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.
    - `amount` (number, required) — Tax amount charged on this payment, in the smallest currency unit (e.g. piasters for EGP).
    - `rateBps` (number, required) — Tax rate applied, in basis points (1% = 100 bps). For example, `1400` means 14%.
  - `platformFees` (AmountDetailsPlatformFees) — Platform fee breakdown for this payment. `null` if not surfaced to the customer.
    - `amount` (number, required) — Platform fee charged by XPay on this payment, in the smallest currency unit.
    - `vatAmount` (number, required) — VAT charged on the platform fee itself, in the smallest currency unit.
  - `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)
    - `brand` (string, required)
    - `country` (string, required)
    - `displayBrand` (string, required)
    - `expMonth` (number, required)
    - `expYear` (number, required)
    - `fingerprint` (string, required)
    - `funding` (string, required)
    - `last4` (string, required)
    - `networks` (object, required)
    - `regulatedStatus` (string, required)
    - `threeDSecureUsage` (ThreeDSecureUsage, required)
    - `wallet` (Wallet, required)
  - `valu` (ValuDetails) — ValU details (if type is 'valu')
    - `loanNumber` (string | null) — Loan number from the provider
    - `tenure` (number | null) — Loan tenure in months
    - `emi` (string | null) — Monthly installment amount
    - `downPayment` (string | null) — Down payment amount
    - `financedAmount` (string | null) — Total financed amount
    - `firstEmiDueDate` (string | null) — First EMI due date
    - `lastInstallmentDate` (string | null) — Last installment date
  - `billingDetails` (BillingDetails, required)
    - `address` (Address, required)
    - `email` (string, required)
    - `name` (string, required)
    - `phone` (string, 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.
    - `url` (string, required) — URL to redirect the customer to in order to complete the next step (typically 3-D Secure).
    - `returnUrl` (string | null) — URL the customer is sent back to after completing the redirect step. `null` if no return URL was configured.
- `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.