How to integrate a stablecoin payouts API: a developer checklist (2026)
Integrate a stablecoin payouts API: dev instance, KYC, bank account, quote, payout request, webhooks, rail minimums, go-live checklist and a 12-test plan.
To integrate a stablecoin payouts API, follow eight steps: create a free development instance, authenticate with a bearer API key, onboard the recipient with KYC data, add a bank account, create a quote, execute the payout, listen to webhooks for every state change, and move to production. This page is the checklist, with the requests and tests.
It covers BlindPay's API as of October 2026. For the concept, start with what a stablecoin payouts API is and how a stablecoin payout works step by step. Older pages go deeper on single topics, and this one links them rather than repeating them. BlindPay publishes this post.
Key takeaways
- The flow is fixed: add a bank account once, create a quote that locks rate and fees for 5 minutes by default, then execute the payout.
- The payout request carries a
quote_idand asender_wallet_address, and one quote can back only one payout. - Minimums by rail: SWIFT 100 USD, SEPA 50 USDC or 40 EUR, Faster Payments 70 USDC or 50 GBP, every other rail 10 USD sender amount.
- On development instances, a
request_amountof 66600 forcesfailedand 77700 forcesrefunded. - Build against webhooks, not polling, and verify the signature on every call.
What does the integration look like end to end?
One customer, one bank account, one quote and one payout per recipient payment. Everything else is state handling.
| Step | Call or action | You get |
|---|---|---|
| 1 | Create a development instance and API key | An isolated, free environment |
| 2 | Accept terms of service, create a customer with KYC data | kyc_status of verifying, then approved |
| 3 | Create a bank account for the customer | A ba_... ID and status |
| 4 | Create a payout quote | A qu_... ID, amounts, fees and expires_at |
| 5 | Execute the payout with quote_id | A po_... ID with status processing |
| 6 | Receive webhooks | payout.new, payout.update, payout.complete |
| 7 | Reconcile | Your ledger matches the payout and fee fields |
How to integrate a stablecoin API covers the wider build, including SDK choice. BlindPay ships SDKs for Node.js, Python, Go, PHP and Swift, plus an OpenAPI spec, all wrapping the same REST API described in the API reference.
How do you set up the environment and authenticate?
Create a development instance, generate an API key and send it as a bearer token. Keep it on your server.
Development and production expose the same endpoints, fields and response shapes, at the same hostname, https://api.blindpay.com. The instance your key belongs to decides the environment. Development instances are free, auto-approve customers and use the USDB test token on test networks. Sandbox vs production lists every difference. Production uses mainnet networks with USDC or USDT; check the supported chains page before you name a network.
Send mutating requests with an Idempotency-Key header so a network retry cannot create two payouts. The docs say a key is kept for 24 hours, and a retry only replays if the body matches byte for byte. Idempotency keys for stablecoin APIs has the pattern.
What KYC data do you send for the recipient?
The customer fields depend on type: individual or business. Create the customer, then wait for approved before you add a bank account or quote.
On production, KYC Standard is automated in about 60 seconds. KYC Enhanced (high-risk countries) and KYB Standard take 3 hours to 1 business day. Development instances auto-approve, so a name of Fail forces a rejection for testing. The KYC requirements list every field. The compliance side, including who owns what, is in stablecoin payout compliance.
How do you add a bank account and create a quote?
Add the bank account once per recipient, then create a quote for each payment.
Bank account fields depend on the rail, so fetch them at runtime from the public rails endpoint instead of hardcoding them. Third-party accounts are allowed, with recipient_relationship set to something other than first_party. Then create the quote against that bank account:
request_amount is an integer in minor units, so 10000 is 100.00. currency_type says which side the amount is denominated in: sender is the stablecoin, receiver is the fiat. cover_fees: false takes fees out of the fiat received, and true adds them on top, which payroll teams usually want. The response returns sender_amount, receiver_amount, flat_fee, partner_fee_amount, commercial_quotation, blindpay_quotation and expires_at in epoch milliseconds. See payout quotes and pricing.
What does the payout request look like?
One POST with the quote_id and the funding wallet address. Check the field list in the payouts docs before you ship.
Payout creation is split by network: /payouts/evm for EVM and managed wallets, /payouts/stellar and /payouts/solana for those chains, each with its own request shape. The response returns a po_... ID with status processing, and sub-status objects tracking_transaction, tracking_payment, tracking_liquidity and tracking_complete. If you fund from an external wallet, authorize the exact amount on-chain first. A managed wallet needs no signing, but it is custodial: see custodial vs non-custodial payout APIs.
A quote_id can only back one payout, so a second call with the same quote returns an error. Create a new quote instead.
Which flavor of the docs should you read?
BlindPay's docs come in two flavors. Abstracted treats the stablecoin leg as plumbing and walks you through add account, quote, execute. Advanced exposes funding paths and on-chain authorization. Read Abstracted if you think in bank rails, and Advanced if you hold wallets. Abstracted vs advanced blockchain payment APIs explains the choice.
What are the minimums by rail?
Check them at quote time. The quote rejects amounts below the minimum, and you should surface that error rather than hardcode the number.
Rail (type) | Minimum | Error when below |
|---|---|---|
SWIFT (international_swift) | 100 USD requested amount, before fees | swift_minimum_is_100_usd |
SEPA (sepa) | 50 USDC by sender amount, or 40 EUR by receiver amount | sepa_minimum_is_50_usdc, sepa_minimum_is_40_eur |
Faster Payments (faster_payments) | 70 USDC by sender amount, or 50 GBP by receiver amount | faster_payments_minimum_is_70_usdc, faster_payments_minimum_is_50_gbp |
| Every other rail (ACH, wire, RTP, Pix, PIX Safe, TED, SPEI, ACH COP, Transfers) | 10 USD sender amount | LIMITS_AMOUNT_OUT_OF_RANGE |
Payout times from the bank accounts docs: Pix, PIX Safe, SPEI, Transfers (Argentina) and RTP are instant, wire and TED and ACH COP and SEPA about 1 business day, ACH and SWIFT about 2 business days, and Faster Payments 5 to 30 minutes. The cut-off times reference says SWIFT settlement can take up to 5 business days. All SWIFT payouts start on_hold until compliance documents are submitted and approved. For international wires, BlindPay runs SWIFT payments and collections on behalf of (POBO/COBO), with UETR tracking and MT103 confirmations.
How should you handle webhooks and statuses?
Register an https endpoint on the instance, verify the signature on every call and treat payout.complete as the terminal signal.
| Event | Fires when |
|---|---|
payout.new | A payout is created |
payout.update | A payout changes status, for example processing to on_hold |
payout.complete | A payout reaches completed, failed or refunded |
payout.partnerFee | A payout completes and a partner fee is owed |
Verify svix-id, svix-timestamp and svix-signature against the raw body with HMAC-SHA256 and reject timestamps outside a 5 minute tolerance. The verification docs have the code. For local testing, webhook.cool gives a temporary URL that logs each request. Webhooks and reconciliation and payout statuses explained cover the handler design.
What is the go-live checklist?
Walk this list on the day you switch to production.
- Quote expiry. Read
expires_atand requote after 5 minutes (shorter on SEPA and Faster Payments). See handling expired quotes. - Minimums. Surface the rail's minimum error to the user instead of failing silently.
- Webhook verification. Verify signatures, check the timestamp, deduplicate on
svix-id, and allowlist the documented source IPs only as an extra layer. - Retries. Send an
Idempotency-Keyon every mutating call and retry only on network errors and 5xx. - Refund scenarios. Know your refund wallet, and know that a
failedpayout is not refunded automatically: contact support@blindpay.com. - Holds. Holds can take up to 30 days, and a timeout fails the payout. Tell recipients what
on_holdmeans. - Reconciliation. Store the quote ID, payout ID and fee fields against each ledger entry.
- Production credentials. New production API key, mainnet networks,
USDCorUSDT, and a small first payout.
What is the 12-item pre-launch test plan?
Run all twelve on a development instance and record the result. Expected outcomes come from the docs.
| # | Test | Expected outcome |
|---|---|---|
| 1 | Create a customer with valid test data | kyc_status ends at approved |
| 2 | Create a customer named Fail | Rejected, and your onboarding shows the rejection path |
| 3 | Add a bank account for your target rail | Account reaches approved |
| 4 | Create a payout quote at a normal amount | Quote returns amounts, fees and expires_at in milliseconds |
| 5 | Execute the payout with that quote | Status processing, then completed automatically |
| 6 | Execute twice with the same quote_id | Second call returns an error, no second payout |
| 7 | Let a quote expire, then execute | Execution fails, and your code requotes |
| 8 | Quote below the rail minimum | LIMITS_AMOUNT_OUT_OF_RANGE or the rail-specific error |
| 9 | Quote with request_amount 66600 and execute | Payout ends failed, handler marks it failed |
| 10 | Quote with request_amount 77700 and execute | Payout ends refunded, handler records the refund |
| 11 | Replay a webhook and send a bad signature | Duplicate is ignored, bad signature is rejected |
| 12 | Send the same mutating call twice with one Idempotency-Key | Second response replays with Idempotency-Replayed: true |
What shortcuts exist for AI agents and the terminal?
The hosted MCP server and the CLI let you try the flow without writing code first. BlindPay describes itself as the most AI-native stablecoin infrastructure.
The hosted MCP server at https://mcp.blindpay.com/mcp signs in over OAuth and lets an agent quote and track payouts, with a read-only variant at https://mcp.blindpay.com/mcp/readonly. Tools carry read-only and destructive annotations, but the server does not block a call by itself, so keep a human confirmation step. The CLI (@blindpay/cli) supports --json, blindpay schema and predictable exit codes (CLI post). Read the MCP docs and the Model Context Protocol site.
Methodology and sources
External sources: the BlindPay API reference, the OpenAPI spec, the Model Context Protocol site and webhook.cool. BlindPay facts come from the payouts, payout quotes, bank accounts, KYC, cut-off times, webhooks, idempotency, sandbox vs production, SDKs and MCP docs, checked in October 2026.
What to do next
Start in the development instance: create a customer, add a bank account, quote and execute a payout, then run the 12 tests above. The payout quickstart walks the whole flow with copyable requests.
FAQ
More payments articles
See all payments articlesNeobank API quickstart: from sign-up screen to first deposit and first payout
Map every neobank screen to a BlindPay API call: terms, KYC, wallet, US account details, first deposit, bank account, quote, payout, and webhooks.
How long does it take to launch cross-border stablecoin payouts? From first API call to first live payout
The go-live critical path for stablecoin payouts: instance setup, KYB, integration, first customer KYC, and first-payout holds, with each wait.
Designing a checkout sessions API for local bank payments
How to design a checkout sessions API over local bank rails in 2026: session states, quote vs session lifetime, idempotency, and webhooks.