Funding a payout from your own wallet needs one on-chain authorization. What EVM approve, Solana delegation, and Stellar signing look like, step by step.
To execute a payout quote from your own wallet, authorize the exact quoted amount on-chain, then create the payout before the quote expires. On EVM chains you call approve on the token contract, on Solana you sign a token delegation, and on Stellar you sign a payment transaction. A BlindPay managed wallet skips the authorization.
Same quote, three chain-native ways to say yes. This guide puts them side by side, with the endpoints, the fields, and the timing traps inside a 5-minute quote window.
Key takeaways
approve with the contract payload from the quote, then POST /payouts/evm.POST /prepare-delegate-solana, sign and submit, then POST /payouts/evm.POST /payouts/stellar/authorize, sign and submit, then POST /payouts/stellar with the signed transaction.Because BlindPay never holds keys to your wallet. For payout flows from customer-controlled wallets, BlindPay operates as a non-custodial payment processor: you authorize the exact amount and BlindPay executes that single transaction. If a payout can't be delivered after the stablecoins are collected, BlindPay refunds them to the quote's refund wallet, or to the sending wallet when none is set. On Pix and other non-USD local rails that refund is automatic, while USD payouts and payouts whose review times out are refunded after an operator review.
The authorization is how you grant "this amount, this once." Each chain has its own primitive for it. What happens on-chain in a stablecoin payment shows where that step sits in the full flow.
If the funds sit in a BlindPay managed wallet instead, there's nothing to sign. You create the quote and call POST /payouts/evm with the managed wallet's address, for every supported chain, Solana included (payout with managed wallet). Managed wallets are in beta and custodial.
| Step | EVM (Ethereum, Base, Polygon, Arbitrum) | Solana | Stellar |
|---|---|---|---|
| Primitive | ERC-20 allowance (approve) | Token delegation | Signed payment transaction (XDR) |
| What BlindPay returns | contract object inside the quote | Serialized transaction from prepare-delegate-solana | Unsigned transaction from payouts/stellar/authorize |
| Who submits on-chain | You | You | You |
| Payout endpoint | POST /payouts/evm | POST /payouts/evm | POST /payouts/stellar |
| Extra field on the payout call | None | None | signed_transaction |
| Reusable? | No, single-use | No, one delegation per quote | No, single-use |
The quote request is the same everywhere: bank_account_id, currency_type, cover_fees, request_amount in minor units, plus the network and token you send from (payout quotes). The chain only changes what happens between the quote and the payout. If you're still choosing the chain, which network to off-ramp from compares finality and fees.
Approve, wait, pay. The quote response for an EVM network carries a contract object with everything the approval needs (payout with EVM):
contract field | What it is |
|---|---|
address | The ERC-20 token contract for the chosen token and network |
abi | The ERC-20 ABI, ready for your Ethereum library |
functionName | Always approve |
blindpayContractAddress | The spender to approve: BlindPay's receiving address on that network |
amount | The decimal-adjusted amount to approve, as a string |
network | { name, chainId } for the quoted network |
With ethers.js, the call looks like this:
The ERC-20 standard defines approve as allowing a spender to withdraw from your account up to the approved value (EIP-20). Once the approval confirms, create the payout with quote_id and sender_wallet_address. You pay gas on the approval, which who pays gas fees covers in detail.
Delegate, sign, pay. Solana payouts need a token delegation before the payout executes (payout with Solana):
POST /v1/instances/{instance_id}/prepare-delegate-solana with owner_address, token_address, and amount. It returns { "success": true, "transaction": "..." }, a base64 serialized transaction.VersionedTransaction, sign it with the sender's wallet (a browser wallet or a server-side keypair), send it, and wait for confirmation.POST /v1/instances/{instance_id}/payouts/evm with quote_id and the Solana sender_wallet_address. Yes, the EVM path. The name is historical.Solana's token program says account owners can delegate authority over some or all of their balance with the Approve instruction, and delegates may transfer or burn up to the amount delegated (Solana Program Library). Each BlindPay delegation covers only the amount tied to that quote, so repeat all three steps for every payout.
Authorize, sign, pay with the signature. Stellar has no allowance mechanism, so you sign a real payment to BlindPay's treasury address (payout with Stellar):
POST /v1/instances/{instance_id}/payouts/stellar/authorize with quote_id and sender_wallet_address. It returns an unsigned transaction in transaction_hash. This call does not consume the quote or create any record.TransactionBuilder.fromXDR, sign with the sender's key, and submit it to the network.POST /v1/instances/{instance_id}/payouts/stellar with quote_id, signed_transaction, and sender_wallet_address. BlindPay re-validates the signed transaction against the quote, destination and amount, before dispatching the payout.Stellar encodes transactions in XDR, a compact binary format that SDKs convert to and from base64 (Stellar docs). BlindPay's Stellar mainnet treasury address is GCOSSQDM2SWMHRP7CDBOLL2V45NHCRLUWUCEHPPBA2ABCOOLPOLZKIHE, useful when you reconcile on an explorer.
A treasury script pays 1,250.00 USDC from an external wallet. request_amount is 125000 in minor units. The approval amount is decimal-adjusted on-chain: BlindPay's own Solana example delegates "50000000" for a 50-dollar quote, which is 50 x 1,000,000, so a token with six decimals needs 1,250 x 1,000,000 = 1,250,000,000 base units here. Read contract.amount from the quote instead of computing it.
Now the clock. The step timings below are illustrative.
| Step | Illustrative time | Clock used |
|---|---|---|
| Create quote | 1 s | 1 s |
| Build and sign the authorization | 3 s | 4 s |
| Wait for on-chain confirmation | 30 s | 34 s |
| Create the payout | 1 s | 35 s |
| Quote window | 300 s | 265 s to spare |
Plenty of room when it's a script. The real risk is a human: a wallet pop-up left open while someone gets coffee. If 300 seconds pass before the payout call, the quote is dead and the old authorization was sized for it. Re-quote and authorize again. Handling expired quotes in TypeScript and Python has the retry loop, and stablecoin API idempotency keys covers safe retries on the payout call. For reading the quote's two rates, see how to read an FX quote.
Pick the chain your treasury already uses, open the matching tutorial in the BlindPay docs, and run one 50-dollar payout end to end on a development instance with USDB. Start with payout with EVM if you're unsure.
Seven places blockchain payments beat bank rails: contractor payroll, remittances, B2B suppliers, marketplaces, 24/7 treasury, bill pay, and PSP payouts.
Push means the payer sends an ACH transfer. Pull means you debit a connected account. How each funds a USD to USDC on-ramp, the fees, and the return risk.
AP2, ACP, and x402 each verify that an AI agent had permission to spend. Here is what every protocol covers, who backs it, and the reconciliation gap none of them close.