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

# Wallet payouts

> Send USDC from a USDC account to a wallet address on Base, Polygon, Ethereum or Solana.

A wallet payout sends USDC from one of your USDC accounts to an address on a public chain. It uses the same destinations, quotes and transfers as a bank payout. What differs is the route, the one field that identifies the payee, and what can go wrong.

<Warning>
  A payout that reaches the chain cannot be recalled. Check the address and the chain before you send: USDC sent to an address on the wrong chain, or to an address nobody controls, is gone.
</Warning>

## What you need

* **A USDC account** whose deposit addresses Sakawave issued. Not every USDC account can pay a wallet. If yours cannot, the preview refuses it before anything is debited, with `409 transfer_source_account_ineligible`.
* **Tier 3.** Crypto withdrawals are gated at tier 3; below it the transfer is refused with `403`, `reason: "feature_not_available"`.
* **The route for the chain.** Each chain is its own route, with `paymentMethod: "stablecoin-transfer"` and the chain as its `scheme`.

| `scheme` | Chain | Address format |
| - | - | - |
| `base` | Base | `0x` followed by 40 hex characters |
| `polygon` | Polygon | `0x` followed by 40 hex characters |
| `ethereum` | Ethereum | `0x` followed by 40 hex characters |
| `solana` | Solana | 32 to 44 base58 characters |

List the routes with [`GET /v1/currencies/USDC/routes`](/api-reference/currencies-and-countries/list-routes-for-a-currency). A wallet route has no country, so always send its `routeId`: without one, a destination is resolved as a bank transfer and needs a country.

## Order of operations

```mermaid theme={null}
flowchart LR
    R["GET /v1/currencies/USDC/routes"] --> D["POST /v1/transfer-destinations<br/>routeId + walletAddress"]
    D --> Q["POST /v1/transfer-quotes"]
    Q --> T["POST /v1/transfers"]
    T --> S["pending → completed"]
```

### 1. Create the destination

```bash theme={null}
curl --request POST \
  --url "$SAKAWAVE_BASE_URL/v1/transfer-destinations" \
  --header "Authorization: Bearer $SAKAWAVE_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "type": "external",
    "routeId": "01KZ6Q8XAV80PMBGPFQ7W3X6EA",
    "currency": "USDC",
    "accountName": "Ada Obi",
    "walletAddress": "0x1234567890123456789012345678901234567890"
  }'
```

`accountName` is the person or business that holds the wallet. It is kept with the payout for your records and ours; it is not checked against the chain, because a chain does not know who holds an address.

Before the destination is created, the address is checked against the route's chain, and screened against sanctions lists. A saved recipient works the same way: its payment detail takes `walletAddress` in `fields`, and it is checked and screened on creation.

### 2. Quote and send

Quote and send as for any same-currency transfer, from the USDC account, in USDC. The preview shows the fee before you commit.

```jsonc theme={null}
{ "amountSide": "source", "sourceAmount": "1250000000" } // 12.5 USDC
```

USDC is held at 8 decimals, like every crypto balance, but carries 6 on chain. An amount must therefore be a whole number of millionths: a multiple of `100` in minor units. Anything finer cannot be sent, and the transfer fails with the debit returned.

### 3. Follow the transfer

The account is debited when you create the transfer, and the transfer stays `pending` until the chain confirms it, usually within a few minutes. Webhooks report each change, as for any transfer.

| Status | Meaning | Debit |
| - | - | - |
| `pending` | Sent, or waiting to be sent | Taken |
| `completed` | Confirmed on chain | Taken |
| `failed` | Not sent, or refused on chain | Returned |

A transfer stays `pending`, rather than failing, while something on our side holds it up: for example, the sanctions lists being refreshed. It is sent as soon as that clears, and you do not need to send it again.

## Errors

| Code | When | What to do |
| - | - | - |
| `wallet_address_invalid` (400) | The address is not an address on the route's chain | Check the address and that you chose the right chain's route |
| `wallet_address_sanctioned` (403) | The address is on a sanctions list | Do not retry. The address cannot be paid |
| `wallet_screening_unavailable` (503) | The sanctions lists cannot be confirmed current | Try again later |
| `transfer_provider_unavailable` (503) | Wallet payouts are paused | Try again later |
| `transfer_source_account_ineligible` (409) | The account cannot pay a wallet address | Send from a USDC account that can |
| `403` with `reason: "feature_not_available"` | Your business is below tier 3 | Complete the verification for tier 3 |
| `destination_country_required` (409) | No `routeId` was sent | Send the wallet route's `routeId` |

An address that is screened clear when you save it is screened again when it is paid. A transfer to an address listed in between fails, and the debit is returned.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.