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

# Fund your balance

Most payouts are paid from a USD balance you hold with Avvio. You top it up by
wire or with USDC, and in the sandbox with one API call.
[Balance & funding](/products/balance-and-funding/) explains what the balance is made of.

1. Find where to wire with `GET /payments/organizations/{orgId}/payin-accounts`.
2. In the sandbox, credit the balance with `POST .../sandbox/fund` instead.
3. Check what you can send with `GET /payments/organizations/{orgId}/balance`.
4. For a payout that returns `requiresFunding: true`, fund that one payout from
   your wallet.

## 1. Find where to wire

```http
GET /payments/organizations/{orgId}/payin-accounts
x-api-key: avvio_live_…
```

```json
{
  "accounts": [
    {
      "id": "sbx_acct_usd_cmsx0h2k900a1n11ib3qz9v42",
      "currency": "USD",
      "shape": "us",
      "status": "active",
      "paymentRails": ["wire", "ach"],
      "settlesTo": "provider_balance",
      "destination": null,
      "balance": { "currency": "USD", "amount": 980000, "decimals": 2 },
      "depositInstructions": {
        "bank_name": "Example Bank",
        "account_number": "****4471",
        "routing_number": "123456789",
        "beneficiary_name": "Avvio",
        "reference": "ORG-7f3a91"
      }
    }
  ]
}
```

Wire to `depositInstructions`. Money you wire is held as your balance; it is not
forwarded anywhere, and payouts debit it. When there is nothing to show, a
live key gets `{ "accounts": [] }`; a test key also gets a `note` with the
reason. USD stablecoins in your
organization's wallet also count toward the balance.

Wire lead time depends on your bank and the receiving bank, so confirm it with
your Avvio contact and fund ahead of your first live run.

## 2. Fund the sandbox

There is no wire in the sandbox, and no `sandbox/fund` in production:

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

```json
{ "balance": "10000.00" }
```

`amount` defaults to `10000.00`. Skip this once to see the
`400 INSUFFICIENT_BALANCE` your integration gets when the balance is short.

## 3. Check the balance

```http
GET /payments/organizations/{orgId}/balance
x-api-key: avvio_live_…
```

```json
{
  "currency": "USD",
  "amount": "13185.03",
  "balances": [{ "currency": "USD", "amount": "13185.03" }],
  "provider": [{ "currency": "USD", "amount": "10000.00" }],
  "wallet": [{ "currency": "USDC", "network": "Ethereum", "amount": "3185.030147" }],
  "unavailable": [],
  "ledger": [{ "currency": "USD", "available": "9800.00", "held": "200.00", "total": "10000.00" }]
}
```

Size payouts against `balances`. When `unavailable` is non-empty the figures
are a floor, so retry before deciding you cannot fund a payout.
[Reading the balance](/products/balance-and-funding/#reading-the-balance) explains every
field.

## 4. Fund a payout that waits for you

Some crypto and dedicated settlement routings price the transfer and wait for
you to fund that one payout from your own wallet. You send the transfer from
your registered wallet and report its transaction hash, unless your
organization has opted in to
[automatic funding](#let-us-fund-it-for-you-opt-in). A payout that needs
funding says so in the creation response:

```json
{
  "requiresFunding": true
}
```

### Read the funding instructions

Call `GET /payments/organizations/{orgId}/payouts/{payoutId}/funding`:

```http
GET /payments/organizations/{orgId}/payouts/sbx_pay_7c1c0f2e-6d9b-4a3e-9d1a-2f4b8c9e0a11/funding
x-api-key: avvio_live_…
```

Response:

```json
{
  "payoutId": "sbx_pay_7c1c0f2e-6d9b-4a3e-9d1a-2f4b8c9e0a11",
  "amount": "200.00",
  "currency": "USDC",
  "depositAddress": "0x71C...492",
  "network": "base",
  "expiresAt": null
}
```

This is a pure read and starts no clock, so poll it freely.

`amount` already includes the payout fee; nothing is added at funding time. See
[Fees](/payouts/#fees).

`expiresAt` is normally `null`; it carries a time only when the network
publishes one. Before sending against old instructions, check the payout's
status at `GET /payments/organizations/{orgId}/orders/{payoutId}`.

### Confirm the transfer

After you broadcast the transfer from your registered wallet, send its hash:

```http
POST /payments/organizations/{orgId}/payouts/sbx_pay_7c1c0f2e-6d9b-4a3e-9d1a-2f4b8c9e0a11/funding/confirm
x-api-key: avvio_live_…
Idempotency-Key: 5a81e921-bc01-447a-9a11-0982716a5b42
Content-Type: application/json

{
  "transactionHash": "0x98a123...45f"
}
```

`transactionHash` is required. Confirmation also accepts
`X-Allow-Duplicate: true` ([Idempotency](/idempotency/)).

Before recording the deposit, Avvio checks the chain, on every network, Solana included. The transaction must:
1. Exist on the designated network.
2. Have successfully confirmed.
3. Have transferred at least the required token amount to the exact `depositAddress`.
4. Originate from the wallet registered for this payout, where the network
   exposes that check.

### Confirmation errors

| Status | Type | Action |
|---|---|---|
| `400` | `FUNDING_TRANSACTION_INVALID` | We read the transaction and it failed a check (reverted, wrong address, too little). Nothing is recorded and the payout stays open; send a correct transfer and confirm its hash |
| `409` | `FUNDING_NOT_YET_VERIFIABLE` | We could not verify it yet: not mined or not indexed. Your transfer is unaffected. Back off and confirm the same hash again |

[Errors](/errors/) lists the rest.

### Cancel a payout you will not fund

CLI:

```bash
avvio-payments cancel <payoutId>
```

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/$payoutId/cancel" \
  -H "x-api-key: $AVVIO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY"
```

Node:

```js
await avvio.cancelPayout(payoutId);   // only before it is funded
```

Python:

```python
import os
import uuid
import requests

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

You can cancel only a payout still waiting on your own funding
(`requiresFunding`). It reports `canceled` and can no longer be funded. It was
never debited, so your balance does not change and no ledger row is written.
Once funded, cancel returns `PAYOUT_NOT_CANCELABLE`; it cannot stop a payout in
flight.

### Let us fund it for you (opt-in)

Ask us to enable automatic funding and we fund these payouts from your
organization's own wallet. Your API calls stay the same.

`POST /payouts` then sends the pay-in itself, a gas-covered USDC transfer from
your wallet, verified as above. The response reads `status: "processing"`, or
`pending` with `requiresFunding: true` while it confirms, usually within a
minute or two; poll the order or take the webhook. If the wallet can't cover it
or the transfer can't be sent, nothing is sent and the payout is left as a
manually funded one, `requiresFunding: true` with the instructions above still
valid.

> [!CAUTION]
> Once you see `processing`, or a `transactionHash` on the order, the pay-in is
> on its way. Funding that payout a second time sends the money twice. While our
> transfer is in flight, the payout cannot be canceled.
