---
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.

# Quickstart

Five calls take a test key to a payout in Mexico. Everything runs in the
sandbox, where no real money moves. The
[Mexico recipe](/recipes/send-your-first-payout-to-mexico/) runs the same calls
one step at a time, with every response, the corridor's fields and a failure on
purpose.

> [!NOTE]
> **Before you start**
> Create a **test key** in Dashboard → Developers and note your organization
> id. The key is shown once, so copy it then.

```bash
export AVVIO_API_KEY=avvio_test_…
export AVVIO_ORG_ID=cmsx…        # a cuid, not an org_ prefix
export AVVIO_BASE_URL=https://api.avvio.xyz/business/api/v1
```

For the Node tabs, install the SDK and create the client once; every Node tab
below uses this `avvio`:

```js
// npm i @avvio/payments
import { PayoutsClient } from '@avvio/payments';

// Reads AVVIO_API_KEY, AVVIO_ORG_ID and AVVIO_BASE_URL from the environment.
const avvio = new PayoutsClient();
```

Send the key as `x-api-key` on every request; there is nothing to sign.
Production uses the same base URL, and the `avvio_test_` prefix keeps these
calls in your sandbox.

> [!WARNING]
> Each sample mints a new `Idempotency-Key` for its own call. Reuse a key only
> to retry that exact request. The same payout under a new key is refused with
> `409 DUPLICATE_REQUEST_DETECTED` for 15 minutes, and pays twice after that
> ([Idempotency](/idempotency/)).

---

## 1. Fund your sandbox balance

CLI:

```bash
avvio-payments fund --amount 5000.00
```

curl:

```bash
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/sandbox/fund" \
  -H "x-api-key: $AVVIO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "content-type: application/json" \
  -d '{
        "amount": "5000.00"
      }'
```

Node:

```js
await avvio.fund('5000.00');   // test keys only
```

Python:

```python
import os
import uuid
import requests

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']}/sandbox/fund",
    headers={
        "x-api-key": os.environ["AVVIO_API_KEY"],
        "Idempotency-Key": idempotency_key,
    },
    json={
        "amount": "5000.00"
    },
)
print(res.status_code, res.json())
```

Payouts draw on your USD balance. A `200` also proves the key works.

---

## 2. Register the recipient

CLI:

```bash
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
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
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
import os
import uuid
import requests

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
```

Mexico needs one field, `clabeNumber`. Each tab saves
`method.destinationAccountId` as `DESTINATION_ACCOUNT_ID`: you pay that id, not
the recipient `id`. Other countries need other fields
([Register recipients](/recipients/)).

---

## 3. Price it, then send it

CLI:

```bash
avvio-payments quote --amount 200.00 --to MXN
```

curl:

```bash
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
const quote = await avvio.quote({
  amount: '200.00',
  to: 'MXN',
});
// → { sourceAmount, destinationAmount, fee, rate, limits, indicative: true }
```

Python:

```python
import os
import requests

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
avvio-payments pay --amount 200.00 \
  --to "$DESTINATION_ACCOUNT_ID" \
  --expect 3384.65 \
  --end-user customer_42 --reference ZZ-2026-0042
```

curl:

```bash
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
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
import os
import uuid
import requests

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())
```

Send the amount you showed as `expectDestination`. If the price drifts more
than `maxDriftBps` (default 2%) from it, the call fails with
`RATE_DRIFT_EXCEEDED` and nothing is sent. Keep `payoutId` for step 4. Sending
the same payout again under a new key within 15 minutes (running a second tab,
say) is refused with `409 DUPLICATE_REQUEST_DETECTED` and nothing is sent; change
`reference` to send another.

> [!CAUTION]
> **A timeout is not a failure**
> After a timeout the payout may exist. Retry with the same `Idempotency-Key`
> to get it back. A new key is refused for 15 minutes
> (`409 DUPLICATE_REQUEST_DETECTED`) and pays twice after that.

---

## 4. Read the payout

```bash
payoutId=sbx_pay_…   # from step 3's response
```

CLI:

```bash
avvio-payments status $payoutId
```

curl:

```bash
curl -s "$AVVIO_BASE_URL/payments/organizations/$AVVIO_ORG_ID/orders/$payoutId" \
  -H "x-api-key: $AVVIO_API_KEY"
```

Node:

```js
const order = await avvio.getPayout(payout.payoutId);
// pending → processing → completed, and sometimes back to failed
```

Python:

```python
import os
import requests

payoutId = "<payoutId>"

res = requests.get(
    f"{os.environ['AVVIO_BASE_URL']}/payments/organizations/{os.environ['AVVIO_ORG_ID']}/orders/{payoutId}",
    headers={
        "x-api-key": os.environ["AVVIO_API_KEY"],
    },
)
print(res.status_code, res.json())
```

In the sandbox the payout reaches `completed` 10 to 20 seconds after you create
it. To follow many payouts, use [webhooks](/webhooks/) and the
[event feed](/reconciliation/) rather than polling: `GET …/orders/{payoutId}`
shares the default 100-requests-a-minute limit, so poll one payout no more than
about every 5 seconds. The [recipe](/recipes/send-your-first-payout-to-mexico/) shows each
response and makes a payout fail on purpose; run that before you go live.

---

## Other languages

The OpenAPI spec generates a client in any language, and our CI checks the
spec's schemas against live responses (it does not build or run a generated
client). Swap `-g python` for `java`, `go`, `ruby`, `csharp`
or `php`.

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

## Next steps

- [Send your first payout to Mexico](/recipes/send-your-first-payout-to-mexico/), step by step
- [Receive and verify webhooks](/recipes/receive-and-verify-webhooks/)
- [Go live](/going-live/)
- [Errors](/errors/)
- [Build with AI](/build-with-ai/)
