---
url: /docs/stablecoin/wallets.md
description: >-
  Full reference for BlindPay-managed wallets (bl_): create, receive
  stablecoins, collect fiat, send fiat, and send stablecoins.
---

A managed wallet is a BlindPay-custodied wallet: BlindPay generates the address, holds the keys, and your customer's balance moves through your product rather than a browser extension or a signed transaction. This page is the full reference for the managed wallet entity (`bl_...`). For the customer-controlled alternative, see [blockchain wallets](/stablecoin/blockchain-wallets).

## Supported chains and tokens

| Chain | Development | Production | Tokens |
| --- | --- | --- | --- |
| Ethereum | `sepolia` | `ethereum` | USDC, USDT |
| Base | `base_sepolia` | `base` | USDC, USDT |
| Polygon | `polygon_amoy` | `polygon` | USDC, USDT |
| Arbitrum | `arbitrum_sepolia` | `arbitrum` | USDC, USDT |
| Solana | `solana_devnet` | `solana` | USDC, USDT |

`USDB` is also available on every development network above, it's BlindPay's test stablecoin and only exists on development instances.

A receiver can hold up to 10 managed wallets.

## Prerequisites

A customer must exist and have `kyc_status: "approved"` before you can create a wallet for them.

## Create a managed wallet

```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": "polygon",
    "external_id": "your-database-id",
    "name": "Blindpay Wallet"
  }'
```

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `network` | string | Yes | One of the chains in the table above |
| `name` | string | Yes | Max 255 characters |
| `external_id` | string | No | Your own correlation ID, max 255 characters |

BlindPay generates the address server-side, you never supply one. Creating a wallet fires a `wallet.new` webhook with the same payload as the GET response. The response returns the wallet, including its `id` (`bl_...`) and `address`:

```json
{
  "id": "bl_000000000000",
  "network": "polygon",
  "address": "0x1234567890abcdef1234567890abcdef12345678",
  "name": "Blindpay Wallet",
  "external_id": "your-database-id",
  "created_at": "2026-01-01T00:00:00.000Z"
}
```

### Get a managed wallet

```bash [cURL]
curl --request GET \
  --url https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/wallets/bl_000000000000 \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json'
```

## Receive stablecoins

Share the wallet `address` with anyone sending stablecoins from an external wallet. There is no approval or signature step on the receiving end, any transfer to that address that arrives on the matching network credits the wallet.

Every time stablecoins land in the wallet, a `wallet.inbound` webhook fires with this payload:

```json [wallet.inbound]
{
  "id": "bl_000000000000",
  "address": "0x1234567890abcdef1234567890abcdef12345678",
  "network": "base",
  "token": {
    "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "id": "usdc",
    "symbol": "USDC",
    "amount": 100
  }
}
```

`wallet.inbound` only fires for USDC and USDT deposits. See [webhooks](/learn/webhooks) for signature verification.

## Collect fiat

You can collect a fiat payment and have the equivalent stablecoins delivered straight into a managed wallet. This is the same on-ramp flow as any payin, with one difference: pass `wallet_id` instead of `blockchain_wallet_id` when creating the payin quote.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/payin-quotes \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "wallet_id": "bl_000000000000",
    "currency_type": "sender",
    "cover_fees": true,
    "request_amount": 1000,
    "payment_method": "pix",
    "token": "USDC"
  }'
```

Continue with `POST /payins/evm` using the resulting `payin_quote_id`. Stablecoins land in the managed wallet's balance and a `wallet.inbound` webhook fires alongside `payin.complete`. See [on-ramp](/stablecoin/receive) for the full multi-corridor flow, payment methods, and cover\_fees details.

## Send fiat

You can fund a payout from a managed wallet's balance instead of an external wallet. Create a payout quote exactly as described in [off-ramp](/stablecoin/send), then pass the managed wallet's address as `sender_wallet_address` when you execute the payout. Because BlindPay already custodies the wallet, there is no `approve` call or signature step, the payout executes directly.

```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": "0x1234567890abcdef1234567890abcdef12345678"
  }'
```

See [off-ramp](/stablecoin/send) for creating the payout quote, per-network detail, and testing amounts.

## Send stablecoins

To move stablecoins out of a managed wallet to another managed wallet or an external address, create a transfer quote and execute it before the quote expires. See [cross-chain transfer](/stablecoin/transfer) for the full request and response fields.

## Related

* [Blockchain wallets](/stablecoin/blockchain-wallets): the customer-controlled alternative to a managed wallet
* [On-ramp](/stablecoin/receive): collect fiat and deliver stablecoins to a wallet
* [Off-ramp](/stablecoin/send): convert a wallet's stablecoin balance to fiat
* [Cross-chain transfer](/stablecoin/transfer): move stablecoins between wallets
* [Webhooks](/learn/webhooks): `wallet.new`, `wallet.inbound`
