A fiat payout (also called an off-ramp) lets a wallet user convert crypto into traditional money and send it to a bank account, debit card, or bill payment. To add fiat payouts to a crypto wallet app, you need three building blocks: a regulated money transmitter, a payment request API, and a KYC layer. The Spritz SDK provides all three through a single TypeScript client, with a typical integration time of one to two weeks. fomo, a Benchmark-backed trading app, used the Spritz SDK to enable $2M+ in fiat withdrawals for 4,000+ users in under two weeks of engineering work.
Download the off-ramp one-pager (PDF) for the full coverage matrix, pricing model, and integration timeline in one page.
What a fiat payout actually means inside a wallet app
A fiat payout is the moment a user stops holding crypto and starts holding money in their bank. The crypto is sold for a stablecoin or USD value, the value is settled with a regulated payments partner, and the funds arrive in the user's destination account on a real-world rail such as ACH or debit-push. Wallet apps typically expose this as a withdraw or cash-out action; the SDK underneath handles quoting, signing, settlement, and reporting.
Three integration models exist. Each trades user-experience control for speed.
| Model | Who owns the UX | Who owns compliance | Time to ship | Best for |
|---|---|---|---|---|
| Hosted widget | The provider | The provider | 1 day | Apps testing demand |
| White-label SDK | You | The provider | 1 to 2 weeks | Wallets and trading apps owning the brand |
| Direct API | You | You and the provider | 4 to 8 weeks | Fintechs with internal compliance teams |
Most modern wallets choose the white-label SDK because it preserves brand control without forcing the wallet team to take on money transmission risk directly. fomo took this path with the Spritz SDK and went live in under two weeks.
Why fiat payouts matter for a wallet in 2026
Stablecoin supply crossed $320 billion in April 2026, per DefiLlama. USDT and USDC together represent about 89% of circulating value. Users who hold those balances increasingly expect to spend them, not just trade them. Wallets without an off-ramp lose retention to wallets that offer one, and lose revenue to centralized exchanges that charge withdrawal fees for the same flow.
The fomo case shows the dynamic clearly. Before integrating the Spritz SDK, fomo had no native off-ramp; users could only withdraw to another wallet address. In Paul Erlanger's words:
“We did not have any good mechanism for users to withdraw via bank account. This led to a lot of user frustration, especially new users who deposit on the platform for the first time.”
— Paul Erlanger, Co-founder, fomo
After integration, support ticket volume around withdrawals dropped sharply, and 4,000+ users transacted $2M+ in bank withdrawals within the first launch window.
The broader market signal is even louder. Mastercard agreed in March 2026 to acquire BVNK for up to $1.8 billion, the largest stablecoin-infrastructure acquisition to date. Stripe paid $1.1 billion for Bridge in February 2025. The world's two largest payment networks are betting that stablecoin off-ramp infrastructure is not a niche; it is core payments plumbing for the next decade.
The off-ramp architecture: how it actually flows
A working off-ramp has four moving parts. The user holds the asset in their wallet. The Spritz SDK orchestrates KYC, account setup, and payment request creation. The user signs an on-chain call to the SpritzPay smart contract from their own wallet. Spritz, as the regulated counterparty, matches the on-chain transfer to the user's destination (bank, card, or bill) and routes the fiat to that destination over ACH or local rail.
The wallet team's job is to wire the user-facing surface (the Withdraw button, the destination picker, the confirmation screen) on top of these layers. Everything below the UI is provided by the SDK under existing licenses.
| Component | What it does | Build it yourself? |
|---|---|---|
| KYC and identity verification | Confirms the user, screens against sanctions | No, the SDK provides it via Persona |
| Payment request engine | Creates a binding payment request tied to a destination account | No, use the SDK |
| SpritzPay smart contract | On-chain settlement counterparty; the user signs a call to it | No, deployed and maintained by Spritz |
| Settlement and money movement | Routes USD to the user's bank, card, or bill | No, requires MSB or EMI licenses |
| Frontend SDK | Renders the withdraw flow inside your app | Yes, you build the UI on top of the SDK |
Step-by-step integration with the Spritz SDK
The code below is from the @spritz-finance/api-client TypeScript client. Install with npm install @spritz-finance/api-client. The full reference is in the README.
Step 1: Initialize the client
The Spritz SDK uses two-tier authentication. An Integration Key identifies your application; a per-user API Key is returned when you create each user. Initialize server-side; never embed the Integration Key in a mobile or web client.
import { SpritzApiClient, Environment } from '@spritz-finance/api-client'
const client = SpritzApiClient.initialize({
environment: Environment.Sandbox,
integrationKey: 'YOUR_INTEGRATION_KEY_HERE',
})Step 2: Create the user and run KYC
Create a user with their email. Spritz returns an API key scoped to that user; set it on the client. Then start KYC, which runs through Persona, either as a hosted URL or an embedded flow.
const user = await client.user.create({ email: 'user@example.com' })
client.setApiKey(user.apiKey)
const { verificationUrl, inquiryId, sessionToken } =
await client.user.getVerificationParams()
// Option 1: open verificationUrl in a webview or browser tab
// Option 2: embed Persona's flow using inquiryId and sessionTokenVerification status updates are delivered via the verification.status.updated webhook event.
Step 3: Add the destination account
The user's destination can be a US or Canadian bank account, a debit card (Visa or Mastercard), or a bill (credit card, mortgage, utility). Add it before creating a payment request.
import { BankAccountType, BankAccountSubType } from '@spritz-finance/api-client'
const bankAccount = await client.bankAccount.create(BankAccountType.USBankAccount, {
accountNumber: '123456789',
routingNumber: '987654321',
subType: BankAccountSubType.Checking,
ownedByUser: true,
})Step 4: Create the payment request
A payment request ties the destination account to an amount and the blockchain network the user will pay from.
import { PaymentNetwork } from '@spritz-finance/api-client'
const paymentRequest = await client.paymentRequest.create({
amount: 500,
accountId: bankAccount.id,
network: PaymentNetwork.Ethereum,
})Step 5: Get on-chain params and sign
The off-ramp settles via the SpritzPay smart contract. Get the transaction parameters from the SDK, then have the user sign the contract call from their own wallet.
const params = await client.paymentRequest.getWeb3PaymentParams({
paymentRequest,
paymentTokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC on Ethereum
})
// params.contractAddress, params.method, params.calldata, params.value, params.requiredTokenInput
const txHash = await wallet.send({
to: params.contractAddress,
data: params.calldata,
value: params.value,
})For Solana, use getSolanaPaymentParams instead. It returns a ready-to-sign VersionedTransaction.
Step 6: Listen for webhooks
Spritz emits webhooks at every payment state transition. Update your wallet UI from these events; do not poll. Webhooks are signed with HMAC SHA256 in the Signature header.
import { createHmac } from 'crypto'
app.post('/spritz/webhook', (req, res) => {
const payload = req.body
const expected = createHmac('sha256', WEBHOOK_SECRET)
.update(JSON.stringify(payload))
.digest('hex')
if (expected !== req.headers['signature']) {
return res.status(401).end()
}
if (payload.eventName === 'payment.completed') {
notifyUser(payload.userId, payload.id)
}
res.status(200).end()
})Key events: payment.created, payment.updated, payment.completed, payment.refunded, verification.status.updated, capabilities.updated.
A complete integration, including edge cases like failed bank verification or sanctioned addresses, typically takes one to two weeks of engineering time. fomo went from first line of code to production in under two weeks.
What fomo learned from going live
fomo is a trading app for non-experts. The team raised a $17M Series A from Benchmark in November 2025. The challenge for fomo was straightforward: trading volume was strong, but new users hit a wall the first time they tried to take money off the platform, because withdraw-to-bank did not exist.
| Decision | What fomo did | Why it worked |
|---|---|---|
| Build vs buy | Bought via Spritz SDK | Fiat rails were not core to fomo's product roadmap |
| Hosted vs white-label | White-label | Brand consistency, native feel |
| Region 1 | United States ACH | Largest user concentration |
| Time to first payout | Under two weeks | Engineering capacity preserved for trading features |
“The Spritz team were professional, knowledgeable, and willing to work with us to create a custom native solution.”
— Paul Erlanger, Co-founder, fomo
| Metric | Result |
|---|---|
| Time from integration start to launch | Under 2 weeks |
| Users on the new withdrawal flow | 4,000+ |
| Fiat withdrawn to bank | $2M+ |
| Support tickets about withdrawals | Sharply down (per fomo) |
“Before integrating Spritz, we only had the option of withdrawing to another wallet address. The impact for users who are not crypto-native is night and day.”
— Paul Erlanger, Co-founder, fomo
Full case: fomo x Spritz SDK case study.
Coverage: what your users can actually do
The matrix below reflects the documented Spritz SDK surface as of May 14, 2026.
| Direction | Account types | Networks |
|---|---|---|
| Off-ramp | US bank account, US debit card, US bills, CA bank account | 8 networks (see token table) |
| On-ramp | Virtual accounts (ACH and wire) plus ACH direct debit to Solana | Ethereum, Polygon, Base, Arbitrum, Avalanche, Optimism, Solana, Tron |
| Bill pay | US credit cards, mortgages, utilities, and more | Same as off-ramp |
| Virtual cards | US virtual debit card, crypto-funded | All supported networks |
Stablecoin coverage per network is documented in the SDK reference. The current matrix:
| Network | Tokens |
|---|---|
| Ethereum | USDC, USDT, DAI, USDP, PYUSD |
| Polygon | USDC |
| Base | USDC |
| Arbitrum | USDC |
| Avalanche | USDC |
| Optimism | USDC |
| Solana | USDC, PYUSD |
| Tron | USDT |
Check if Spritz covers your target geographies. Talk to sales and we will respond within one business day with confirmed rails, supported tokens, and a sandbox key.
Compliance: what your team is responsible for
The split is simple: Spritz holds the licenses, and the integrator keeps Spritz informed about its user base and intended volumes.
| Responsibility | Wallet app | Spritz |
|---|---|---|
| Money transmitter / MSB license | Not required | Held |
| KYC / KYB program | Not required | Run by Spritz |
| Sanctions screening (OFAC, EU, UK) | Not required | Run by Spritz |
| Travel Rule reporting | Pass user data via API | Files reports |
| Acceptable use policy | Your call | Spritz aligns |
This split is what makes the white-label SDK model viable for crypto-native teams without a banking org chart. For the full onboarding picture, see our KYB and compliance guide.
Build vs buy: a framework
If you are evaluating an off-ramp partner against a build path, the table below captures the realistic tradeoffs.
| Dimension | Build in-house | License an SDK |
|---|---|---|
| Time to first payout | 9 to 18 months | 1 to 2 weeks |
| Licensing cost (US only) | $750K to $2M | Included |
| Headcount required | 4 to 8 (legal, compliance, ops, eng) | 0 to 1 |
| Coverage at launch | 1 country | Global |
| Margin on each transaction | Higher long-term | Set your own markup |
| Speed of new rail launch | Quarters | Days |
| Engineering distraction from core product | High | Low |
| Regulatory exposure | High | Low |
The honest answer for most wallet teams: license the SDK, set your own markup on top, and revisit the build decision once monthly off-ramp volume crosses $50M. fomo's choice to license rather than build is the textbook case; the team kept engineering focused on trading, not on money transmitter licensing.
Common pitfalls
Three failure patterns recur in wallet integrations. None of them are technical; they are all process or expectations issues.
The first is skipping the test suite for sanctioned wallet addresses. Engineering teams build the happy path quickly and assume the SDK will gracefully reject any flagged transaction. It will, but the in-app UX for “your transaction was blocked for compliance reasons” needs to be designed up front.
The second is showing the user a fiat quote before checking the on-chain transaction has confirmed enough blocks. Tie the UI state strictly to webhook events. A 10-second lag on a confirmation screen is recoverable; a refunded completed payout is not.
The third is hardcoding rail support per country. Coverage expands. The wallet should fetch supported rails dynamically from the SDK at app launch and cache them for the session.
Myths about crypto off-ramps
| Myth | Reality |
|---|---|
| Off-ramps require my company to become a money transmitter | False. Spritz is the money transmitter. Your app remains a software provider. |
| Self-custody and off-ramps are incompatible | False. The user signs the SpritzPay contract call from their own wallet; Spritz only takes possession of the asset after that on-chain transfer settles. |
| Off-ramps are too slow for consumer UX | False. US ACH settles same-day to 1 business day. Token delivery to settlement is on-chain (seconds on Solana and Base, minutes on Ethereum L1). |
| Off-ramp pricing is opaque | Spritz exposes the full cost stack so integrators can set their own markup. Transaction fees only apply once monthly volume exceeds $100. |
| Adding fiat off-ramp invites regulatory scrutiny on the wallet | The opposite. The licensed counterparty model insulates the wallet from money-transmission obligations. |
Glossary
| Term | Definition |
|---|---|
| Off-ramp | Conversion of crypto into fiat with delivery to a real-world destination |
| Payment request | A binding Spritz object linking an amount, network, and destination account; the on-chain equivalent of a “quote” |
| SpritzPay | The Spritz smart contract that the user signs a call to in order to settle a payment |
| ACH | Automated Clearing House, the US bank-to-bank payment rail |
| Persona | The KYC provider the Spritz SDK uses for identity verification |
| MSB | Money Services Business, a US regulatory category for money transmitters |
| EMI | Electronic Money Institution, the EU equivalent |
| Integration Key | The credential that identifies your application to the Spritz SDK |
| User API Key | A per-user credential returned when you create a user; scopes SDK calls to that user |
FAQ
What is a crypto off-ramp API?
A crypto off-ramp API is a server-side interface that converts cryptocurrency into fiat money and settles it to a user's bank account, card, or local payment rail. It typically exposes endpoints for KYC, payment request creation, on-chain settlement params, and webhook delivery.
How long does it take to add fiat payouts to a crypto wallet app?
Using a white-label SDK such as Spritz, a wallet team can ship fiat payouts to production in 1 to 2 weeks. fomo went live in under two weeks. Building the same capability in-house, including obtaining money transmitter licenses in the United States, typically takes 9 to 18 months and $750K to $2M.
Do I need a money transmitter license to offer fiat off-ramps?
Not if you partner with a licensed provider. Spritz holds the MSB and EMI licenses and acts as the regulated counterparty. The wallet app is the technology layer.
Which chains and tokens does the Spritz SDK support?
The Spritz SDK supports off-ramp from 8 networks: Ethereum, Polygon, Base, Arbitrum, Avalanche, Optimism, Solana, and Tron. Token coverage per network is documented in the SDK reference. USDC is supported on every network. Ethereum also supports USDT, DAI, USDP, and PYUSD; Solana supports USDC and PYUSD; Tron supports USDT.
How fast is the payout?
US ACH settles same-day to 1 business day. Token delivery to the SpritzPay settlement contract is on-chain, typically seconds on Solana and Base and minutes on Ethereum L1. Local rails in other markets settle on the same timelines they do for any fintech using that rail.
Can my users keep custody of their crypto until the moment of payout?
Yes. The Spritz off-ramp model is non-custodial up to the on-chain transfer. The user signs the SpritzPay contract call from their own wallet; Spritz only takes possession of the asset at the settlement contract address.
What is the difference between an on-ramp and an off-ramp?
An on-ramp converts fiat into crypto. An off-ramp converts crypto into fiat. The Spritz SDK supports both directions; for the on-ramp side, see our crypto onramp API guide.
What does the Spritz SDK cost?
Pricing depends on volume, geography, and which flows you turn on. The model is transparent: a clean fee structure with no rev share, so partners can set their own markup on top. Per-transaction fees apply once monthly volume exceeds $100. Request the one-pager for the full pricing model or talk to sales.
Has anyone shipped this on the Spritz SDK?
Yes. fomo, a Benchmark-backed trading app, integrated the Spritz SDK in under two weeks and processed $2M+ in fiat withdrawals for 4,000+ users. Full details in the fomo case study.
What happens if a payout fails?
Spritz emits a payment.refunded webhook event when a payment cannot be settled to the destination account. Surface the refund in the user's wallet UI so the user knows funds were returned.
Can users pay bills directly, or only withdraw to a bank?
Both. The same SDK supports bill pay (paying a third-party biller directly) and off-ramp (paying the user's own bank). Bills include US credit cards, mortgages, utilities, and more. See the crypto bill pay guide.
Does the Spritz SDK support virtual cards?
Yes. Integrators can issue crypto-funded virtual debit cards via client.virtualCard.create. Card numbers and CVVs are rendered securely via Spritz secure-element libraries for React and React Native.
Can integrators subsidize fees for their users?
Yes. The SDK supports per-transaction fee subsidies (gated feature). Set feeSubsidyPercentage and maxFeeSubsidyAmount on the payment request. Subsidized amounts are invoiced to the integrator separately.
Get started
Three paths from here, matched to where you are in your decision:
- Just exploring? Download the off-ramp one-pager (PDF). Coverage matrix, integration timeline, pricing model on one page.
- Comparing providers? Read the fomo case study and the self-custodial vs custodial guide.
- Ready to integrate? Talk to sales. We respond within one business day with a sandbox key, a coverage check, and a 30-minute walkthrough.
Most partners go from first call to live sandbox within 48 hours, and from sandbox to production in one to two weeks.



