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

# The nextAction Contract

> The object on every Agent Pay result that tells you what has to happen next, and who has to do it.

**You don't need this page to ship.** [Embedded checkout](https://docs.paywithatoa.com/agent-pay/embed.md) reads `nextAction` for you, and so
does the [Approvals SDK](https://docs.paywithatoa.com/agent-pay/approvals.md). Read on if you're rendering payment UI yourself, relaying actions
through a channel Atoa doesn't know about, or want to see what the embed switches on.

Every Agent Pay result carries one `nextAction`: the single thing that must happen next. It holds the ids,
amounts and links a renderer needs, so you never pick fields out of a raw response. With no UI, poll
`nextAction.resolve` until the status is terminal. In a chat, post `nextAction.fallback.text`.

## The shape

| Field | Type | Meaning |
| - | - | - |
| `v` | `1` | Envelope version. |
| `type` | string | The action kind — the [catalogue](#the-catalogue) below. New types can appear: switch on it and fall back on anything unknown. |
| `state` | string? | Where the flow is — the underlying payment/contract status when there is one. |
| `for` | `'customer' \| 'owner' \| 'none'` | **Who must act.** `'none'` tells an agent NOT to prompt a human. |
| `expiresAt` | ISO datetime? | When the action lapses. |
| `mustEscalate` | boolean | Reserved. Always `false` today — no action currently needs a top-level window. |
| `data` | object | Everything a surface needs, by type — **additive-only**: ignore fields you don't know. |
| `fallback` | `{ text, url }` | **Present on every action.** One sentence and a link — the plain-text path when you render nothing. Never carries a secret. |
| `resolve` | `{ poll, id, until }`? | How to learn it finished: poll `'payment' \| 'contract' \| 'approval'` with `id` until a status in `until`. |

Read approval fields from `data`: `data.approvalId`, `data.approvalUrl`, `data.clientSecret`. The same three are
also mirrored at the top level of `nextAction` for backwards compatibility.

## The catalogue \[#the-catalogue]

Four types. That's the whole set an Agent Pay call can return today.

| `type` | Who acts | What it asks for |
| - | - | - |
| `PAY` | customer | Pay an open pay-link — `data.paymentRequestId`, `amount`, `hostedUrl`. |
| `APPROVAL` | customer or owner | The SCA [approval gate](https://docs.paywithatoa.com/agent-pay/reference.md#approval-gate) (SCA: the approver's one-time code or passkey check) — `data.approvalId`, `approvalUrl`, `clientSecret`. |
| `AUTHORIZE_CONTRACT` | customer or owner | Authorise a contract — `data.kind` says which page: `'collect'` (customer links a method + approves) or `'cvrp'` (a commercial Variable Recurring Payment — the account holder consents at their bank). |
| `NONE` | none | Terminal. State the outcome, ask for nothing. |

Choosing a card, entering card details, verifying a contact, enrolling a passkey — those are **steps inside** a
`PAY`, `APPROVAL` or `AUTHORIZE_CONTRACT` flow, handled on Atoa's pages. They never arrive as a `nextAction` you
have to render.

## Handling a type you don't know

**When you get a `type` you don't recognise, render `fallback.text` and `fallback.url`.**

`type` is a plain string, not an enum, so Atoa can add action types without an SDK release. Every action type has
a usable `fallback`. The embed does this for you.

`fallback.text` never contains a `clientSecret`, so it's safe to post to a chat or an email.

## Amounts are pre-formatted

`data.amount` is `{ value, currency, display }` — `value` is a decimal **string**, exactly as sent on the wire;
`display` is pre-formatted (`"£45.00"`). Print `display`; never format money yourself.

```json theme={null}
{
  "v": 1,
  "type": "PAY",
  "state": "PENDING",
  "for": "customer",
  "mustEscalate": false,
  "data": {
    "paymentRequestId": "prq_a81f…",
    "amount": { "value": "45.00", "currency": "GBP", "display": "£45.00" },
    "orderId": "booking-8812",
    "hostedUrl": "https://pay.atoa.me/prq_a81f…"
  },
  "fallback": {
    "text": "Pay £45.00 securely from your bank: https://pay.atoa.me/prq_a81f…",
    "url": "https://pay.atoa.me/prq_a81f…"
  },
  "resolve": { "poll": "payment", "id": "prq_a81f…", "until": ["COMPLETED", "FAILED", "CANCELLED", "EXPIRED"] },
  "source": "sdk"
}
```


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