# Balance & payments

Every intent ends with a payment. There are two ways it gets paid:

1. **From your agent balance.** Top up a balance in the
   [dashboard](/dashboard/wallets) and intents pay from it on their own, within
   the limits you set. No human in the loop.
2. **With a payment link.** If the balance can't cover the purchase (or is over
   a limit, or you asked for one), the API pauses the intent and returns a
   `payment_url`. Whoever opens it pays, and the intent carries on to the
   receipt.

The 5% transaction fee is paid the same way as the purchase, in the same step.

## Agent balance

A balance is prepaid money your agents can spend. Top it up from a card or bank
account in the dashboard; each organization has its own. Check it with
[`GET /v1/balance`](/docs/api#get-the-balance) or `openintents balance`.

When an intent reaches checkout, OpenIntents pays from the balance if all of
these hold:

- the balance covers the total plus the 5% fee,
- the total is within the per-intent limit,
- it doesn't push the month's spend past the monthly limit.

Otherwise it asks for payment with a link.

| Control | Where | Effect |
| --- | --- | --- |
| `max_amount` | per intent | The intent fails rather than spend more. |
| Per-intent limit | balance | Intents above it return a payment link. |
| Monthly limit | balance | Intents that would exceed it return a payment link. |
| `require_payment_link` | per intent | Always return a payment link, even if the balance could pay. |

## Payment links

When an intent needs someone to pay, it pauses with
`"status": "requires_payment"` and a `payment` object describing the purchase:

```json
{
  "id": "int_7f11b0",
  "status": "requires_payment",
  "payment": {
    "reason": "insufficient_balance",
    "payment_url": "https://pay.openintents.io/p_7f11b0",
    "merchant": "TAP Air Portugal",
    "total": 38900,
    "fee": 1945,
    "currency": "usd",
    "expires_at": "2026-10-01T09:00:00Z"
  }
}
```

`reason` is `insufficient_balance`, `over_limit` or `requested`. Send the
`payment_url` to the person who should pay: show it in your app, post it in a
chat, or let the [MCP tools](/docs/mcp) hand it to the user. It is a hosted
checkout page showing the merchant, items and total. Once it's paid, the intent
resumes and completes. Links expire after 30 minutes; an expired or
[cancelled](/docs/api#cancel-an-intent) intent is free.

<Callout type="warning">
  Card details never reach your code, your agent or the model. They are entered
  on the hosted payment page, or already sit behind your balance.
</Callout>
