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

# Recurring billing with PayLinks

> Charge agents all month on a budget they approved once. The subscription model for the agent economy.

# Recurring billing with PayLinks

Cards have "save this card and charge monthly". Agents have something better: **PayLinks** are budgets that a human approves once, that you draw against as value is delivered.

## When to use a PayLink vs plain charges

| Use plain charges when...              | Use PayLinks when...                                 |
| -------------------------------------- | ---------------------------------------------------- |
| One-off purchases (an API call pack)   | Recurring services (monthly retainer, seat plans)    |
| Amount is small enough to auto-approve | You want one approval instead of many                |
| The agent pays you ad-hoc              | You need predictable, capped exposure for both sides |

## Full walkthrough

### 1. Create the link

```bash theme={null}
curl -X POST https://your-payzor-host/merchant/paylinks \
  -H "Authorization: Bearer sk_mch_..." \
  -d '{
    "label": "Retainer mensual data",
    "budgetUsdCents": 500,
    "perChargeUsdCents": 150,
    "maxUses": 10,
    "expiresInHours": 720
  }'
```

All constraints are optional except the budget:

* `budgetUsdCents`: total ceiling across all draws.
* `perChargeUsdCents`: max size of any single draw.
* `maxUses`: max number of draws.
* `expiresInHours`: self-explanatory.

Response:

```json theme={null}
{
  "paylinkId": "pl_8eb56b59f563e9ed",
  "code": "h83YpjKQ",
  "label": "Retainer mensual data",
  "budgetMinor": 500,
  "perChargeMinor": 150,
  "maxUses": 10,
  "remainingMinor": 500,
  "status": "active"
}
```

### 2. Deliver the code to your customer's agent

The agent fetches the public view and decides:

```bash theme={null}
curl https://your-payzor-host/pl/h83YpjKQ
```

```json theme={null}
{
  "code": "h83YpjKQ",
  "business": "Acme Digital Goods",
  "label": "Retainer mensual data",
  "budgetMinor": 500,
  "remainingMinor": 500,
  "status": "active"
}
```

Then it accepts (this creates the grant, the auditable "yes" from the human side):

```bash theme={null}
curl -X POST https://your-payzor-host/pl/h83YpjKQ/accept \
  -H "Authorization: Bearer pz_sk_..."
```

```json theme={null}
{
  "grantId": "plg_8045a45414bdb863",
  "paylink": { "...": "..." }
}
```

You'll receive a `paylink.accepted` webhook with the grant id and the agent's identity.

### 3. Charge whenever you deliver value

```bash theme={null}
curl -X POST https://your-payzor-host/merchant/paylinks/h83YpjKQ/charge \
  -H "Authorization: Bearer sk_mch_..." \
  -d '{
    "agentId": "agent_6b75c0e895ba9c3d",
    "amountUsdCents": 150,
    "description": "Uso semanal"
  }'
```

```json theme={null}
{
  "paid": true,
  "charge": { "status": "paid", "method": "paylink", "...": "..." },
  "spentMinor": 150,
  "remainingMinor": 350,
  "exhausted": false
}
```

### 4. Handle exhaustion

When the remaining budget hits zero:

* further draws return `{ "error": "paylink_exhausted" }`,
* you receive a final `budget.exhausted` webhook,
* over-budget draws are rejected *before* touching the wallet, with the exact remaining amount in the error message.

## Design patterns

<AccordionGroup>
  <Accordion title="Metered usage">
    Set `perChargeUsdCents` to your unit price; draw once per billing period based on measured usage. Budget caps the customer's worst case.
  </Accordion>

  <Accordion title="Seat plans">
    One PayLink per customer per month. `expiresInHours: 720` auto-retires it; issue next month's link at renewal.
  </Accordion>

  <Accordion title="Trials">
    Small budget (\$1), no expiry, enough to prove value without risk.
  </Accordion>
</AccordionGroup>
