---
title: "Create card session"
method: POST
path: "/card-sessions"
tags: ["Card Sessions"]
---

# Create card session

`POST /card-sessions`

## Request

- Base URL: `https://api.natural.com`
- URL: `https://api.natural.com/card-sessions`
- Auth: HTTP bearer

Open a session to pay for one purchase with one card. Poll it until the user approves, then claim it once for a stand-in card and proxy login.

## Headers

- `X-Instance-ID` string, nullable
- `Idempotency-Key` string

## Request body

- object
  - `data` object, required
    - `attributes` object, required
      - `cardId` union, required: Card to use: an agent card issued to you (pcd_...) or a card the user added on the dashboard (eac_...).
        - string
        - string
      - `customerPartyId` string: Customer party to act for (pty_*). Omit to act as your own party. To act for another party, pass the ID of a party that has authorized you to act on its behalf.
      - `allowedHosts` string[], required: Exact hostnames allowed to receive the real card, such as the payment processor's API host the merchant's checkout sends the card to. Required: there is no default. When the card fields are an iframe from checkoutshopper-live.adyen.com or flex.cybersource.com, list that host, and for CyberSource also the merchant host that serves the payment page.
      - `ttlSeconds` integer: How long the stand-in card and proxy login stay valid once claimed. Defaults to 600.
      - `claimWindowSeconds` integer: How long you have to claim the session once the user approves it, from 600 (10 minutes) to 86400 (24 hours). Defaults to 600. Natural holds the card's encrypted security code for this long after approval, so pick the shortest window that fits.
      - `purchase` object: What the agent will do with the card, shown to the user on the approval page. Required for a card the user added (eac_). The user approves what you describe here; merchantName, amount and description aren't enforced, while allowedHosts is.
        - `merchantName` string, required: Merchant name as the user will recognize it. Shown to the user, not enforced: the proxy doesn't check which merchant the card goes to.
        - `amount` integer, required: Total in minor units (cents) of `currency`. Use 0 for a card action with no purchase, such as saving the card on file at the merchant. Shown to the user, not enforced as a cap.
        - `currency` string, required: ISO 4217 currency code, e.g. USD.
        - `description` string: A short plain-text line for the user saying what the agent will do or buy, such as `Save this card on file at Amazon` or `Flowers for tomorrow morning, up to $200`. The approval page shows it prominently. Shown, not enforced.
      - `reference` string: Your own reference for the session, such as your checkout or task ID. Not unique: filter GET /card-sessions by it to find the session again.
      - `returnUrl` string: Where to send the user once they approve or decline: an https page in your product, or sms:+15551234567 to reopen your Messages thread. It's added to approvalUrl as returnTo. The approval page opens https pages on its own after the user answers, and offers a button for sms: links.
      - `requestAgentToken` boolean: Cards the user added only, for a USD purchase from $0.01 to $999,999.99. A backup for checkouts that don't send the raw card number in the HTTP request, for example ones that encrypt it in the browser, so the proxy can't swap it in. Paying through the proxy stays the default. On approval, Natural also tries to set up agent payments on the card. Most cards don't support them yet, so agentToken.mandateId is often null: then claim this session and try the proxy. Defaults to false.

## Response `201`

Successful Response

- object
  - `sessionId` string, required
  - `cardId` string, required
  - `cardSource` 'natural_issued' | 'external', required: natural_issued: an agent card Natural issued to you. external: a card the user added on the dashboard.
  - `status` 'pending_approval' | 'approved' | 'declined' | 'claimed' | 'expired', required: pending_approval: waiting for the user; keep polling. approved: claim it now. declined: the user said no. claimed: already collected. expired: open a new session.
  - `allowedHosts` string[], required
  - `reference` string, nullable, required: The reference you created the session with. Null when you didn't set one.
  - `purchase` object, nullable, required: The purchase you created the session with, as the user saw it. Null for an agent card session opened without one.
    - `merchantName` string, required
    - `amount` integer, required: Minor units (cents) of `currency`. 0 means no purchase.
    - `currency` string, required
    - `description` string, nullable, required: The description you set. Null when you didn't.
  - `approvalExpiresAt` string, required: A pending session must be approved before this, 24 hours after creation. After it, an unapproved session is expired.
  - `claimExpiresAt` string, required: An approved session must be claimed before this: approval plus claimWindowSeconds. Until the user approves, it's the latest that could be: approvalExpiresAt plus claimWindowSeconds. After it, an unclaimed session is expired.
  - `claimedAt` string, nullable, required
  - `credentialExpiresAt` string, nullable, required: When the claimed proxy login stops working.
  - `createdAt` string, required
  - `agentToken` object, required: Agent token for this purchase, when you set requestAgentToken.
    - `requested` boolean, required: You set requestAgentToken when creating the session.
    - `mandateId` string, nullable, required: Once the session is approved: the mandate (amd_) to pay with. Create an agentic purchase with it (POST /agentic-payments/purchases) and claim that purchase's credential. Null when you didn't ask, while the session waits for approval, and when the card couldn't take agent payments, which is common: then claim this session and try the proxy.
  - `note` object, nullable, required: Cards the user added only, once the purchase is approved: a suggestion to pass on to the user. Null when there's nothing to suggest, and always null in list results: get the session for it.
    - `message` string, required: What to tell the user: what would let them skip the security code next time, such as verifying their identity or adding money to Natural.
    - `url` string, nullable, required: A page to send the user to for that step. Null when there's nothing to do yet.
  - `approvalUrl` string, nullable, required: Cards the user added only: send the user here to approve the purchase. Returned only in this response; it can't be fetched again.

## Other responses

- `400`: Validation Error
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not Found. Returned when the resource does not exist, or when it exists but is not accessible to your account. The two cases are intentionally indistinguishable, so that resource IDs cannot be enumerated by probing.
- `409`: Conflict
- `422`: Validation Error. The response contains one error object for each invalid request value.
- `428`: Precondition Required
- `429`: Too Many Requests
- `500`: Internal Server Error
- `501`: Not Implemented
- `502`: Bad Gateway
- `503`: Service Unavailable

## Changes

- **2026-10-26** `9327f52d75d3`: 3 info
  - added the new optional request property `data/attributes/purchase/description`
  - the `data/attributes/purchase/amount` request property's min was decreased from `1.00` to `0.00`
  - added the required property `purchase` to the response with the `201` status
- **2026-10-22** `4fda009457be`: 2 info
  - added the new optional request property `data/attributes/claimWindowSeconds`
  - added the required property `approvalExpiresAt` to the response with the `201` status
- **2026-10-20** `d17693dd16b3`: 1 info
  - added the new optional request property `data/attributes/returnUrl`
- **2026-10-15** `95af42ae53c7`: 2 info
  - added the new optional request property `data/attributes/requestAgentToken`
  - added the required property `agentToken` to the response with the `201` status
- **2026-10-13** `af91bb69dfcf`: 3 info
  - added the new optional `header` request parameter `Idempotency-Key`
  - added the new optional request property `data/attributes/reference`
  - added the required property `reference` to the response with the `201` status

[Operation history](https://skmtc.dev/natural/apis/natural-api/changes/card-sessions/post.md)

---

[API](https://skmtc.dev/natural/apis/natural-api.md) - [All operations](https://skmtc.dev/natural/apis/natural-api/llms.txt) - [OpenAPI document](https://skmtc.dev/natural/apis/natural-api/revisions/59c1208fa5dc?raw)
