How To: Implement Merchant Payouts (From BYO Wallet)

Developers can use this documentation to implement merchant payouts (from your own crypto wallet) to an end-user’s bank account.

Merchant (BYO Wallet) Payout Guide

Overview

This guide enables merchants to send fiat payouts to end-users’ bank accounts using your own crypto wallet as the source of funds. All payouts are processed via API integration.


Prerequisites

Your Own Crypto Wallet

Have your merchant crypto wallet ready as the source of funds

Understand Flow of Funds

Review the merchant payout flow before implementation

API Implementation Required

Coinflow does not provide a pre-built UI for merchant payouts - API integration required

Wallet Signing Capability

Your wallet must be able to sign transactions on the blockchain

Important Implementation Note

This flow is similar to the Merchant (Coinflow Wallet) Payout flow except for the endpoint used to initiate payouts (Step 5). Make sure to understand your flow of funds before proceeding.


Flow of Funds


Implementation Guide

1

Step 1: KYC/KYB Verification for Withdrawers

To complete a payout/withdraw, every Withdrawer must complete verification before they can proceed with a payout through Coinflow. Withdrawers only need to KYC the first time they withdraw and do not need to KYC again for any subsequent withdrawals.

Choose your KYC implementation method:

Merchants who want to use Coinflow for KYC should call Register User.

U.S. Withdrawers

Endpoint: POST /api/withdraw/kyc

Request
1curl --location 'https://api-sandbox.coinflow.cash/api/withdraw/kyc' \
2--header 'Authorization: YOUR_API_KEY' \
3--header 'accept: application/json' \
4--header 'content-type: application/json' \
5--header 'x-coinflow-auth-user-id: usher' \
6--data-raw '{
7 "info": {
8 "email": "usher@atl.com",
9 "firstName": "usher",
10 "surName": "raymond",
11 "physicalAddress": "2800 N Damen Ave",
12 "city": "Chicago",
13 "state": "IL",
14 "zip": "60625",
15 "country": "US",
16 "dob": "19761014",
17 "ssn": "1234"
18 }
19}'
Response
1{
2 "withdrawer": {
3 "_id": "672400ead654e5cdd247b33f",
4 "currency": "USD",
5 "email": "usher@atl.com",
6 "verification": {
7 "status": "approved"
8 }
9 }
10}

Non-U.S. Withdrawers

Endpoint: POST /api/withdraw/kyc

Request
1curl --request POST \
2--url https://api-sandbox.coinflow.cash/api/withdraw/kyc \
3--header 'Authorization: YOUR_API_KEY' \
4--header 'accept: application/json' \
5--header 'content-type: application/json' \
6--header 'x-coinflow-auth-user-id: dwaynejohnsongb123' \
7--data '{
8 "merchantId": "testtest",
9 "email": "dwaynejohnsongb@gmail.com",
10 "country": "GB"
11}'
Response
1{
2 "withdrawer": {
3 "_id": "676091072cd3ae949702b0ea",
4 "currency": "GBP",
5 "email": "dwaynejohnsongb@gmail.com",
6 "verification": {
7 "status": "approved"
8 }
9 }
10}

Merchants who want to pass KYC data from their existing KYC provider can call our Register User via Document endpoint.

Endpoint: POST /api/withdraw/kyc-doc

Request
1curl --request POST \
2--url https://api-sandbox.coinflow.cash/api/withdraw/kyc-doc \
3--header 'accept: application/json' \
4--header 'content-type: multipart/form-data' \
5--header 'x-coinflow-auth-session-key: YOUR_SESSION_KEY' \
6--form email=dwaynejohnsonus@gmail.com \
7--form country=US \
8--form idType=ID_CARD \
9--form idFront='@1128061-ID_front.png' \
10--form idBack='@012e6a1-ID_back.png' \
11--form merchantId=testtest
Response
1{
2 "withdrawer": {
3 "_id": "67449b17d654e5cdd2925f1c",
4 "currency": "USD",
5 "email": "testtasha@coinflowlabs.app",
6 "verification": {
7 "status": "approved"
8 }
9 }
10}

Merchants who want to share Sumsub data with Coinflow will need to enter a tri-party agreement with Sumsub and Coinflow. Reach out to the Coinflow team with your Sumsub client ID to get started.

Once this agreement has been signed, follow these steps:

  1. Call Sumsub’s Generate Share Token endpoint to obtain a token.
  2. Call our Register User Via Share Token endpoint to pass KYC data.
Request
1curl --request POST \
2--url https://api-sandbox.coinflow.cash/api/withdraw/kyc/share-token \
3--header 'Authorization: YOUR_API_KEY' \
4--header 'accept: application/json' \
5--header 'content-type: application/json' \
6--header 'x-coinflow-auth-user-id: user123' \
7--data '{
8 "vendor": "sumsub",
9 "shareToken": "YOUR_SHARE_TOKEN",
10 "country": "US",
11 "merchantId": "testtest",
12 "email": "testuser@test.com"
13}'
Response
1{
2 "withdrawer": {
3 "_id": "67449b17d654e5cdd2925f1c",
4 "currency": "USD",
5 "email": "testtasha@coinflowlabs.app",
6 "verification": {
7 "status": "approved"
8 }
9 }
10}

Merchants must receive approval from the Coinflow Compliance team regarding approval of your KYC attestation program. Once you’ve receive approval, follow these implementation steps.

Request
1curl --request POST \
2 --url https://api-sandbox.coinflow.cash/api/withdraw/kyc/attested \
3 --header 'Authorization: YOUR_API_KEY' \
4 --header 'accept: application/json' \
5 --header 'content-type: application/json' \
6 --header 'x-coinflow-auth-user-id: user-id' \
7 --data '
8{
9 "email": "djohnson051972@gmail.com",
10 "firstName": "Dwayne",
11 "surName": "Johnson",
12 "physicalAddress": "201 E Randolph St",
13 "city": "Chicago",
14 "state": "IL",
15 "zip": "60601",
16 "country": "US",
17 "dob": "05021972",
18 "ssn": "1234"
19}
20'
Response
1{
2 "withdrawer": {
3 "_id": "685d8a89e36b426f2df64069",
4 "__v": 0,
5 "availability": {
6 "status": "Functional",
7 "reason": "Initial",
8 "editor": "system",
9 "updatedAt": "2025-06-26T17:59:37.451Z"
10 },
11 "currency": "USD",
12 "email": "djohnson051972@gmail.com",
13 "merchant": "6840bca9c7cb21ee5baaae76",
14 "originalCurrency": "USD",
15 "riskScoreOverride": false,
16 "user": true,
17 "verification": {
18 "hash": "ce749aa83c2efab20c4e1bfeca602f0674e1cf1b",
19 "vendor": "persona",
20 "reference": "ver_R6E6KrEK5rZN36Hd8d7gPaKg1cms",
21 "status": "attested"
22 },
23 "wallets": [
24 {
25 "wallet": "user-id",
26 "blockchain": "user"
27 }
28 ],
29 "watchlistExempt": "Unknown"
30 }
31}
2

Step 2: Get Withdrawer Details

After calling Coinflow’s withdraw endpoints, you must call Get Withdrawer to get the latest verification status. This endpoint will tell you the user’s verification status. The get withdrawer endpoint can also be queried at any time to get more information about a withdrawer who has already completed KYC/KYB.

Endpoint: GET /api/withdraw

Request
1curl --request GET \
2 --url https://api-sandbox.coinflow.cash/api/withdraw \
3 --header 'Authorization: YOUR_API_KEY' \
4 --header 'accept: application/json' \
5 --header 'x-coinflow-auth-user-id: usher'
3

Step 3: Add a Payout Destination

Want to use Coinflow’s UI for KYC and Bank Authentication?

Merchants can choose to use Coinflow’s UI for KYC and bank authentication, saving time by avoiding the need to build these flows and add payout destinations. You’ll only need to create the UI for displaying quotes and initiating payouts.

If you choose to use our UI, you do not need to separately implement Step 3: Add A Payout Destination as the bank auth UI also handles linking payout destinations.

Withdrawers must link a payout destination so we know where to send the funds.

1. Withdrawers in the U.S.

Withdrawers in the U.S.

If withdrawers are in the U.S. and want to receive USD, they can link their debit card or bank account.

Add a debit card as a payout destination:
Request
1curl --request POST \
2 --url https://api-sandbox.coinflow.cash/api/withdraw/debit-card \
3 --header 'Authorization: <YOUR_API_KEY>' \
4 --header 'accept: application/json' \
5 --header 'content-type: application/json' \
6 --header 'x-coinflow-auth-user-id: usher' \
7 --data '{
8 "cardToken": "411111YJM5TX1111",
9 "expMonth": "10",
10 "expYear": "29"
11 }'
Add a bank account as a payout destination:
Request
1curl --location 'https://api-sandbox.coinflow.cash/api/withdraw/account' \
2--header 'Authorization: <YOUR_API_KEY>' \
3--header 'accept: application/json' \
4--header 'content-type: application/json' \
5--header 'x-coinflow-auth-user-id: usher' \
6--data '
7{
8 "type": "checking",
9 "alias": "Ushers Savings 1",
10 "accountNumber": "1111222233330000",
11 "routingNumber": "333333334"
12}
13'
Response
{
"withdrawer": {
"_id": "672400ead654e5cdd247b33f",
"__v": 0,
"currency": "USD",
"email": "usher@atl.com",
"isBlocked": false,
"merchant": "6723f186b2f506b29dbee63d",
"originalCurrency": "USD",
"user": true,
"verification": {
"hash": "02154e69e0f38f2b31dec3b658535fa1cc283063",
"vendor": "persona",
"reference": "ver_DisMcS9M3HftnJYPpFSowNEWHyjT",
"status": "approved"
},
"wallets": [
{
"wallet": "usher",
"blockchain": "user"
}
],
"watchlistExempt": false,
"bankAccounts": [
{
"alias": "Ushers Savings 1",
"token": "0dc36240-29fc-4708-81f6-bcab19e6e597",
"routingNumber": "333333334",
"last4": "0000",
"accountHash": "cb20055931a543bcfe3183541f335f031452055a",
"rtpEligible": false,
"reference": "67240124b2f506b29dbef137",
"isDeleted": false
}
],
"cards": [
{
"last4": "1111",
"type": "VISA",
"disbursementStatus": "Immediate",
"token": "411111YJM5TX1111",
"createdAt": "2024-10-31T22:13:56.435Z"
}
],
"ibans": [],
"pixes": [],
"rtpDisabled": false,
"cardDisabled": false
}
}
2. Withdrawers in the EU/UK

If withdrawers reside in the EU or UK, they can link their IBAN to receive EUR or GBP.

Add an IBAN account:
Request
1curl --location 'https://api-sandbox.coinflow.cash/api/withdraw/iban' \
2--header 'Authorization: <YOUR_API_KEY>' \
3--header 'accept: application/json' \
4--header 'content-type: application/json' \
5--header 'x-coinflow-auth-user-id: usher' \
6--data '
7{
8 "alias": "Ushers Savings 1",
9 "number": "<Iban number>",
10 "sortCode": "<UK Sort Code>"
11}
12'
Response
1{
2 "withdrawer": {
3 "_id": "672400ead654e5cdd247b33f",
4 "__v": 0,
5 "currency": "USD",
6 "email": "usher@atl.com",
7 "isBlocked": false,
8 "merchant": "6723f186b2f506b29dbee63d",
9 "originalCurrency": "USD",
10 "user": true,
11 "verification": {
12 "hash": "02154e69e0f38f2b31dec3b658535fa1cc283063",
13 "vendor": "persona",
14 "reference": "ver_DisMcS9M3HftnJYPpFSowNEWHyjT",
15 "status": "approved"
16 },
17 "wallets": [
18 {
19 "wallet": "usher",
20 "blockchain": "user"
21 }
22 ],
23 "watchlistExempt": false,
24 "bankAccounts": [],
25 "cards": [],
26 "ibans": [{
27 "alias": "Ushers Savings 1",
28 "token": "0dc36240-29fc-4708-81f6-bcab19e6e597",
29 "last4": "0000",
30 "accountHash": "cb20055931a543bcfe3183541f335f031452055a",
31 "reference": "67240124b2f506b29dbef137",
32 "isDeleted": false
33 }],
34 "pixes": [],
35 "rtpDisabled": false,
36 "cardDisabled": false
37 }
38}
3. Withdrawers in Brazil

If withdrawers reside in Brazil, they can link their PIX account to receive BRL.

Add a PIX account:
Request
1curl --request POST \
2 --url https://api-sandbox.coinflow.cash/api/withdraw/pix \
3 --header 'accept: application/json' \
4 --header 'content-type: application/json' \
5 --data '{"pixKey":"1234"}'
Response
{
"withdrawer": {
"_id": "672400ead654e5cdd247b33f",
"__v": 0,
"currency": "USD",
"email": "usher@atl.com",
"isBlocked": false,
"merchant": "6723f186b2f506b29dbee63d",
"originalCurrency": "USD",
"user": true,
"verification": {
"hash": "02154e69e0f38f2b31dec3b658535fa1cc283063",
"vendor": "persona",
"reference": "ver_DisMcS9M3HftnJYPpFSowNEWHyjT",
"status": "approved"
},
"wallets": [
{
"wallet": "usher",
"blockchain": "user"
}
],
"watchlistExempt": false,
"bankAccounts": [],
"cards": [],
"ibans": [],
"pixes": [ {
"key" : "1234",
"accountHash" : "ef501efc395b66692b1fe5aa6ad1d3f4a0af48d7",
"token" : "7ab01310-66b1-4b13-8d80-868bd31a6f8e"
}],
"rtpDisabled": false,
"cardDisabled": false
}
}
4

Step 4: Get a Quote for the Withdraw

Merchants may show an estimated quote of how much the user will receive after fees. See list of USDC token addresses to pass as token by chain.

Endpoint: GET /api/withdraw/quote

Request
1curl --location 'https://api-sandbox.coinflow.cash/api/withdraw/quote?token=4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU&amount=3&merchantId=YOUR_MERCHANT_ID&usePermit=true' \
2--header 'Authorization: <YOUR_API_KEY>' \
3--header 'accept: application/json' \
4--header 'x-coinflow-auth-blockchain: solana' \
5--header 'x-coinflow-auth-user-id: usher'
Response
1//Response
2{
3 "quote": {
4 "cents": 300,
5 "currency": "USD"
6 },
7 "gasFees": {
8 "gasFees": {
9 "cents": 0
10 },
11 "gasFeesWei": "0"
12 },
13 "same_day": {
14 "fee": {
15 "cents": 50,
16 "currency": "USD"
17 },
18 "finalSettlement": {
19 "cents": 250,
20 "currency": "USD"
21 },
22 "limit": {
23 "cents": 10000000,
24 "currency": "USD"
25 }
26 },
27 "standard": {
28 "fee": {
29 "cents": 100,
30 "currency": "USD"
31 },
32 "finalSettlement": {
33 "cents": 200,
34 "currency": "USD"
35 },
36 "limit": {
37 "cents": 10000000,
38 "currency": "USD"
39 }
40 },
41 "card": {
42 "fee": {
43 "cents": 200,
44 "currency": "USD"
45 },
46 "finalSettlement": {
47 "cents": 100,
48 "currency": "USD"
49 },
50 "limit": {
51 "cents": 5000000,
52 "currency": "USD"
53 }
54 }
55}
5

Step 5: Initiate the Payout

This endpoint enables a user to submit a payout from your own wallet on the chain you specify. Upon sending the request, funds from your own merchant wallet balance will decrement, and the end-user will receive their funds in their selected payout destination.

Getting the Tokenized Account

To get the tokenized bank account / IBAN / PIX / debit card, call get withdrawer and reference the token param. For example, for bank account: bankAccounts[0]['token']

Speed Options:

Pass any of the following as the speed depending on the payout method the withdrawer selects:

  • card - Instant debit card payouts
  • asap - Instant, RTP payout
  • same_day - Same day ACH payout
  • standard - Standard ACH payout
  • iban - SEPA payout
  • pix - PIX payout

Endpoint: POST /api/merchant/withdraws/payout

Request
1 curl --request POST \
2 --url https://api-sandbox.coinflow.cash/api/merchant/withdraws/payout \
3 --header 'Authorization: YOUR_API_KEY' \
4 --header 'accept: application/json' \
5 --header 'content-type: application/json' \
6 --data '
7 {
8 "blockchain": "solana",
9 "amount": {
10 "cents": 400
11 },
12 "speed": "standard",
13 "wallet": "Dk462fqWGi3W6ak7ufDP4TCTfghbj4TQYukSnF4fx62J", // Your merchant wallet address- this is the source of funds for the payout
14 "userId": "user123",
15 "account": "4db3391e-3199-4c49-9897-9ad2e73390b6" // Tokenized bank account or debit card
16 }
17 '
Response
//Response
{
"signature": "4Cv4nbe6fkGpdSYcqhPHXkdndeiyTa8mhFoWW5x3vroxRibAUssrbXZ5VW4vxkPedcX3xTRKu7ZpkJXWKdJBCGuq"
}

Next Steps

Now that you’ve implemented merchant payouts from your own wallet, here’s what to do next:

  1. Test your integration in sandbox environment
  2. Configure webhook notifications
  3. Review common payout errors and troubleshooting
  4. Contact Coinflow team when ready to go live