---
url: /docs/quickstart-payout.md
description: >-
  Send your first off-ramp payout from a BlindPay-managed wallet to a bank
  account on a development instance, using only the REST API.
---

This quickstart walks through a payout: funds leave a BlindPay-managed wallet and USD lands in a recipient's bank account. You will accept the terms of service, create a customer, create and fund a managed wallet, add a bank account, quote the payout, and execute it. Because BlindPay custodies the funding wallet, there is no on-chain signing or token approval; every step is a REST call. On a development instance the payout completes automatically a few seconds after you execute it.

## Before you begin

You need a BlindPay account and an API key for a development instance. See [Instances](/learn/instances) and [API keys](/learn/api-keys).

### Accept terms of service

Every instance requires a terms of service acceptance before you can create customers. For testing, you can accept on behalf of the customer; in production, your customer should accept the terms themselves.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/e/instances/in_000000000000/tos \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "idempotency_key": "<your_uuid>"
  }'
```

Open the URL from the response in your browser, accept the terms, and copy the `tos_id` shown on the confirmation screen. You will pass this `tos_id` when you create the customer in the next step.

### Create a customer

Every payout requires a customer that has completed KYC. This example creates an individual customer with standard KYC.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/customers \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "tos_id": "to_000000000000",
    "type": "individual",
    "kyc_type": "standard",
    "email": "email@example.com",
    "tax_id": "12345678",
    "address_line_1": "8 The Green",
    "address_line_2": "#12345",
    "city": "Dover",
    "state_province_region": "DE",
    "country": "US",
    "postal_code": "02050",
    "ip_address": "127.0.0.1",
    "phone_number": "+13022006100",
    "proof_of_address_doc_type": "UTILITY_BILL",
    "proof_of_address_doc_file": "https://example.com/proof-of-address.jpg",
    "first_name": "John",
    "last_name": "Doe",
    "date_of_birth": "1998-01-01T00:00:00Z",
    "id_doc_country": "US",
    "id_doc_type": "PASSPORT",
    "id_doc_front_file": "https://example.com/passport-front.jpg",
    "selfie_file": "https://example.com/selfie.jpg"
  }'
```

Save the `id` from the response: this is your customer ID (`re_...`).

On development instances, KYC is approved automatically. In production, automated review for standard KYC takes about 60 seconds.

### Create a managed wallet

Every payout needs a funding source, the wallet the settlement stablecoins are pulled from. A [managed wallet](/wallets) is the simplest one: BlindPay generates the address and holds the keys, so executing the payout later needs no approval or signature. This example creates it on Solana Devnet, the development network with a REST endpoint for minting test funds.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/wallets \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "network": "solana_devnet",
    "name": "Quickstart Wallet"
  }'
```

Save the `id` (`bl_...`) and the `address` from the response. You need the address for the next step and for executing the payout.

### Fund the wallet with USDB

Mint USDB, BlindPay's development-only test stablecoin, straight into the managed wallet. Pass the wallet's `address` and the amount of USDB to mint:

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/mint-usdb-solana \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "address": "YOUR_WALLET_ADDRESS",
    "amount": "100"
  }'
```

The response returns `success: true` with the on-chain signature. The wallet now holds 100 USDB to pay out from.

### Add a bank account

This is the payout destination, the bank account that receives the USD. This example adds a US ACH account. Use real, valid bank details, even on development.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/bank-accounts \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "type": "ach",
    "name": "Display Name",
    "beneficiary_name": "<Replace this>",
    "routing_number": "<Replace this>",
    "account_number": "<Replace this>",
    "account_type": "checking",
    "account_class": "individual"
  }'
```

Save the bank account ID (`ba_...`).

### Create a payout quote

A quote locks the conversion rate and fees for 5 minutes. The `network` and `token` describe the funding wallet: `solana_devnet` and `USDB` for the wallet you just funded.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/quotes \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "bank_account_id": "ba_000000000000",
    "currency_type": "sender",
    "cover_fees": false,
    "request_amount": 5000,
    "network": "solana_devnet",
    "token": "USDB"
  }'
```

`request_amount` is an integer in minor units, so `5000` here means $50.00. `cover_fees: false` means the fee is deducted from what the bank account receives, the common case. Save the quote ID (`qu_...`).

### Execute the payout

Execute the payout by passing the quote ID and the managed wallet's address as the funding source. Because BlindPay custodies the wallet, there is no approve or delegation step; this single call moves the funds.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/payouts/evm \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "quote_id": "qu_000000000000",
    "sender_wallet_address": "YOUR_WALLET_ADDRESS"
  }'
```

The response returns the payout with `status: "processing"`.

The endpoint is `/payouts/evm` regardless of the funding network; it handles managed wallets on every supported chain.

## What happens next

On a development instance, the payout completes automatically a few seconds after you execute it. Check for the `payout.complete` webhook to confirm. In production, settlement timing depends on the payout rail; see [cut-off times](/kb/cut-off-times).

Done. To send another payment, create a new payout quote and execute it again; each quote is single-use.

## Related

* [Pay out to bank](/payouts): full reference for every payout rail, including Pix, SPEI, and SWIFT
* [Bank transfer to stablecoins](/quickstart-payin): the payin counterpart of this guide
* [Managed wallet](/wallets): the funding wallet entity used in this quickstart
* [Webhooks](/learn/webhooks): handle `payout.complete` and other events in real time

This quickstart walks through an off-ramp payout: pulling USDB from a managed wallet and delivering USD to a bank account. You will accept the terms of service, create a customer, create and fund a managed wallet, add a bank account, create a payout quote, and execute the payout. Every step is a REST call, no on-chain signing involved.

If you want to fund the payout from a self-custodied wallet instead (with the on-chain authorization that entails), follow the [Payout with EVM](/payout-evm), [Stellar](/payout-stellar), or [Solana](/payout-solana) tutorials after this one.

## Before you begin

You need a BlindPay account and an API key for a development instance. See [Instances](/learn/instances) and [API keys](/learn/api-keys).

## Steps

### Accept terms of service

For testing you can accept the terms of service yourself. In production, your customer should be the one accepting them.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/e/instances/in_000000000000/tos \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "idempotency_key": "<your_uuid>"
  }'
```

Open the returned URL in your browser, accept the terms, and copy the `tos_id` shown on the confirmation screen. You will need it to create the customer.

### Create a customer

Every payout requires a customer that has completed KYC. On development instances, customers are auto-approved.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/customers \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "tos_id": "to_000000000000",
    "type": "individual",
    "kyc_type": "standard",
    "email": "email@example.com",
    "tax_id": "12345678",
    "address_line_1": "8 The Green",
    "address_line_2": "#12345",
    "city": "Dover",
    "state_province_region": "DE",
    "country": "US",
    "postal_code": "02050",
    "ip_address": "127.0.0.1",
    "phone_number": "+1234567890",
    "proof_of_address_doc_type": "UTILITY_BILL",
    "proof_of_address_doc_file": "https://pub-4fabf5dd55154f19a0384b16f2b816d9.r2.dev/v4-460px-Get-Proof-of-Address-Step-3-Version-2.jpg.jpeg",
    "first_name": "John",
    "last_name": "Doe",
    "date_of_birth": "1998-01-01T00:00:00Z",
    "id_doc_country": "US",
    "id_doc_type": "PASSPORT",
    "id_doc_front_file": "https://pub-4fabf5dd55154f19a0384b16f2b816d9.r2.dev/1000_F_365165797_VwQbNaD4yjWwQ6y1ENKh1xS0TXauOQvj.jpg",
    "selfie_file": "https://pub-4fabf5dd55154f19a0384b16f2b816d9.r2.dev/selfie.png"
  }'
```

This is the full standard KYC payload (`kyc_type: "standard"`): identity document, selfie, and proof of address. Save the customer ID (`re_...`) from the response.

### Create a managed wallet

The payout needs a funding source, the wallet the stablecoins are pulled from. A [managed wallet](/wallets) is the simplest one: BlindPay generates the address and holds the keys, so executing the payout later needs no approval or signature. This example creates it on Solana Devnet, the development network with a REST endpoint for minting test funds.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/wallets \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "network": "solana_devnet",
    "name": "Quickstart Wallet"
  }'
```

Save the `id` (`bl_...`) and the `address` from the response. You need the address for the next step and for executing the payout.

### Fund the wallet with USDB

Mint USDB, BlindPay's development-only test stablecoin, straight into the managed wallet. Pass the wallet's `address` and the amount of USDB to mint:

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/mint-usdb-solana \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "address": "YOUR_WALLET_ADDRESS",
    "amount": "100"
  }'
```

The response returns `success: true` with the on-chain signature. The wallet now holds 100 USDB to pay out from. See [Mint USDB](/mint-usdb) for minting on other networks.

### Add a bank account

This is the fiat destination for the payout, the bank account that receives the USD once the stablecoin is converted. This example adds a US ACH account. Use real, valid bank details, even on development.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/bank-accounts \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "type": "ach",
    "name": "Display Name",
    "beneficiary_name": "<Replace this>",
    "routing_number": "<Replace this>",
    "account_number": "<Replace this>",
    "account_type": "checking",
    "account_class": "individual"
  }'
```

Save the bank account ID (`ba_...`).

### Create a payout quote

A quote locks the conversion rate and fees for 5 minutes. The `network` and `token` describe the funding wallet: `solana_devnet` and `USDB` for the wallet you just funded.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/quotes \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "bank_account_id": "ba_000000000000",
    "currency_type": "sender",
    "cover_fees": false,
    "request_amount": 5000,
    "network": "solana_devnet",
    "token": "USDB"
  }'
```

`request_amount` is an integer in minor units, `5000` is $50.00. `cover_fees: false` means the customer's stablecoin amount absorbs the fee, the common case. Save the quote ID (`qu_...`).

### Execute the payout

Execute the payout by passing the quote ID and the managed wallet's address as the funding source. Because BlindPay custodies the wallet, there is no `approve` call, signature, or delegation; this single call moves the funds.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/payouts/evm \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "quote_id": "qu_000000000000",
    "sender_wallet_address": "YOUR_WALLET_ADDRESS"
  }'
```

The response returns the payout with `status: "processing"`. On a development instance, the payout completes automatically a few seconds after creation, no manual settlement step needed. You will receive a `payout.complete` webhook once it does.

Congratulations! You've completed your first off-ramp payout with BlindPay. To send another, create a new quote and execute again, each quote is single-use.

## Next steps

This quickstart used a managed wallet, so no on-chain authorization was needed. To pull funds from a self-custodied wallet instead, follow the per-network tutorials: [EVM](/payout-evm) (ERC-20 approve), [Stellar](/payout-stellar) (authorize + signed XDR), or [Solana](/payout-solana) (token delegation).

## Related

* [Payouts](/payouts): the full payout section, with a tutorial per funding path
* [Payins](/payins): accept fiat and deliver stablecoins to a wallet
* [Managed wallet](/wallets): the funding wallet entity used in this quickstart
* [Webhooks](/learn/webhooks): handle `payout.complete` and other real-time events
* [KYC](/kb/kyc): customer verification levels and required fields
