> ## 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.

# Key concepts

> How a payment moves through Ionic, how its objects connect, and how each status changes.

Every Ionic payment follows one lifecycle, whether the buyer pays on a hosted
page, in [Ionic Blocks](/blocks/overview), or at a terminal. Learn it once and every product works
the same way.

## The lifecycle of a payment

Every payment moves through the same five stages.

<Steps>
  <Step title="Create">
    Your server creates the payment and sets the amount: a [checkout session](/checkout/overview)
    for a hosted page, or a PaymentIntent for Ionic Blocks and terminals.
  </Step>

  <Step title="Collect the card">
    The buyer enters a card on Ionic's hosted page, in the secure inputs of
    Ionic Blocks, or on a terminal. Card numbers stay with Ionic, and your
    server works with IDs such as `pi_…` and `pm_…`. Ionic Blocks uses a
    publishable key and the intent's client secret, which authorizes that one
    intent.
  </Step>

  <Step title="Authorize">
    Ionic sends the payment to the card issuer for approval, and records each
    attempt as a Charge. A decline records a decline code on the Charge, such
    as `insufficient_funds`, and returns the PaymentIntent to
    `requires_payment_method` so the buyer can try another card. See
    [Decline codes](/api-reference/decline-codes).
  </Step>

  <Step title="Capture">
    With automatic capture, an approved payment completes at once and the
    PaymentIntent becomes `succeeded`. With manual capture, it waits in
    `requires_capture` until you capture the funds or cancel to release the
    hold. Terminal payments always capture automatically.
  </Step>

  <Step title="Notify">
    Ionic sends signed events, such as `checkout.session.completed` and
    `payment_intent.succeeded`, to your webhook endpoint. Fulfill the order
    from a verified event; the browser redirect only updates the buyer's
    screen. Events arrive at least once and in no guaranteed order, so
    deduplicate on the event `id`. See [Webhooks](/webhooks/overview).
  </Step>
</Steps>

After the payment, a Refund returns all or part of a succeeded Charge.

## How the objects connect

```mermaid theme={null}
flowchart TD
  PL["Payment link"] -->|opens| CS["Checkout session"]
  CU["Customer"] -->|owns| PM["PaymentMethod"]
  SI["SetupIntent"] -->|saves| PM
  CS -->|creates| PI["PaymentIntent"]
  TP["Terminal payment"] -->|processes| PI
  PM -->|pays| PI
  PI -->|each attempt| CH["Charge"]
  CH -->|money returned| RF["Refund"]
```

| Object | Represents | Created by |
| - | - | - |
| PaymentIntent (`pi_…`) | One payment, from creation to completion | Your server, or a checkout session when the buyer pays |
| Charge (`ch_…`) | One attempt to charge a payment method | Ionic, when a PaymentIntent is confirmed |
| Refund (`rf_…`) | Money returned from a charge | Your server |
| Checkout session (`cs_…`) | A purchase on an Ionic-hosted page | Your server, or a buyer opening a payment link |
| Customer (`cus_…`) | A buyer you charge again | Your server |
| PaymentMethod (`pm_…`) | A saved card that belongs to a customer | A SetupIntent, or a payment that saves the card |
| SetupIntent | Saving a card without taking a payment | Your server |
| Event (`evt_…`) | A change delivered to your webhook endpoint | Ionic |

Amounts are integers in the currency's minor unit, so an `amount` of `2500` in
`usd` is \$25.00.

## How payment status changes

```mermaid theme={null}
stateDiagram-v2
  [*] --> requires_payment_method
  requires_payment_method --> requires_confirmation: payment method attached
  requires_confirmation --> processing: confirmed
  processing --> succeeded: approved
  processing --> requires_capture: approved, manual capture
  processing --> requires_payment_method: declined or failed
  requires_capture --> succeeded: captured
  requires_capture --> canceled: canceled
  succeeded --> [*]
  canceled --> [*]
```

A PaymentIntent in `requires_payment_method` or `requires_confirmation` can
also be canceled, which ends it in `canceled`.

| PaymentIntent status | Meaning | Your next step |
| - | - | - |
| `requires_payment_method` | Waiting for card details, or the last attempt was declined | Collect a card, or ask the buyer to try another |
| `requires_confirmation` | A payment method is attached | Confirm the PaymentIntent |
| `processing` | An attempt is in progress | Wait for the result or the next event |
| `requires_capture` | Approved with manual capture | Capture the funds, or cancel to release the hold |
| `succeeded` | The payment completed | Fulfill the order |
| `canceled` | The payment can no longer complete | Create a new PaymentIntent to try again |

A confirmation that returns `502 GATEWAY_ERROR` was not processed, so no money
moved. The PaymentIntent returns to `requires_confirmation`, or to
`requires_payment_method` when the card must be entered again. Ionic does not
run 3-D Secure today, so PaymentIntents do not enter `requires_action`.

| Charge status | Meaning |
| - | - |
| `pending` | The attempt is in progress. |
| `authorized` | Approved and waiting for capture. |
| `succeeded` | Captured. |
| `declined` | The issuer declined. `decline_code` says why. |
| `failed` | The attempt could not be processed. |
| `uncertain` | The outcome is not known yet. Retrieve the Charge before retrying. |
| `voided` | The authorization was released before capture. |
| `refunded` | The full amount was refunded. |

A Refund is `pending` while it is processed, then `succeeded` or `failed`, or
`uncertain` until its outcome is known. A checkout session stays `open` until
the buyer pays and it becomes `complete`, or until it expires and becomes
`expired`. Its `payment_intent_id` is set when the session is confirmed.
Fulfill a session when its `status` is `complete` and its `payment_status` is
`paid`. See [Payment flow](/concepts/payment-flow) for each collection path.

## Test mode and live mode

Every key belongs to one mode, shown in its prefix: `sk_v1_test_` or
`sk_v1_live_`. Test and live data are fully isolated, so customers, webhook
endpoints, and object IDs exist in one mode only. Objects and events carry
`livemode`.

Test mode moves no money. Test cards return simulated results, and every test
account includes simulated terminals. See [Test cards](/guides/test-cards).

## Keys and permissions

Secret keys authenticate requests from your server. Restricted secret keys
limit a key to the permissions you select, and publishable keys run in the
browser. A key without the permission an operation needs receives `403`. See
[Authentication](/guides/authentication).

## Safe retries

Send an `Idempotency-Key` with each create and money-moving `POST`. A retry
with the same key and body returns the original result instead of repeating
the operation, so a timeout or a double click does not charge twice. The same
key with a different body or endpoint returns `422`.

When a request times out, retrieve the object before creating it again. See
[Reliable API requests](/concepts/reliability-model) and
[Idempotency](/api-reference/idempotency).

## Platforms and connected accounts

With Connect, a platform acts for the businesses that connect to it. The
platform authenticates with its own key and names one connected account per
request with the `Ionic-Account` header. That account owns everything the
request creates. Each request needs its permission on the platform key, on the
account's connection, and within the Platform Program. Platform webhook events
carry an `account` field that names the connected account. See
[How Connect works](/guides/connect-overview).

## In-person payments

A location holds terminals, and a terminal payment records each attempt to
process a PaymentIntent at the counter. Each terminal reports its setup,
connection, and capability states independently. See
[The Terminal object](/concepts/terminal-object).

## What's next

<CardGroup cols={2}>
  <Card title="Payment flow" icon="diagram-project" href="/concepts/payment-flow">
    Choose a collection flow and see what your server does at each step.
  </Card>

  <Card title="Reliable API requests" icon="shield-check" href="/concepts/reliability-model">
    Retry safely and recover when a response does not arrive.
  </Card>

  <Card title="Test cards" icon="credit-card" href="/guides/test-cards">
    See the card numbers and behaviors that test mode supports.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.