> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ionicfi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Confirm a payment intent

> Attempts the charge using exactly one of `payment_method` or
`payment_token`. With automatic capture a success moves the intent to
`succeeded`; with manual capture it moves to `requires_capture`. A
decline returns `402` with the intent embedded. Send an `Idempotency-Key`
header so a retry never charges twice.




## OpenAPI

````yaml /openapi/payments.yaml post /payment_intents/{id}/confirm
openapi: 3.0.3
info:
  title: Ionic Payments API
  version: '2026-05-01'
  description: |
    Payment intents, charges, and refunds — the money-movement core.

    A payment intent (`pi_…`) tracks one payment. Create it with an amount and
    currency, then confirm it with a payment method or one-time payment token.
    Each confirmation creates a Charge; after a decline, confirm the same
    PaymentIntent again with a different payment method. With
    `capture_method: automatic` (the default) a successful
    confirmation captures immediately; with `manual` it authorizes, and you
    capture later. A Charge (`ch_…`) records one confirmation attempt, and
    `latest_charge_id` points to the most recent one. A Refund (`rf_…`) returns
    captured funds from a Charge.

    All monetary amounts are integers in the currency's minor unit (for example
    cents for USD). Timestamps are Unix epoch seconds. Identifiers are opaque,
    prefixed strings.

    Authentication uses a merchant secret key (`sk_…`) as a bearer token. Read
    endpoints require the `payments:read` permission; write endpoints require
    `payments:write`. The mode of the key (test or live) scopes which resources
    it can see and mutate, and is reflected by each resource's `livemode` field.
    Confirming and retrieving an intent additionally accept a publishable key
    (`pk_…`) together with the intent's `client_secret`, for client-side flows;
    every other endpoint is secret-key only. Send an `Idempotency-Key` header on
    create, confirm, capture, and cancel so retries do not duplicate an
    operation.

    Errors are returned as `{ "error": { "code": "...", "message": "..." } }`.
    Payment-specific failures carry extra fields: a card decline returns `402`
    with `type: card_error`, a `decline_code`, a `decline_type`, and a
    `retryable` flag, and embeds the current payment intent so you can inspect
    its status without a second call.
servers:
  - url: '{baseUrl}/v1'
    variables:
      baseUrl:
        default: https://api.ionicfi.com
        description: API base URL for your environment.
security:
  - secretKey: []
tags:
  - name: Payment Intents
    description: Create, confirm, capture, and cancel attempts to collect money.
  - name: Charges
    description: Records of individual PaymentIntent confirmation attempts.
  - name: Refunds
    description: Reversals of captured funds on a charge.
paths:
  /payment_intents/{id}/confirm:
    parameters:
      - $ref: '#/components/parameters/PaymentIntentId'
    post:
      tags:
        - Payment Intents
      summary: Confirm a payment intent
      description: >
        Attempts the charge using exactly one of `payment_method` or

        `payment_token`. With automatic capture a success moves the intent to

        `succeeded`; with manual capture it moves to `requires_capture`. A

        decline returns `402` with the intent embedded. Send an
        `Idempotency-Key`

        header so a retry never charges twice.
      operationId: payment_intents_confirm
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfirmPaymentIntentRequest'
      responses:
        '200':
          description: The confirmed payment intent.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaymentIntent'
                  - type: object
                    properties:
                      saved_payment_method:
                        type: string
                        nullable: true
                        description: >-
                          Only present when `save_card` was requested: the id of
                          the reusable payment method saved for the intent's
                          customer, or `null` when the save was skipped (no
                          customer) or failed. The charge outcome is independent
                          of this field.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/Declined'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/PaymentIntentNotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - secretKey:
            - payments:write
components:
  parameters:
    PaymentIntentId:
      name: id
      in: path
      required: true
      description: The payment intent id (`pi_…`).
      schema:
        type: string
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >-
        A unique key that makes retries safe: the same key with the same request
        body returns the original response instead of repeating the operation.
      schema:
        type: string
        maxLength: 255
  schemas:
    ConfirmPaymentIntentRequest:
      type: object
      description: Confirm with exactly one of `payment_method` or `payment_token`.
      properties:
        payment_method:
          type: string
          description: A saved payment method id (`pm_…`).
        payment_token:
          type: string
          description: A single-use payment token created by the client-side card form.
        mandate:
          type: string
          description: Mandate id authorizing a merchant-initiated charge.
        client_secret:
          type: string
          description: Required when confirming with a publishable key.
        initiated_by:
          type: string
          enum:
            - customer
            - merchant
          description: '`merchant` requires a secret key.'
        billing_details:
          type: object
          nullable: true
          description: >-
            Only valid with `payment_token`. The details are attached to the
            single-use payment method created from the token, and the address
            feeds AVS on the authorization. Rejected when `payment_method` is
            used.
          properties:
            name:
              type: string
              description: Cardholder name. Optional.
            email:
              type: string
              description: Email address; format-validated when supplied. Optional.
            phone:
              type: string
              description: Phone number. Optional.
            address:
              type: object
              nullable: true
              required:
                - postal_code
                - country
              description: >-
                Billing address for AVS. `postal_code` and a two-letter
                `country` are required when an address is supplied; other fields
                are optional.
              properties:
                line1:
                  type: string
                  description: The street address. Optional.
                line2:
                  type: string
                  nullable: true
                  description: The secondary address line. Optional.
                city:
                  type: string
                  description: The city. Optional.
                state:
                  type: string
                  description: The state or province. Optional.
                postal_code:
                  type: string
                  description: The postal code. Required when an address is supplied.
                country:
                  type: string
                  description: >-
                    The two-letter ISO 3166-1 alpha-2 country code. Required
                    when an address is supplied.
        save_card:
          type: boolean
          description: >-
            Save the card as this charge runs, creating a reusable payment
            method for the intent's customer. Only takes effect with
            `payment_token` and a customer on the intent; ignored otherwise.
            Consent details are recorded from `customer_acceptance`.
        customer_acceptance:
          type: object
          nullable: true
          description: >-
            How consent to store the card was captured. Only read when
            `save_card` is true. Omitted or `online` records the request IP and
            user agent; send `offline` for MOTO keyed entry when the buyer is
            not using this browser.
          properties:
            type:
              type: string
              enum:
                - online
                - offline
              description: The acceptance channel.
    PaymentIntent:
      type: object
      required:
        - amount
        - capture_method
        - client_secret
        - created_at
        - currency
        - customer
        - id
        - latest_charge_id
        - livemode
        - merchant_id
        - metadata
        - object
        - payment_method
        - status
        - updated_at
      properties:
        id:
          type: string
          description: The payment intent id (`pi_…`).
        object:
          type: string
          enum:
            - payment_intent
          description: Always `payment_intent`.
        merchant_id:
          type: string
          description: The owning merchant (`mer_…`).
        livemode:
          type: boolean
          description: >-
            Whether this intent was created with a live (`true`) or test
            (`false`) key.
        client_secret:
          type: string
          nullable: true
          description: >-
            Returned when the intent is created or confirmed; null on capture,
            cancel, and list responses.
        tokenization:
          allOf:
            - $ref: '#/components/schemas/TokenizationConfig'
          nullable: true
          description: >-
            Browser-safe card-fields configuration returned with `client_secret`
            on publishable-key requests. Null when card collection is not
            available.
        customer:
          type: string
          nullable: true
          description: >-
            The attached customer (`cus_…`). Null unless a customer was passed
            at creation.
        amount:
          type: integer
          description: The amount to collect, in minor units. Always positive.
        currency:
          type: string
          description: Three-letter ISO currency code. USD, EUR, and GBP are supported.
        capture_method:
          type: string
          enum:
            - automatic
            - manual
          description: >-
            `automatic` captures the charge on confirmation. `manual` authorizes
            a hold; capture it later via `POST /payment_intents/{id}/capture`.
        status:
          type: string
          enum:
            - requires_payment_method
            - requires_confirmation
            - requires_action
            - requires_capture
            - processing
            - succeeded
            - canceled
          description: >-
            One of `requires_payment_method` (collect or attach a payment
            method), `requires_confirmation` (ready to confirm), `processing`
            (payment is in progress), `requires_action` (the buyer must complete
            another step), `requires_capture` (authorized and awaiting manual
            capture), `succeeded` (payment completed), or `canceled` (payment
            can no longer be completed).
        payment_method:
          type: string
          nullable: true
          description: >-
            The attached payment method (`pm_…`). Nullable; cleared on a decline
            so a retry can attach a different method.
        latest_charge_id:
          type: string
          nullable: true
          description: The most recent charge produced by this intent (`ch_…`).
        reference:
          type: string
          description: Your order number or other reference. Max 256 characters.
        metadata:
          type: object
          additionalProperties:
            type: string
          description: >-
            A string key-value map for storing your own structured data. Up to
            50 keys; each key at most 40 characters and each value at most 500
            characters.
        created_at:
          type: integer
          description: Unix epoch seconds.
        updated_at:
          type: integer
          description: Unix epoch seconds, bumped on every mutation.
    TokenizationConfig:
      type: object
      description: Browser-safe configuration for initializing hosted card fields.
      required:
        - provider
        - tokenization_key
      properties:
        provider:
          type: string
          description: >-
            Reserved for the Ionic browser SDK. Do not inspect or configure this
            value.
        tokenization_key:
          type: string
          description: >-
            A browser-safe public key used to create a one-time payment token.
            It cannot submit a charge.
    Error:
      type: object
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'
    PaymentError:
      type: object
      description: >-
        An error that embeds the current payment intent so you can inspect its
        status.
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'
        payment_intent:
          $ref: '#/components/schemas/PaymentIntent'
    ErrorDetail:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
        message:
          type: string
        type:
          type: string
          enum:
            - card_error
            - invalid_request_error
            - api_error
        decline_code:
          type: string
        decline_type:
          type: string
          enum:
            - authorization
            - authentication
            - infrastructure
        retryable:
          type: boolean
          description: >-
            Whether the underlying condition may resolve on its own over time —
            for example available funds being deposited or a velocity window
            resetting. `true` does not mean the request is safe to retry
            immediately.
        doc_url:
          type: string
  responses:
    BadRequest:
      description: The request was malformed or failed validation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INVALID_REQUEST
              message: invalid currency
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Declined:
      description: The card was declined. The error embeds the current payment intent.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PaymentError'
          example:
            error:
              type: card_error
              code: PAYMENT_DECLINED
              message: Your card was declined.
              decline_code: insufficient_funds
              decline_type: authorization
              retryable: false
            payment_intent:
              id: pi_2pXq
              object: payment_intent
              merchant_id: mer_7kRzDef
              livemode: false
              client_secret: null
              customer: null
              amount: 5000
              currency: USD
              capture_method: automatic
              status: requires_payment_method
              payment_method: null
              latest_charge_id: null
              metadata: {}
              created_at: 1700000000
              updated_at: 1700000000
    Forbidden:
      description: The key lacks the required permission, or the merchant is not active.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    PaymentIntentNotFound:
      description: No payment intent with that id is visible to this key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: PAYMENT_INTENT_NOT_FOUND
              message: payment intent not found
    RateLimited:
      description: Too many requests. Honour the `Retry-After` header before retrying.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalError:
      description: |
        The API could not return a successful response. For a mutating request,
        retrieve the resource before retrying because the operation may have
        completed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    secretKey:
      type: http
      scheme: bearer
      description: 'A merchant secret key (`sk_…`) sent as `Authorization: Bearer <key>`.'

````