Endpoints
Onramp exposes two environments. Use sandbox for local development and testing. Use production for real transactions.
Your API key authenticates your server. Keep it
server-side only, since it grants full access to your Onramp integration.
Widget origin
BothcreateAppServerKit on your server and new AppKit on your client accept
a widgetBaseUrl option that points at the widget origin. The default is the
production widget URL, so production integrations don’t need to set it. To
target sandbox, pass the sandbox widget origin on both sides.
Server side:
mountIframe and
openWindow throw an
INPUT_WIDGET_URL_ORIGIN_MISMATCH
error (code 1910).
Sandbox
Sandbox is a testing environment for developing your Onramp integration without real money movement. It exposes the same API surface as production. Only the endpoints and the API key binding differ. Use sandbox for local development. The production widget’s Content Security Policy blockslocalhost, so a production widget won’t load from a local dev
server.
To target sandbox, override two config values on the server and one on the
client. API keys are environment-bound. A sandbox API key won’t work against
production, and a production API key won’t work against sandbox.
Example .env
.env
widgetBaseUrl value is safe to expose to the browser, so a NEXT_PUBLIC_
(or your framework’s equivalent) prefix lets the client read it. The API key is
the only real secret and never gets a public prefix.
Content security policy
If your site sends a CSP header, you must allow the widget and API origins for the environment you target. Without these directives, the iframe silently fails to load. Sandbox:Container element
Two container-side preconditions apply when callingmountIframe:
The container must be attached to the document
The App Kit SDK appends the iframe synchronously and installs aMutationObserver that auto-disposes the widget if the container later
detaches. The container must be in the DOM when you call mountIframe:
- In React, mount from a
useEffect(not during render) so the ref is populated before the call. - In other frameworks, use that framework’s mounted lifecycle.
- In plain browser code, wait for
DOMContentLoadedor insert the container yourself before calling.
The container must have an explicit, non-zero height
The iframe renders atwidth: 100%; height: 100%. A cross-origin iframe cannot
size itself to its content, so without a resolved height the iframe collapses to
0px and the user sees nothing.
- A fixed
height(such as720px). - A
min-height. - A flex child inside a parent with a sized cross-axis.
Popup mode constraints
When you useopenWindow instead of mountIframe, the host environment
matters:
- Mobile browsers open a new tab, not a sized popup. The
widthandheightfeatures are ignored. - In-app browsers (Instagram, Facebook, TikTok, LinkedIn, WeChat, LINE)
block popups.
openWindowreturns{ status: 'blocked', reason: 'in_app_browser' }so you can fall back tomountIframe. - Installed web apps in standalone mode also block popups.
openWindowreturns{ status: 'blocked', reason: 'pwa_standalone' }.
Third-party storage in iOS Safari
iOS Safari’s Intelligent Tracking Prevention (ITP) can restrict the embedded app’s access to its own storage inside an iframe. If you see KYC or session issues that only occur on iOS Safari, useopenWindow mode on that platform.
Webhooks are the source of truth
Browser lifecycle events such asDEPOSIT_SUBMITTED and DEPOSIT_SETTLED are
best-effort UX signals. A user can close the tab between submitting a deposit
and settlement, and the browser will never deliver the settlement event even
though the deposit completes server-side.
Session lifetime
Onramp sessions are valid for 30 minutes from creation. If your app pre-fetches or reuses a session, mint a fresh one once more than 30 minutes have passed to avoid a stale-session error.Close unused widgets
EachmountIframe() call, and each successful openWindow() call, returns a
widget controller. Keep that controller and call widget.close() before
starting over or when the user leaves the view.