---
updatedAt: 2026-10-05T04:43:44.548Z
---

Fetch the complete documentation index at: https://docs.avvio.xyz/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# CLI

Installed by `npx`, or as a dependency. Every command takes `--json` for machine-readable output, and reads `AVVIO_API_KEY`, `AVVIO_ORG_ID` and `AVVIO_BASE_URL` from the environment. This page is generated from the CLI's own `--help`, so it always matches the released binary.

```bash
npx -y @avvio/payments doctor
```

## Setup

| Command | What it does |
| --- | --- |
| `guide` | The whole flow, as commands you can paste |
| `doctor` | Check your credentials, connectivity and balance |
| `mcp` | Run as an MCP server over stdio (for agents) |

## Discovery

| Command | What it does |
| --- | --- |
| `policy` | Your caps, approval threshold, features and rate limits: read first |
| `corridors` | Currencies you can pay out to |
| `requirements <CCY>` | Fields a beneficiary in that currency needs |
| `payment-reasons` | What --purpose may say, where one is required |

## Pricing

| Command | What it does |
| --- | --- |
| `quote --amount 200 --to MXN` | What the recipient gets, and the fee |

## Beneficiaries

| Command | What it does |
| --- | --- |
| `beneficiary create --name "Maria Gonzalez" --currency MXN --end-user emp_42 --external-id cust42_maria --field clabeNumber=012180000080004471 [--email maria@example.com] [--country MX] [--external-id <your id>]` | `[--email maria@example.com]`: optional contact detail. `[--country MX] [--external-id <your id>]`: external-id makes a repeat create return the existing beneficiary instead of registering a second account |
| `beneficiary list [--end-user emp_42] [--limit 50] [--cursor <id>]` | See the help text below |
| `beneficiary get <id> \| beneficiary get --external-id cust42_maria` | See the help text below |
| `beneficiary update <id> [--name] [--email] [--phone] [--country] [--type]` | Contact details only. Bank details are not editable; register a new method instead |
| `beneficiary delete <id>` | Removes them and every method on them |
| `beneficiary method delete\|details <id> <methodId>` | Drop one account, or read the whole one on file |

## Sandbox

| Command | What it does |
| --- | --- |
| `fund [--amount 5000]` | Credit your test balance |
| `balance` | What you can send (network figure and our ledger) |

## Paying

| Command | What it does |
| --- | --- |
| `pay --amount 200 --to <destinationAccountId> --end-user emp_42 [--expect <destinationAmount from quote>] [--end-user-name "Ana Lopez"] [--reference ZZ-1] [--idempotency-key k1] [--max-drift-bps 200] [--exact] [--worth]` | `[--exact]`: --amount is what they receive, in their currency. `[--worth]`: --amount is what they receive, in yours; fees on top |
| `cancel <payoutId>` | stop a payout that has not been funded yet |
| `status <payoutId> [--watch]` | --watch polls until it stops moving |
| `payouts` | Recent payouts |

## Reconciliation

| Command | What it does |
| --- | --- |
| `events [--since <sequence>] [--limit N] [--payout-id ID] [--type a,b] [--follow]` | Every transition, in order. Carry the returned nextSince back as --since; --type narrows to the families you book; --follow polls and prints new rows as they land (--interval SECONDS) |
| `approvals [--status pending]` | Payouts and runs waiting on your approvers (a 202 from pay or a batch confirm). Deciding one is a dashboard action, not a command |
| `approval <approvalId>` | One approval; executed ones name the payoutId |
| `audit-events [--cursor <id>] [--limit N] [--action payout.create] [--resource-id ID] [--api-key <prefix>] [--actor <userId>] [--after ISO] [--before ISO]` | Who did what, with which credential, newest first |
| `balance-transactions [--cursor <id>] [--limit N] [--type payout,funding] [--order-id ID] [--currency USD] [--after ISO] [--before ISO]` | Every change to your balance, newest first, with balanceAfter. Carry nextCursor back as --cursor |

## Funding

| Command | What it does |
| --- | --- |
| `funding` | Where to wire money to top up your balance |
| `funding <payoutId>` | Deposit instructions for a payout you fund yourself (requiresFunding: true) |
| `funding confirm <payoutId> --tx <hash>` | Report the transfer you already sent |

## Payout links

| Command | What it does |
| --- | --- |
| `link create --amount --to --end-user` | Mint a one-time link; the recipient enters their own bank details (--reference, --expires MINUTES) |

## Checkout (accept payments on your website; test and live keys)

| Command | What it does |
| --- | --- |
| `product create --name "Consulting (60 min)" --currency USD --amount 150.00 [--description "..."]` | See the help text below |
| `product list` | Your catalog |
| `checkout create --product <productId> \| --currency USD --item "Consulting (60 min)" --amount 150.00 [--success-url https://…] [--cancel-url https://…] [--ref <your order id>] [--meta key=value]... [--expires-in 30m\|2h\|7d] [--draft]` | Publishes and prints shareUrl; --draft keeps it unpublished. --ref is your join key on events. --expires-in sets a deadline: past it the page answers 410 and the link reads expired |
| `checkout update <linkId> --expires-in 2h \| --no-expiry` | Move or clear a live link's deadline. A draft also takes the create flags |
| `checkout get <linkId>` | One link, with what it has received |
| `checkout list [--status sent\|expired] [--source api\|dashboard] [--limit N] [--cursor <id>]` | See the help text below |
| `checkout pause <linkId>` | Stop it taking payments. Permanent: make a new link to sell again |
| `checkout payments <linkId>` | What was paid on it, newest first (base units) |
| `checkout refund <paymentId> --full \| --amount 12.50 [--reason requested_by_customer\|duplicate\|fraudulent\|other] [--note "..."] [--idempotency-key K] [--allow-duplicate]` | Moves money back to the buyer. Needs a key with the refunds scope. --full says so explicitly |
| `checkout simulate <linkId> [--ref R]` | Sandbox only. Pay the link as a buyer would. `[--ref R]`: The link amount picks the outcome |
| `checkout simulate <payId> --action chargeback\|refund\|fail` | Sandbox only. Force it now instead of waiting |
| `checkout scenarios` | Sandbox only. What each amount does |

## Webhooks

| Command | What it does |
| --- | --- |
| `webhook create --url <url>` | Sandbox only. Register an endpoint, print its signing secret (--events a,b; https only) |
| `webhook deliveries <id>` | Sandbox endpoint: delivery attempts and retries |
| `webhook endpoints` | Endpoints registered for your org (read-only; registering and pausing are dashboard actions) |
| `webhook attempts <id>` | Last 50 delivery attempts for a registered endpoint: eventId, attempts, lastError |

## Configuration (environment)

| Command | What it does |
| --- | --- |
| `AVVIO_API_KEY` | required Complete avvio_live_* or avvio_test_* bearer key |
| `AVVIO_ORG_ID` | required |
| `AVVIO_BASE_URL` | optional |

## A first payout, end to end

The same three calls in every language:

**curl**

```bash title="GET /payments/organizations/{orgId}/rates"
curl -s "$AVVIO_BASE_URL/payments/organizations/$AVVIO_ORG_ID/rates?from=USD&to=MXN&amount=200.00" \
  -H "x-api-key: $AVVIO_API_KEY"
```

**Node**

```js title="GET /payments/organizations/{orgId}/rates"
const quote = await avvio.quote({
  amount: '200.00',
  to: 'MXN',
});
// → { sourceAmount, destinationAmount, fee, rate, limits, indicative: true }
```

**Python**

```python title="GET /payments/organizations/{orgId}/rates"

res = requests.get(
    f"{os.environ['AVVIO_BASE_URL']}/payments/organizations/{os.environ['AVVIO_ORG_ID']}/rates",
    headers={
        "x-api-key": os.environ["AVVIO_API_KEY"],
    },
    params={
        "from": "USD",
        "to": "MXN",
        "amount": "200.00"
    },
)
print(res.status_code, res.json())
```

**CLI**

```bash title="GET /payments/organizations/{orgId}/rates"
avvio-payments quote --amount 200.00 --to MXN
```

**curl**

```bash title="POST /recipients/{orgId}"
IDEMPOTENCY_KEY=$(uuidgen)  # new key per call; reuse it only to retry this exact request
curl -s -X POST "$AVVIO_BASE_URL/recipients/$AVVIO_ORG_ID" \
  -H "x-api-key: $AVVIO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "content-type: application/json" \
  -d '{
        "type": "individual",
        "name": "María González",
        "country": "MX",
        "externalId": "cust42_maria",
        "endUserId": "customer_42",
        "method": {
          "kind": "fiat",
          "currency": "MXN",
          "recipientDetails": {
            "clabeNumber": "012180000080004471"
          }
        }
      }' | tee response.json
export DESTINATION_ACCOUNT_ID=$(jq -r .method.destinationAccountId response.json)
```

**Node**

```js title="POST /recipients/{orgId}"
const beneficiary = await avvio.createBeneficiary({
  name: 'María González',
  email: 'maria@example.com',                // optional contact detail
  country: 'MX',
  currency: 'MXN',
  endUserId: 'customer_42',        // your id for the person sending
  externalId: 'cust42_maria',      // makes a repeat create safe
  details: { clabeNumber: '012180000080004471' },
});
const destinationAccountId = beneficiary.method.destinationAccountId; // you pay this
```

**Python**

```python title="POST /recipients/{orgId}"

idempotency_key = str(uuid.uuid4())  # new key per call; reuse it only to retry this exact request

res = requests.post(
    f"{os.environ['AVVIO_BASE_URL']}/recipients/{os.environ['AVVIO_ORG_ID']}",
    headers={
        "x-api-key": os.environ["AVVIO_API_KEY"],
        "Idempotency-Key": idempotency_key,
    },
    json={
        "type": "individual",
        "name": "María González",
        "country": "MX",
        "externalId": "cust42_maria",
        "endUserId": "customer_42",
        "method": {
            "kind": "fiat",
            "currency": "MXN",
            "recipientDetails": {
                "clabeNumber": "012180000080004471"
            }
        }
    },
)
print(res.status_code, res.json())
os.environ["DESTINATION_ACCOUNT_ID"] = res.json()["method"]["destinationAccountId"]  # a later step reads it
```

**CLI**

```bash title="POST /recipients/{orgId}"
avvio-payments beneficiary create \
  --name "María González" --email maria@example.com \
  --currency MXN --country MX \
  --end-user customer_42 --external-id cust42_maria \
  --field clabeNumber=012180000080004471 | tee response.json
export DESTINATION_ACCOUNT_ID=$(jq -r .method.destinationAccountId response.json)
```

**curl**

```bash title="POST /payments/organizations/{orgId}/payouts"
IDEMPOTENCY_KEY=$(uuidgen)  # new key per call; reuse it only to retry this exact request
curl -s -X POST "$AVVIO_BASE_URL/payments/organizations/$AVVIO_ORG_ID/payouts" \
  -H "x-api-key: $AVVIO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "content-type: application/json" \
  -d '{
        "amount": "200.00",
        "destinationAccountId": "'"$DESTINATION_ACCOUNT_ID"'",
        "amountLeg": "source",
        "expectDestination": "3384.65",
        "maxDriftBps": 200,
        "reference": "ZZ-2026-0042",
        "endUser": {
          "id": "customer_42"
        }
      }'
```

**Node**

```js title="POST /payments/organizations/{orgId}/payouts"
const idempotencyKey = crypto.randomUUID(); // persist it with the order so a retry reuses it
const payout = await avvio.payout({
  amount: '200.00',
  destinationAccountId,
  expectDestination: quote.destinationAmount.amount,  // 3384.65
  endUser: { id: 'customer_42' },
  reference: 'ZZ-2026-0042',
  idempotencyKey,
});
```

**Python**

```python title="POST /payments/organizations/{orgId}/payouts"

idempotency_key = str(uuid.uuid4())  # new key per call; reuse it only to retry this exact request

res = requests.post(
    f"{os.environ['AVVIO_BASE_URL']}/payments/organizations/{os.environ['AVVIO_ORG_ID']}/payouts",
    headers={
        "x-api-key": os.environ["AVVIO_API_KEY"],
        "Idempotency-Key": idempotency_key,
    },
    json={
        "amount": "200.00",
        "destinationAccountId": os.environ["DESTINATION_ACCOUNT_ID"],
        "amountLeg": "source",
        "expectDestination": "3384.65",
        "maxDriftBps": 200,
        "reference": "ZZ-2026-0042",
        "endUser": {
            "id": "customer_42"
        }
    },
)
print(res.status_code, res.json())
```

**CLI**

```bash title="POST /payments/organizations/{orgId}/payouts"
avvio-payments pay --amount 200.00 \
  --to "$DESTINATION_ACCOUNT_ID" \
  --expect 3384.65 \
  --end-user customer_42 --reference ZZ-2026-0042
```

## Full help text

```text
avvio-payments: pay out to your customers from your balance

  Setup
    guide                       The whole flow, as commands you can paste
    doctor                      Check your credentials, connectivity and balance
    mcp                         Run as an MCP server over stdio (for agents)

  Discovery
    policy                      Your caps, approval threshold, features and rate limits: read first
    corridors                   Currencies you can pay out to
    requirements <CCY>          Fields a beneficiary in that currency needs
    payment-reasons             What --purpose may say, where one is required

  Pricing
    quote --amount 200 --to MXN         What the recipient gets, and the fee

  Beneficiaries
    beneficiary create --name "Maria Gonzalez" --currency MXN \\
      --end-user emp_42 --external-id cust42_maria \\
      --field clabeNumber=012180000080004471
      [--email maria@example.com]                optional contact detail
      [--country MX] [--external-id <your id>]   external-id makes a repeat
                                                 create return the existing
                                                 beneficiary instead of
                                                 registering a second account
    beneficiary list [--end-user emp_42] [--limit 50] [--cursor <id>]
    beneficiary get <id> | beneficiary get --external-id cust42_maria
    beneficiary update <id> [--name] [--email] [--phone] [--country] [--type]
                                Contact details only. Bank details are not
                                editable; register a new method instead
    beneficiary delete <id>     Removes them and every method on them
    beneficiary method delete|details <id> <methodId>
                                Drop one account, or read the whole one on file

  Sandbox
    fund [--amount 5000]        Credit your test balance
    balance                     What you can send (network figure and our ledger)

  Paying
    pay --amount 200 --to <destinationAccountId> --end-user emp_42 \\
        [--expect <destinationAmount from quote>] [--end-user-name "Ana Lopez"] \\
        [--reference ZZ-1] [--idempotency-key k1] [--max-drift-bps 200]
        [--exact]                       --amount is what they receive, in their currency
        [--worth]                       --amount is what they receive, in yours; fees on top
    cancel <payoutId>      stop a payout that has not been funded yet
  status <payoutId> [--watch]   --watch polls until it stops moving
    payouts                     Recent payouts

  Reconciliation
    events [--since <sequence>] [--limit N] [--payout-id ID] [--type a,b] [--follow]
                                Every transition, in order. Carry the returned
                                nextSince back as --since; --type narrows to the
                                families you book; --follow polls and prints new
                                rows as they land (--interval SECONDS)
    approvals [--status pending]
                                Payouts and runs waiting on your approvers
                                (a 202 from pay or a batch confirm). Deciding
                                one is a dashboard action, not a command
    approval <approvalId>       One approval; executed ones name the payoutId
    audit-events [--cursor <id>] [--limit N] [--action payout.create]
                 [--resource-id ID] [--api-key <prefix>] [--actor <userId>]
                 [--after ISO] [--before ISO]
                                Who did what, with which credential, newest first
    balance-transactions [--cursor <id>] [--limit N] [--type payout,funding]
                         [--order-id ID] [--currency USD] [--after ISO] [--before ISO]
                                Every change to your balance, newest first, with
                                balanceAfter. Carry nextCursor back as --cursor

  Funding
    funding                     Where to wire money to top up your balance
    funding <payoutId>          Deposit instructions for a payout you fund
                                yourself (requiresFunding: true)
    funding confirm <payoutId> --tx <hash>
                                Report the transfer you already sent

  Payout links
    link create --amount --to --end-user
                                Mint a one-time link; the recipient enters their
                                own bank details (--reference, --expires MINUTES)

  Checkout (accept payments on your website; test and live keys)
    product create --name "Consulting (60 min)" --currency USD --amount 150.00
                                [--description "..."]
    product list                Your catalog
    checkout create --product <productId>
                  | --currency USD --item "Consulting (60 min)" --amount 150.00
        [--success-url https://…] [--cancel-url https://…] [--ref <your order id>]
        [--meta key=value]... [--expires-in 30m|2h|7d] [--draft]
                                Publishes and prints shareUrl; --draft keeps it
                                unpublished. --ref is your join key on events.
                                --expires-in sets a deadline: past it the page
                                answers 410 and the link reads expired
    checkout update <linkId> --expires-in 2h | --no-expiry
                                Move or clear a live link's deadline. A draft
                                also takes the create flags
    checkout get <linkId>       One link, with what it has received
    checkout list [--status sent|expired] [--source api|dashboard]
                  [--limit N] [--cursor <id>]
    checkout pause <linkId>     Stop it taking payments. Permanent: make a new
                                link to sell again
    checkout payments <linkId>  What was paid on it, newest first (base units)
    checkout refund <paymentId> --full | --amount 12.50
        [--reason requested_by_customer|duplicate|fraudulent|other] [--note "..."]
        [--idempotency-key K] [--allow-duplicate]
                                Moves money back to the buyer. Needs a key with
                                the refunds scope. --full says so explicitly
    checkout simulate <linkId>  Sandbox only. Pay the link as a buyer would.
                  [--ref R]     The link amount picks the outcome
    checkout simulate <payId> --action chargeback|refund|fail
                                Sandbox only. Force it now instead of waiting
    checkout scenarios          Sandbox only. What each amount does

  Webhooks
    webhook create --url <url>  Sandbox only. Register an endpoint, print its
                                signing secret (--events a,b; https only)
    webhook deliveries <id>     Sandbox endpoint: delivery attempts and retries
    webhook endpoints           Endpoints registered for your org (read-only;
                                registering and pausing are dashboard actions)
    webhook attempts <id>       Last 50 delivery attempts for a registered
                                endpoint: eventId, attempts, lastError

  Configuration (environment)
    AVVIO_API_KEY   required    Complete avvio_live_* or avvio_test_* bearer key
    AVVIO_ORG_ID    required
    AVVIO_BASE_URL  optional

  Every command takes --json for machine-readable output.
```
