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

> ## Agent Instructions
> When building application code, use `@naturalpay/sdk` for TypeScript or `naturalpay` for Python.
> When operating Natural directly for a user, use the payments MCP at `https://mcp.natural.com`.
> When searching Natural documentation, use the docs MCP at `https://docs.natural.com/mcp`.
> Use the Natural CLI for terminal and CI automation.
> Use REST only for unsupported languages or when the user explicitly requests raw HTTP.
> Start integration development and testing in the sandbox. Do not use production unless the user explicitly requests it.
> For sandbox requests that require `customerPartyId`, list customers first. Reuse only the intended fixture; otherwise create a customer.
> REST and SDK amounts use integer minor units. Payments MCP amounts use decimal strings with a required currency code.

# Overview

> Let agents pay with a card without ever seeing the real card number

Card sessions let an [agent](/guides/concepts/agents) pay with a card without ever seeing the real card number (PAN), by checking out through a browser proxy.

Each card session (`csn_*`) covers one purchase. The agent gets a stand-in card number and a proxy login, fills in the merchant's checkout with the stand-in, and routes its browser through the proxy. When the checkout sends the card to one of the session's allowed hosts, the proxy swaps in the real card on the way. Anywhere else, or after the session expires, the stand-in is useless.

Card sessions are for agents: call them with an [agent key](/guides/concepts/agent-keys). Creating and claiming a session also needs the `X-Instance-ID` header.

Card sessions work with cards a user saved on the dashboard. Support for [Natural-issued cards](/guides/concepts/natural-issued-cards) is coming soon.

## Flow

1. **Find a card.** [`GET /card-external-accounts`](/api-reference/external-accounts/list-card-external-accounts) lists the cards the user saved on the dashboard (`eac_*`), with brand and last four digits. The agent key needs the `wallets.read` scope.
2. **Open a session.** [`POST /card-sessions`](/api-reference/card-sessions/create-card-session) with the `cardId`, the `purchase` (merchant name, amount, currency) and the `allowedHosts` that may receive the real card. For a saved card, the response includes an `approvalUrl`. Send it to the user: it's returned only once.
3. **Wait for approval.** The user opens the link, checks the purchase and approves it with the card's security code. Poll [`GET /card-sessions/{sessionId}`](/api-reference/card-sessions/get-card-session) until `status` is `approved`. A `declined` or `expired` session is over: open a new one.
4. **Claim.** [`POST /card-sessions/{sessionId}/claim`](/api-reference/card-sessions/claim-card-session) returns the stand-in card, the cardholder name and billing address, and the proxy login. It succeeds once; the credential can't be fetched again.
5. **Check out.** Fill in the merchant's checkout with the stand-in card and send the payment request to an allowed host through the proxy, trusting the proxy's root certificate at `caBundleUrl`.

## Allowed hosts

`allowedHosts` is required and has no default. Entries are exact hostnames, such as `api.stripe.com`. Wildcards, ports and paths aren't accepted. Only requests to these hosts get the real card, so name the payment processor's API host that receives the card, not the merchant's website. The user sees the hosts on the approval page.

## Limits

* A session covers one purchase. For another purchase, open a new session.
* The user must approve, and the agent must claim, before `claimExpiresAt`.
* The stand-in card and proxy login stop working at the claim's `expiresAt` (`ttlSeconds`, 600 by default, up to 900).
* Checkouts that encrypt the card in the browser before sending it can't be completed this way.
