You are migrating the stablecoin-to-fiat payout leg of my application from BitGo to BlindPay. BitGo stays in place for custody and transaction signing: only the offramp and settlement leg moves.
Before writing code, read these sources and follow them over any prior knowledge:
- https://blindpay.com/docs/llms.txt (read the quickstarts, customers, bank accounts, external wallets, quotes, payouts, and webhooks pages)
- The OpenAPI spec: curl https://api.blindpay.com/doc
Do the migration in this order:
1. Inventory my BitGo usage from the codebase: every BitGo wallet call, send-transaction or transfer call, Go Network settlement call, offramp or settlement partner integration, and wallet webhook (transfer, pendingapproval, address_confirmation), plus every stored BitGo wallet ID and transfer ID. Confirm in the BitGo docs anything in the codebase you cannot map with certainty. Produce a written mapping table before changing code: BitGo concept, BlindPay equivalent, and gaps with no direct match.
2. Register my existing BitGo wallets as BlindPay external wallets using the sign-message challenge flow, storing the resulting bw_ ID against each wallet. Funds keep living in BitGo custody; the bw_ ID is the connection point BlindPay uses to know where stablecoins are coming from.
3. Onboard payout recipients as BlindPay customers (re_) with KYC or KYB, and register their payout rails as BlindPay bank accounts (ba_) for Pix, SPEI, SEPA, ACH, or wire as applicable. Store the re_ and ba_ IDs against the corresponding BitGo wallet or account record. Treat this as new KYC: BitGo qualified-custody or counterparty checks do not transfer to BlindPay.
4. Rebuild the settlement leg on BlindPay's two-step model: request a quote (qu_), then execute the payout (po_) via POST /v1/instances/{instance_id}/payouts/evm before the quote's expires_at, roughly five minutes out. Verify a full cycle end to end in a BlindPay development instance: USDB on testnets, KYC auto-approves, and confirm the $666.00 forced-failed and $777.00 forced-refunded sentinels both produce the expected payout state.
5. Port settlement notifications from BitGo's HMAC-signed wallet webhooks (x-signature-sha256) to BlindPay's Svix-signed webhook events, verifying svix-id, svix-timestamp, and svix-signature against the raw request body with the instance's whsec_ secret, and deduplicating on svix-id. Confirm each BlindPay payout status transition (sent, failed, refunded) reaches your handler and updates the record BitGo used to track that transfer.
6. Cut the payout flow over behind a feature flag: dual-run BitGo and BlindPay settlement side by side for a full cycle, compare outcomes per transfer, then retire the BitGo settlement path only once every in-flight BitGo transfer has settled and every payout in the dual-run window matches. BitGo continues to hold and sign the underlying assets after cutover; only the fiat leg has moved.
Constraints:
- BitGo remains the custodian and signer for any wallet not explicitly re-platformed; do not move custody.
- API keys stay server-side, never in client code or logs.
- All amounts are integer minor units; never use floating point for money math.
- Develop and test the full flow against a BlindPay development instance before touching production.
Deliverables: the migration report (mapping table, gaps, re-KYC plan), the external wallet registration script (bw_ IDs), the BlindPay client and quote-then-payout code path behind a flag, Svix webhook handlers with signature verification, and a cutover checklist covering the dual-run comparison and BitGo retirement criteria.