Stablecoin payroll run runbook: timing, checklist and failure handling (2026)
A runbook for a stablecoin payroll run: pre-run checklist, a 200-recipient example, quote timing, cover_fees true, and what to do when a payout fails.
A stablecoin payroll run has five stages: freeze the payroll file, fund the wallet, create one payout quote per recipient with cover_fees set to true, execute each quote right after you create it, and track every payout to a terminal status. Slow rails like ACH and SEPA start days before payday. Instant rails like Pix and SPEI fire on payday.
This runbook is the operating procedure, as of October 2026. For what stablecoin payroll is and why LATAM contractors prefer it, read stablecoin payroll for LATAM contractors. For the underlying concepts, start with what a stablecoin payouts API is.
Key takeaways
- A payout quote locks the rate and fees for 5 minutes by default, so create the quote right before you execute it, never at the start of the run.
- Setting
cover_feestotrueadds fees on top, so each recipient receives the full quoted amount. It is the usual choice for payroll. - Per BlindPay docs, Pix, SPEI and Transfers payouts are instant, while ACH and SWIFT take about two business days. The run calendar must start slow rails first.
- A
failedpayout is not refunded automatically. Contact support@blindpay.com and do not assume it resolves by itself. - On a development instance, a
request_amountof 66600 forcesfailedand 77700 forcesrefunded, so you can rehearse failure handling before payday.
What does a payroll run look like end to end?
It looks like a pipeline, not a single call. Each recipient is one quote and one payout, and the run is a loop around those pairs with checks before it and reconciliation after it.
- Freeze the file. Lock recipients, amounts and bank accounts. Anything added later goes into the next run.
- Fund the wallet. Move enough stablecoins to the funding wallet to cover the whole run plus a buffer.
- Start slow rails. Create and execute payouts for rails that need business days.
- Run payday rails. On payday, quote and execute Pix, SPEI and other instant payouts.
- Track. Consume
payout.new,payout.updateandpayout.completewebhooks. - Close. Reconcile, requeue failures and message recipients.
The flow per recipient follows the three documented steps on the payouts page: add the bank account once, create a payout quote, execute the payout. The step-by-step guide to how stablecoin payouts work walks through them in detail.
What should the payroll-run checklist cover before you press go?
Check recipients, money and rails before the first quote. Most failed payroll payouts trace back to a bad account or an unfunded wallet, not to the API.
| Check | What to confirm | Why it matters |
|---|---|---|
| Recipient KYC | Each customer has passed verification | Every payment flows through a customer that completed KYC (KYC docs) |
| Bank account approved | Account exists and uses the right rail type | A payout needs an approved bank account |
| Relationship field | recipient_relationship is set, such as employee or independent_contractor | The bank accounts docs list these values; set first_party only for the customer's own account |
| Minimum amount | Each line clears the rail minimum | 10 USD sender amount on most rails, 100 USD requested amount on SWIFT, 50 USDC or 40 EUR on SEPA, 70 USDC or 50 GBP on Faster Payments |
| Wallet funded | Balance covers the run plus a buffer | Rates move between funding day and payday |
| Webhook endpoint | Registered, signature verified, handler idempotent | You close the run from events, not from the loop |
| Idempotency keys | One Idempotency-Key per execute call | A retry replays instead of paying twice (idempotency docs) |
| Failure rehearsal | Sentinel amounts tested on a development instance | 66600 forces failed, 77700 forces refunded |
If a recipient is new this cycle, allow time for verification. Per the BlindPay cut-off times reference, KYC Standard takes about 60 seconds when automated, while KYC Enhanced and KYB Standard take 3 hours to 1 business day with manual review. Do not add a first-time recipient on payday morning.
How should a 200-recipient run be structured?
Group recipients by rail, then schedule each group by how long the rail needs. The example below is illustrative, with no fees and no real rates.
| Group (illustrative) | Recipients | Rail | Start | Expected arrival, per docs |
|---|---|---|---|---|
| Brazil contractors | 90 | Pix | Payday | Instant |
| Mexico contractors | 50 | SPEI | Payday | Instant |
| Argentina contractors | 10 | Transfers | Payday | Instant |
| Euro area staff | 25 | SEPA | 2 business days before payday | About 1 business day |
| US staff and vendors | 20 | ACH | 3 business days before payday | About 2 business days |
| UK contractors | 5 | Faster Payments | Payday | 5 to 30 minutes |
That is 200 recipients and 200 quotes. Nothing in the docs describes a bulk endpoint, so a payroll run is a loop of quote-then-execute pairs, with your own queue controlling concurrency. Run slow-rail groups first, then payday groups in a queue sized to your API client. The development instance caps requests at 40 per minute per instance, so test your queue speed there with that limit in mind. The sandbox docs state that production instances have no per-instance request cap.
The Federal Reserve closes on holidays, and ACH does not move on them. Check the Federal Reserve holiday schedule when you count business days for ACH and wire. For the cadence side of recurring runs, see scheduling recurring payouts with live quotes.
Why set cover_fees to true for payroll?
Because a salary is a promise of a number. With cover_fees set to true, fees are added on top of the stablecoin amount you send, so the recipient receives the full quoted amount. With false, fees come out of the fiat the recipient receives, which is the common case for other products.
On payroll, a recipient who is owed R$ 8,000 should see R$ 8,000. Set currency_type to receiver so the local amount is fixed, and cover_fees to true so the fee does not shrink it. The cost moves to your side and shows up in the quote's sender_amount.
On pricing, BlindPay states it this way: "BlindPay combines a monthly plan (platform access) with per-transaction fees that vary by rail and network and are disclosed only in the live quote before execute. BlindPay does not publish a static flat rate card; always cite the quote's fee breakdown rather than a fixed bps number." There is no setup fee or monthly minimum, and development instances are always free, per the billing docs. Finance should approve the run against quote totals, not a rate card. If you earn a markup as a platform, the partner fee shows up as partner_fee_amount on each quote. See also partner fees as markup on live quotes.
When do you create the quote?
Immediately before you execute it. The quote locks the rate and fees for 5 minutes by default, and expires_at is returned in epoch milliseconds. SEPA and Faster Payments quotes can be shorter, so always read expires_at.
A quote backs exactly one payout. If it expires, request a new one, do not retry the old quote_id. Do not request 200 quotes at the start and execute them as the queue drains: the last ones would expire. Create, execute, move on. Why one quote cannot cover a batch explains the pattern, and how much USDC to hold for payouts covers sizing the wallet.
How do you handle failures during the run?
Map each failure to one action and one owner. The table lists the cases a payroll operator meets.
| Failure | Typical cause | Action |
|---|---|---|
| Quote expired before execute | Queue delay, slow client | Create a new quote and execute it |
Amount below minimum, LIMITS_AMOUNT_OUT_OF_RANGE | Line under 10 USD on most rails | Fix the amount or combine with another line |
| SWIFT line below 100 USD | SWIFT minimum on requested amount before fees | Move the line to a local rail or raise the amount |
Payout failed | Review timeout or rejected compliance check | Contact support@blindpay.com, fix the cause, quote again |
Payout refunded | Delivery not possible | Stablecoins returned to the refund wallet or the sender; correct the account and requeue |
Payout on_hold | Compliance review, always for SWIFT | Wait; holds can take up to 30 days and a timeout fails the payout |
| Webhook missed | Endpoint down | Replay from the webhook portal or fetch the payout by id |
Two rules keep payroll safe. First, a failed payout is not refunded automatically, so open a support ticket instead of waiting. Second, never pay twice: before you requeue a line, confirm the original payout's terminal status. How to explain a delay to recipients has message templates for held and failed payments, and payout statuses explained defines each state.
How do you reconcile and close the run?
A run is closed when every payout id has a terminal status. Do the sum at the end.
- Count payouts by status:
completed,failed,refunded. - Match each completed payout to its payroll line by
id. - Compare the sum of quoted
receiver_amountvalues to the payroll file. - Compare total stablecoin sent to the sum of
sender_amountvalues. - Requeue failed lines with a new quote and a new idempotency key.
- Archive quotes, payout ids and webhook events with the payroll record.
Webhook reconciliation for stablecoin APIs shows the ledger pattern, including duplicate events.
What does this post not cover?
It does not cover employment classification, taxes or labor law. Whether someone is an employee or contractor, what withholding applies, and which local rules govern pay in each country depend on facts about the worker and the jurisdiction, and a payout API does not decide them. Get advice for each country before your first run. For tax reporting on the US side of contractor payments, see the IRS digital assets page.
On compliance, the provider side covers KYC, sanctions screening and the travel rule in the same flow. See the travel rule for stablecoin off-ramps for what that includes.
Methodology and sources
External sources: the Federal Reserve holiday schedule, the Central Bank of Brazil page on Pix, and the IRS digital assets page. BlindPay docs used: payouts, payout quotes, bank accounts, cut-off times, billing, partner fees, webhooks and idempotency. The 200-recipient table is illustrative and contains no fees. Rail estimates are BlindPay's documented estimates as of October 2026 and can change with volume.
What to do next
Rehearse the run on a free development instance with the failure sentinels, then request a live quote for your first corridor and compare it with what your finance team expects. The payout quotes docs have the full request fields.
FAQ
More payments articles
See all payments articlesStablecoin payin API pricing: fees to expect and how to compare them
Stablecoin API pricing for payins: the fee types to expect, a worked USD 10,000 example, a quote checklist, and what BlindPay charges.
Mass payouts API architecture: how to pay thousands of recipients across borders (2026)
A reference architecture for mass payouts: queue, quote, execute, webhooks and reconciliation, with a failure table, monitoring checklist and partner fees.
What happens when a stablecoin payin fails, arrives late, or does not match?
Failed stablecoin deposit refund: why payins fail, late or mismatched deposits, and the support runbook, using BlindPay's real payin statuses.