TL;DR
A crypto onramp turns fiat into crypto inside your product. Most guides treat it as a third-party widget you redirect users to. It is better understood as one step in the wallet's funding lifecycle, because a card purchase, a bank transfer, a transfer from an existing wallet, and a withdrawal from an exchange all end at the same place: funds in your user's wallet. Openfort models all of them as one funding session with a single status model (requires_payment_method to waiting_payment to processing to succeeded, ending at bounced or expired) and one webhook, so you write the failure handling once. The parts that decide your build are KYC ownership, country coverage, settlement time, and what happens when a card is declined — not the widget.

Your user has a wallet. It is empty. Everything you built after that point — the payment, the subscription, the payout, the trade — waits on one question: how does money get in?
That question is what a crypto onramp answers, and most guides answer it badly. They treat the onramp as a vendor you bolt on, compare five of them on fees, and stop. This guide covers what an onramp actually is, the four ways money reaches a wallet, how to build the fiat path, and what it costs you in compliance and failure handling. For the product side, see Openfort Funding.
What a crypto onramp actually is
A crypto onramp converts fiat into crypto and delivers it to a wallet address. A user pays with a card or a bank transfer; USDC, ETH, or another token lands in the wallet. The conversion, the identity checks, and the on-chain settlement happen behind that single action.
Four things get conflated here, and they are not interchangeable:
- An onramp takes fiat and produces crypto.
- An offramp takes crypto and produces fiat. It is a separate integration with a separate compliance surface.
- A bridge moves a token from one chain to another. Both sides are crypto.
- A swap exchanges one token for another. Both sides are crypto.
Every onramp has three parties behind it, whether or not you can see them: a payment processor that takes the money, a compliance provider that verifies the buyer, and a liquidity source that delivers the crypto. When people say an onramp is "just a widget," they mean a vendor has bundled those three and given you an iframe.
The older meaning of the word — send your user to an exchange and hope they come back — stopped being viable once products started creating wallets for users who had never held crypto. Those users will not open a Coinbase account to use your app. The onramp had to move inside the product.
The four ways money gets into a wallet
A fiat onramp is one path. Treating it as the only path is the most common design mistake, because it leaves out every user who already holds crypto somewhere else.
Card, Apple Pay, and Google Pay. The fastest path and the one users expect. It is also the one with the highest decline rate and the tightest per-buyer limits, because the risk sits with the card networks.
Bank transfer. ACH, SEPA, or Interac depending on the region. Cheaper per unit and better for larger amounts, and slow enough that your interface has to show a pending state honestly rather than pretending the transfer is instant.
Transfer from a wallet or an exchange. The user already holds crypto in MetaMask, Phantom, or a Binance account. No fiat is involved, no KYC event is triggered on your side, and the money can arrive in one transaction. For a crypto-native audience this is often the highest-converting path, and a fiat-only integration ignores it completely.
A universal deposit address. One address per route that accepts a token on a chain the user already uses, then bridges and swaps it to the token your app actually needs. This is what removes "wrong network" from your support queue. We wrote about the mechanics in the universal deposit address post.
The reason to name all four is that they share a destination. If each one has its own SDK, its own status vocabulary, and its own webhook, you write the same reconciliation logic four times and get four different bugs.

How to add a fiat onramp to your app
There are two shapes this build can take.
The naive path
Embed a provider's widget, redirect the user out, and reconcile the provider's webhooks against your own wallet state yourself. This works. It also means you own the mapping between the provider's status vocabulary and yours, you own the case where the user closes the window mid-payment, and you own the second mapping when you add a second provider for a region the first does not serve.
The funding-session path
Model the deposit as one session with a destination and a source, whatever the source is. In Openfort, a funding session advances through a single status model:
_10requires_payment_method → waiting_payment → processing → succeeded
It can also end at bounced, where delivery failed and the funds were refunded on the source chain, or expired, where no deposit ever arrived. Those three terminal states are the entire outcome space, and they are the same whether the user paid with a card or sent USDC from Polygon.
In React, three hooks cover the fiat path. useFunding creates the session, useFundingMethods resolves which fiat methods this specific buyer can use, and useOnramp quotes and commits the purchase:
_10import { useFunding, useFundingMethods, useOnramp } from '@openfort/react'_10_10function Deposit({ walletAddress }: { walletAddress: string }) {_10 const { createSession, session, status } = useFunding()_10 const { methods, country, loaded } = useFundingMethods(session)_10 const card = methods.find((m) => m.id === 'card')_10 const onramp = useOnramp(session, card, { mode: 'redirect' })_10_10 // create a session for USDC on Base, then present the resolved methods_10}
Method resolution happens server-side, per buyer, by region and destination. Your app never holds provider keys and never renders provider branding. A committed method carries an angle that tells you how to present it: popup for a hosted checkout you open in a new tab, native for an Apple Pay or Google Pay sheet, embedded for the provider's own elements rendered inside your page. The headless API reference documents the same flow over HTTP for backends, scripts, and agents.
Two constraints are worth knowing before you plan the work. Fiat methods are off by default and fail closed — until you enable them in the dashboard, method resolution returns no fiat rows at all, which looks like a bug and is not. And fiat coverage is mainnet-only, delivering USDC on Base, Ethereum, Polygon, Arbitrum, Optimism, or Solana; a testnet destination resolves no fiat methods, so you cannot exercise the fiat path on a testnet destination.
Some presentations depend on your own provider credentials. Native Apple Pay and Google Pay in the US require Coinbase CDP keys; without them the same methods still resolve, degraded to the hosted popup. Stripe rails require your Stripe secret key, and the optional Link OAuth client is what moves card checkout from a popup to an in-page element.
Whichever path you pick, you still own three things: the destination wallet, the limits you enforce on top of the provider's, and the retry experience when a payment fails.
What an onramp really costs you
The sticker price is the smallest part.
The fee stack has three layers, and a provider quoting you "1.5%" is usually naming one of them. There is the processor fee on the payment itself, the spread between the quoted rate and the market rate, and the network fee to deliver on-chain. Ask every provider to break out all three, and price the same test transaction across the providers you are considering rather than comparing published rates. Published rates move, and coverage differs by corridor. If the token you are delivering is a stablecoin, the same three layers show up again in the stablecoin payment infrastructure underneath it.
Declines are the real cost. Card onramps for crypto sit in a high-risk category, and a share of legitimate buyers get rejected on the first attempt. That share is the number that decides whether your funding flow works, and it is the number no provider publishes. Measure it yourself in your first month and design a second method to fall back to, because a user who cannot fund cannot use the product at all.
KYC ownership decides your compliance surface. Identity collection happens at the provider — with Openfort's limit-upgrade flow, the buyer is sent to a provider-hosted URL and that data never passes through Openfort. What this does not settle is which entity is merchant of record for a given buyer, and that answer changes with the provider serving that region. Confirm it in writing with each provider you enable, before launch rather than during a review.
Coverage gaps are a routing problem, not an error. No provider covers every country, and the ones that do cover a country do not cover every method in it. The design question is what your interface does when method resolution comes back with fewer rows than you expected — which is why resolving methods per buyer, before rendering options, is worth the extra call.
Settlement time belongs in the interface. Cards clear in seconds; bank transfers take hours or days. A session sitting in processing is normal. Openfort emits funding.session.updated webhooks for every transition, and the reason to drive your UI from those rather than from the checkout window is blunt: the window closing is not an outcome. The buyer may have paid a second before they closed it.
Standalone onramp provider or bundled wallet funding
| Dimension | Standalone onramp provider | Openfort funding |
|---|---|---|
| Integration surface | A separate SDK plus a redirect, reconciled against your wallet state | One funding session inside the wallet SDK |
| Methods covered | Card and, with some providers, bank transfer | Card, Apple Pay, Google Pay, bank transfer, wallet and exchange transfer, universal deposit address |
| Status model | The provider's webhooks, mapped by you | requires_payment_method → waiting_payment → processing → succeeded, ending at bounced or expired |
| Provider selection | You integrate and maintain each one | Resolved server-side per buyer by method, region, and destination |
| Provider keys in your app | Yes | No, except the optional Coinbase CDP and Stripe credentials that unlock native and embedded presentations |
| KYC | At the provider | At the provider; identity collection never passes through Openfort |
| Country coverage | Per provider — confirm against each provider's current coverage page | Per provider, resolved per buyer at request time |
| Fees | Per provider — confirm against each provider's current pricing page | Per provider; quote each method through the session before committing it |
A standalone provider is genuinely the right call in a narrow case: you serve one market, you need one method, and you already have a processor relationship worth preserving. That is a real situation and the extra abstraction buys you nothing.
Bundling wins when any of those stops being true. Multiple methods, multiple regions, multiple chains, or a small team — in each case the cost is not the integration, it is maintaining N status models forever. If you are weighing specific platforms, we compare them directly on Openfort vs Crossmint and Openfort vs Turnkey.
An onramp selection checklist
Copy this into your evaluation doc and make each vendor answer it in writing.
- Methods. Card, Apple Pay, Google Pay, bank transfer, and crypto transfer — which are supported, and in which countries separately from the country list for the provider as a whole?
- Country coverage. Which corridors are live today, which are announced, and what does the API return for a buyer in an unsupported one?
- KYC model. Who collects identity data, who stores it, and who is merchant of record? Get this per region, because the answer changes with the provider.
- Limits. What are the per-transaction and per-period limits for a new buyer, and what does the upgrade path look like?
- Settlement time. Per method, and stated as a range rather than a best case.
- Fee transparency. Processor fee, spread, and network fee broken out separately, on a quote for a real transaction.
- Status and webhook model. How many states, are they documented, and does a webhook fire for every transition or only on success?
- Chain and token coverage. Which chains can receive, which tokens, and is there a bridge step behind the scenes you should know about?
- Failure handling. What happens on a declined card, a stuck payment, a partial fill, and a delivery failure after the buyer has already paid?
- Testability. Can you exercise the full flow before launch, and if fiat is mainnet-only, what is the plan for testing it?
The last two are the ones teams skip and then discover in production.
Where to start
If you are choosing between vendors, start with the checklist above and score them on failure handling rather than on fees. Fees converge; failure handling does not.
If you already run embedded wallets and are adding funding to them, the shorter path is to model every deposit as one session against one status model, so the card path and the crypto path fail the same way. That is what Openfort Funding does, and it sits on the same embedded wallet and wallet-as-a-service infrastructure you would already be running. Pricing is on the pricing page, and the funding docs have the full session model.
FAQ
What is a crypto onramp?
A crypto onramp converts fiat money into crypto and delivers it to a wallet. In a product context it means a user pays with a card, Apple Pay, Google Pay, or a bank transfer, and the equivalent value arrives in the wallet your app created for them. The conversion, the compliance checks, and the settlement to a blockchain address all happen behind that one action.
What is the difference between an onramp and an offramp?
An onramp moves value from fiat into crypto. An offramp moves it the other way, from crypto back into a bank account or card. They are separate integrations with separate compliance surfaces, and supporting one does not give you the other. A bridge and a swap are different again: both move value that is already crypto, between chains or between tokens.
How do I add a fiat onramp to my app?
Either integrate a standalone onramp provider directly, or use the funding layer of the wallet platform you already run. With Openfort you create a funding session for a destination, resolve which fiat methods the buyer can use, commit one as the payment method, and read the session until it settles. The provider is selected server-side by method, region, and destination, so your app never holds provider keys.
Who handles KYC when you use an embedded onramp?
The onramp provider does. Identity collection happens on the provider's own hosted flow, and with Openfort's limit-upgrade endpoint that flow never passes through Openfort. That does not make the question moot for you: which provider serves a given buyer determines whose terms apply, so confirm the merchant-of-record model with each provider you enable before launch.
How long does a fiat-to-crypto onramp take to settle?
It depends on the payment method, not on the chain. Card, Apple Pay, and Google Pay clear in seconds to minutes. Bank transfers over ACH, SEPA, or Interac clear in hours to days. Design the wait into the product: a session in processing is a normal state that your interface has to show, not an error.
Do I need a separate onramp provider if my wallet platform includes funding?
Usually not, and the reason is failure handling rather than features. A separate provider means a second SDK, a second status model, and a second set of webhooks to reconcile against your own wallet state. Bundled funding is worth giving up when you serve one market with one method and already have a processor relationship worth keeping.

