---
updatedAt: 2026-09-30T15:54:20.000Z
---

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.

# For agents

Every page here is also plain markdown, and two MCP servers expose the docs and
the API, so an agent reads and acts without scraping HTML.
[Build with AI](/build-with-ai/) connects both in your tool.

## Machine-readable files

```
https://docs.avvio.xyz/llms.txt        index of everything, with links
https://docs.avvio.xyz/llms-full.txt   every guide, samples in all languages
https://docs.avvio.xyz/partner-payouts.openapi.yaml   the payouts contract
https://docs.avvio.xyz/partner-checkout.openapi.yaml  the checkout contract
```

`llms.txt?query=webhooks` returns only the index entries that match. Append
`.md` to any page URL (`https://docs.avvio.xyz/webhooks.md`) for its markdown,
or request the page with `Accept: text/markdown`. Every page also has a
**Copy page** menu by its title.

## The skill

`https://docs.avvio.xyz/skill.md` is a standing brief for an agent: where the
docs are, how to authenticate, and the four mistakes that cost money. Skill
installers find it through `/.well-known/agent-skills/index.json` and
`/.well-known/skills/index.json`.

## Docs MCP server

`https://docs.avvio.xyz/mcp` serves these docs over Streamable HTTP with four
tools:

- `search_docs` returns the matching sections, ranked, with a URL for each.
- `fetch_page` returns one page.
- `list_endpoints` lists every operation in both contracts.
- `get_endpoint` returns one operation as markdown, with its parameters, an
  example request and its responses.

It holds no key and cannot reach the API.

## Payments MCP server

`npx -y @avvio/payments mcp` runs the MCP server in the `@avvio/payments` npm
package over stdio. It calls the API with the `AVVIO_API_KEY` and
`AVVIO_ORG_ID` in its environment, so an agent can price, send and track
payouts.

> **Give an agent a test key:** An `avvio_test_` key cannot move real money, and `doctor` and `get_policy`
> report which mode the key is in.
> Money-moving tools also require `confirm: true`, so a half-parsed instruction
> ("pay Maria") cannot become a payment.

### What the agent gets on connect

The server briefs the agent on call order, idempotency, bank returns and
sandbox accounts, and adds two prompts:

- `integrate_payouts` takes your `stack` and `use_case`, then builds the bank
  form, recipients, idempotent payouts, webhooks, reconciliation and tests.
- `sandbox_walkthrough` sends one test payout, paid then returned, in under a
  minute.

Both build from the reference integration
[avvio-payout-demo](https://github.com/anzolabs/avvio-payout-demo), live at
[payoutdemo.avvio.xyz](https://payoutdemo.avvio.xyz).

The [tool reference](#payments-mcp-tools) at the end of this page lists every
tool and its arguments.

## Four mistakes agents make here

- Retrying with a new `Idempotency-Key`, which sends the payout twice. Persist
  the key and reuse it ([Idempotency](/idempotency/)).
- Treating a timeout as a failure. The payout may exist; retry with the same key.
- Treating `completed` as final. A bank can return it days later
  ([Track status & failures](/status/)).
- Inventing corridor fields. Build the form from
  `GET /recipients/{orgId}/corridors`, because fields change with routing.

## Writing the integration yourself

Read the [Quickstart](/quickstart/) and the [recipes](/recipes/), then [Errors](/errors/) before any retry
logic, then [Go live](/going-live/). Generate a client from the spec instead of
hand-rolling HTTP:

```bash
npx @openapitools/openapi-generator-cli generate \
  -i https://docs.avvio.xyz/partner-payouts.openapi.yaml -g python -o ./avvio --package-name avvio_payouts
```

> **Danger:** The API reference's **Try It** console accepts an `avvio_test_*` key, and only
> there. Never generate a browser or mobile integration that contains a key, and
> never paste an `avvio_live_*` key into the console.

The CLI, MCP tools, endpoint table, samples and sandbox triggers here are
generated from source. If a page and the API disagree, the API is right; tell
us, with the `requestId`.

## Payments MCP tools

34 tools, read from the server's registered tool list. **confirm: true** marks the money-moving ones.

| Tool | Effect | What it does |
| --- | --- | --- |
| `list_corridors` | reads | List every currency this organization can pay out to, or pass one currency to use its exact approved provider routing. Read this instead of hardcoding a form: field names differ by corridor and can change. |
| `get_requirements` | reads | The exact beneficiary fields needed to pay out in one currency, with validation patterns. Call this before create_beneficiary. |
| `quote` | reads | Indicative price for a corridor with no beneficiary needed: what the recipient gets, the fee, the rate, and the corridor minimum and maximum. Use this while a user is still choosing an amount. It is an estimate, not a locked rate. |
| `create_beneficiary` | writes | Register who is being paid. Scope it to the end user paying them via endUserId, so each of your users only ever sees their own beneficiaries. Returns destinationAccountId, which send_payout needs. |
| `list_beneficiaries` | reads | Beneficiaries saved for one end user. Always pass endUserId for anything shown to a user; omitting it returns the whole organization. |
| `get_beneficiary` | reads | One beneficiary by the id this API returned, with their payment methods and each destinationAccountId. |
| `get_beneficiary_by_external_id` | reads | One beneficiary by your own id for them: the externalId you sent when you created them. Use this instead of listing everyone and filtering: it is unique per organization, so it returns exactly one or NOT_FOUND. |
| `update_beneficiary` | writes | Correct a beneficiary’s contact details: name, email, phone, country, individual/business. Only the fields you pass change. Bank details cannot be edited: a wrong account is a new payment method, and the old one is deleted. |
| `delete_beneficiary_method` | **confirm: true** | Remove one way of paying a beneficiary, such as an account that closed or one entered wrong. Irreversible, and the destinationAccountId it carried stops being payable, so it requires confirm:true. The beneficiary and their other methods are untouched. |
| `list_payment_reasons` | reads | The stated payment reasons this organization may use. Some corridors require one on a payout; read this rather than inventing a value, because a rejected one is a 400 on a payout already promised to somebody. |
| `send_payout` | **confirm: true** | This moves real money. Prices the payout and executes it, debiting your balance. Requires confirm:true. If it times out, the outcome is unknown: call again with the same idempotencyKey rather than starting over. |
| `get_payout` | reads | Current state of one payout. Always live, and authoritative, more so than a webhook you may have missed. |
| `list_payouts` | reads | Recent payouts for this organization, newest first. Filter by `reference` to find the payout behind your id. This is how you check whether a send whose response was lost (timeout, 5xx) actually went out, before retrying it with the same idempotencyKey. |
| `funding_accounts` | reads | Where to wire money to top up the balance that payouts debit. |
| `list_events` | reads | The change feed: one row per transition, with a `sequence` cursor. This is the reconciliation primitive: carry `nextSince` back as `since` and you observe every revision. Each row’s `data` is the webhook body for the same event (amounts, fee, reference). Payout, batch, approval and endpoint events share the feed; pass `type` to narrow it. |
| `list_approvals` | reads | Payouts and batch runs waiting on the organization’s human approvers. send_payout answers 202 with `approvalId` when a policy holds it; this is that queue. Approving is a dashboard action; there is no tool for it, by design. |
| `get_approval` | reads | One approval by the `approvalId` a 202 returned. Once `status` is `executed`, `payoutId` is the payout it became. |
| `list_audit_events` | reads | Who did what, from where, with which credential: every audited mutation on the organization, newest first, refused attempts included. Rows carry the key prefix, actor, IP, requestId, outcome and errorType. Page with `cursor` = the `nextCursor` from the last page. |
| `get_policy` | reads | What this organization is bound by, read live. Call it first: payout caps in USD (null = no cap), the approval threshold and how many approvers a held payout needs, which features are on (mass_payouts, developer), rate limits per minute, idempotency windows, the currencies that require purposeOfPayment, and fees.payout (the pre-quote fee schedule; null = only priced inside a quote). Plan sends against it instead of discovering a cap from a 422 or an approval from a 202. |
| `get_balance` | reads | The organization’s available balance. Check this before sending: an underfunded payout is refused, and the refusal is a 400 rather than a queued payment. |
| `list_balance_transactions` | reads | Every change to the balance, newest first, each with `balanceAfter`: funding, payouts, returns, holds and their release, adjustments. Page with `cursor` = the `nextCursor` from the last page. An empty page means no rows yet, not an error. |
| `get_funding` | reads | Deposit instructions for a payout that requires funding: the address, the exact amount, the network, and an expiry. Only some routings need this; the payout says so with `requiresFunding`. |
| `create_payout_link` | writes | Mint a one-time link that collects the recipient’s own bank details and pays them, so you never handle the details yourself. The link is a credential: it is the only thing needed to be paid, so send it to the person being paid and nobody else. |
| `create_product` | writes | Create a catalog product for checkout: one name, one fixed price in one currency. Links made from it copy the name and price at creation. |
| `list_products` | reads | The checkout catalog, active products first. Images are not on the list. |
| `create_checkout_link` | writes | Create a checkout link a buyer pays on a hosted page. Pass productId, or currency + items. publish:true makes it live and returns shareUrl, the URL to send the buyer to. clientReferenceId is the merchant’s join key, echoed on every checkout_payment event. If publish fails the draft is kept and the error names linkId. |
| `update_checkout_link` | writes | Edit a checkout link. A draft takes any create field. A live (sent) link takes exactly one field: expiresAt on its own, a new ISO-8601 instant or null to remove the deadline; anything else on a live link is refused, because repricing a URL a buyer may be looking at is a money bug. |
| `get_checkout_link` | reads | One checkout link: status, shareUrl, and received (what it has taken in). |
| `list_checkout_links` | reads | Checkout links, newest first. status is draft, sent (live), cancelled (paused) or expired (past its expiresAt). |
| `refund_checkout_payment` | **confirm: true** | This moves real money. Refunds a checkout payment to the buyer, whole (omit amount) or in part. Requires confirm:true and an idempotencyKey; the key must hold the refunds scope, granted by an owner or admin. On a timeout, call again with the same idempotencyKey. |
| `pause_checkout_link` | **confirm: true** | Stop a live checkout link taking payments. This is permanent: a paused link cannot be republished. Requires confirm:true. |
| `list_checkout_payments` | reads | Payments made on one checkout link, newest first. Amounts are base units with decimals beside them. The authoritative read; never trust a success redirect alone. |
| `confirm_funding` | **confirm: true** | Report the transaction that funded a payout. We read the chain before recording it: a hash that does not fund this payout is refused and nothing is written, so a rejection is always safe to correct. One transfer funds exactly one payout. |
| `cancel_payout` | **confirm: true** | Stop a payout that has not been funded yet: the recovery for one created by mistake. Once funded it cannot be canceled and you get PAYOUT_NOT_CANCELABLE, which is the honest answer rather than a cancellation that does not happen. |

### Tool arguments

#### list_corridors

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `currency` | string | — | Optional ISO code, e.g. MXN |

#### get_requirements

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `currency` | string | yes | ISO code, e.g. MXN |

#### quote

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `amount` | string | yes | Amount to send, e.g. "200.00" |
| `to` | string | yes | Destination currency, e.g. MXN |
| `from` | string | — | Source currency. Defaults to USD. |

#### create_beneficiary

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes | The recipient's full legal name. |
| `email` | string | — | Optional contact address kept on the beneficiary for your records. Not used to route the payout. |
| `country` | string | — | ISO-3166 alpha-2, e.g. MX |
| `currency` | string | yes | The payout currency, ISO 4217, such as `MXN`. |
| `endUserId` | string | — | Your id for the person sending the money. |
| `externalId` | string | — | Your own id for this beneficiary. Makes creation idempotent. |
| `details` | object | yes | Corridor fields from get_requirements, e.g. {"clabeNumber":"012..."} |

#### list_beneficiaries

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `endUserId` | string | — | Your id for the customer sending the money, never the recipient. |

#### get_beneficiary

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `recipientId` | string | yes | The beneficiary's `id`. |

#### get_beneficiary_by_external_id

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `externalId` | string | yes | Your id for this beneficiary, e.g. "payroll-4471". |

#### update_beneficiary

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `recipientId` | string | yes | The beneficiary's `id`. |
| `name` | string | — | The recipient's full legal name. |
| `email` | string | — | The recipient's email address. |
| `phone` | string | — | The recipient's phone number in E.164, such as `+525512345678`. |
| `country` | string | — | ISO-3166 alpha-2, e.g. MX |
| `type` | string | — | `individual` or `business`. |

#### delete_beneficiary_method

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `recipientId` | string | yes | The beneficiary's `id`. |
| `methodId` | string | yes | From the beneficiary’s paymentMethods[].id. |
| `confirm` | boolean | yes | Must be true. The account cannot be restored, only re-registered. |

#### send_payout

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `amount` | string | yes | The USD amount as a decimal string, such as `"200.00"`. |
| `destinationAccountId` | string | yes | From create_beneficiary or list_beneficiaries. |
| `endUserId` | string | — | Your id for the customer sending the money, never the recipient. |
| `endUserName` | string | — | That customer's display name. |
| `reference` | string | — | Your payment reference. |
| `purposeOfPayment` | string | — | One of the values `list_payment_reasons` returns, where the corridor requires a purpose. |
| `expectDestinationAmount` | string | — | What you told the payer they would receive. The send is refused if the binding quote drifts more than 2% from it. |
| `amountLeg` | string | — | Which side `amount` describes. 'source' (default) takes the fees out of what you send. 'destination' pays the beneficiary that exact figure in their currency and adds the fees to your debit. 'source_net' means the same but keeps the figure in the sender's currency ('send them $200 worth'), converted at the market rate. The two locking modes need capabilities.exactOutput from list_corridors. |
| `idempotencyKey` | string | yes | Required. A unique id you generate for this payout. If the call times out, call again with this same value, which replays the original payout instead of sending a second one. |
| `confirm` | boolean | yes | Must be true. Explicit acknowledgement that this moves money. |

#### get_payout

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `payoutId` | string | yes | The payout's `payoutId`. |

#### list_payouts

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `reference` | string | — | Your reference from send_payout. |
| `status` | string | — | pending, processing, completed, failed or canceled. |
| `endUserId` | string | — | Only payouts sent on behalf of this end user. |
| `limit` | number | — | How many to return (default 20). |
| `cursor` | string | — | nextCursor from the previous page. |

#### list_events

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `since` | string | — | A `sequence` from a previous page. Digits only. |
| `limit` | number | — | 1-500, default 100. |
| `payoutId` | string | — | Only this payout’s transitions. |
| `type` | string | — | Comma-separated event types, e.g. payout.completed,payout.failed,payout.returned. Unknown values are a 400. |

#### list_approvals

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string | — | pending, approved, rejected, expired, executing, executed, execution_failed, execution_unknown. |
| `limit` | number | — | 1-100, default 50. |

#### get_approval

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `approvalId` | string | yes | The `approvalId` a `202` returned. |

#### list_audit_events

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `cursor` | string | — | A `nextCursor` from a previous page. Digits only. |
| `limit` | number | — | 1-100, default 50. |
| `action` | string | — | e.g. payout.create, payout_batch.confirm, recipient.delete, api_key.rotate. |
| `resourceId` | string | — | Everything done to one payout, batch, approval, beneficiary, key or endpoint. |
| `apiKey` | string | — | A key prefix. |
| `actorUserId` | string | — | Only events by this dashboard user. |
| `createdAfter` | string | — | Inclusive, ISO-8601 with a timezone. |
| `createdBefore` | string | — | Inclusive, ISO-8601 with a timezone. |

#### list_balance_transactions

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `cursor` | string | — | A `nextCursor` from a previous page. Digits only. |
| `limit` | number | — | 1-100, default 100. |
| `type` | string | — | Comma-separated: funding, payout, payout_return, hold, hold_release, adjustment. |
| `orderId` | string | — | Everything that moved for one payout. |
| `currency` | string | — | Only rows in this currency, such as `USD`. |
| `createdAfter` | string | — | Inclusive, ISO-8601 with a timezone. |
| `createdBefore` | string | — | Inclusive, ISO-8601 with a timezone. |

#### get_funding

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `payoutId` | string | yes | The payout's `payoutId`. |

#### create_payout_link

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `amount` | string | yes | Decimal string, e.g. "200.00". |
| `destinationCurrency` | string | yes | ISO code, e.g. MXN |
| `endUserId` | string | yes | Your id for the person being paid. |
| `reference` | string | — | Your reference, echoed on the payout it creates. |
| `expiresInMinutes` | number | — | 1-10080, default 60. |

#### create_product

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes | The product name buyers see. |
| `currency` | string | yes | ISO code, e.g. USD |
| `unitAmount` | string | yes | Decimal string above zero, e.g. "150.00". |
| `description` | string | — | Shown to buyers on the checkout page. |

#### create_checkout_link

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `productId` | string | — | The product's `id`. |
| `currency` | string | — | Required without productId. |
| `items` | array | — | Required without productId. |
| `successUrl` | string | — | https only. |
| `cancelUrl` | string | — | Same rule as successUrl. |
| `clientReferenceId` | string | — | Letters, digits, - and _, up to 200. |
| `metadata` | object | — | Your own string key-value pairs, echoed back verbatim. |
| `fromName` | string | — | The seller name shown on the checkout page. |
| `memo` | string | — | A note shown to the buyer. |
| `expiresAt` | string | — | When the link stops taking payments: ISO-8601 with a timezone, in the future, at most a year away. Past it the page answers 410 and status reads expired. Omit for no deadline. |
| `publish` | boolean | — | true to make it live in the same call. |

#### update_checkout_link

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `linkId` | string | yes | The checkout link's `id`. |
| `expiresAt` | string,null | — | New deadline (ISO-8601 with a timezone, future, within a year), or null to clear it. |
| `successUrl` | string | — | Drafts only. https only. |
| `cancelUrl` | string | — | Drafts only. https only. |
| `clientReferenceId` | string | — | Drafts only. |
| `metadata` | object | — | Drafts only. Replaced whole. |
| `memo` | string | — | Drafts only. |

#### get_checkout_link

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `linkId` | string | yes | The checkout link's `id`. |

#### list_checkout_links

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string | — | Only links in this status. |
| `source` | string | — | api: links made with an API key. dashboard: made by a person. Omit for both. |
| `limit` | number | — | Page size. |
| `cursor` | string | — | The `nextCursor` from the previous page. |

#### refund_checkout_payment

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `paymentId` | string | yes | The payment id from list_checkout_payments. |
| `amount` | string | — | Decimal string in the payment’s currency. Omit to refund everything still refundable. |
| `reason` | string | — | Why you are refunding. |
| `note` | string | — | For the merchant’s team; never shown to the buyer. |
| `idempotencyKey` | string | yes | A new key per refund. Reuse it only to retry that same refund. |
| `confirm` | boolean | yes | Must be `true`. The tool refuses to run without it. |

#### pause_checkout_link

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `linkId` | string | yes | The checkout link's `id`. |
| `confirm` | boolean | yes | Must be `true`. The tool refuses to run without it. |

#### list_checkout_payments

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `linkId` | string | yes | The checkout link's `id`. |
| `limit` | number | — | Page size. |
| `cursor` | string | — | The `nextCursor` from the previous page. |

#### confirm_funding

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `payoutId` | string | yes | The payout's `payoutId`. |
| `transactionHash` | string | yes | 0x-prefixed 32-byte hex. |
| `confirm` | boolean | yes | Must be true. This commits funds you have already sent. |

#### cancel_payout

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `payoutId` | string | yes | The payout's `payoutId`. |
| `confirm` | boolean | yes | Must be true. Canceling is irreversible. |
