Skip to main content
Embed the Onramp widget inline in an existing web app using the App Kit SDK. A signed-in user can open your page and complete an onramp inside an iframe. The Onramp widget integration is framework-agnostic. The server handler uses the Fetch Request / Response standard, and the browser widget only needs a mounted DOM container. The route example uses Next.js App Router wiring, but the same handler works in Fetch-compatible backends such as Hono, Cloudflare Workers, Bun, Deno, and modern Node. For Express or Fastify hosts, see Customize session minting.
See the Onramp flow in production at portal.arc.io/deposit/fiat. It uses real payments and identity checks. For testing, use the sandbox environment.

Prerequisites

Before you begin, ensure that you’ve:

Step 1. Set your environment variables

Add your API key to your server environment. Never inline it in client code or commit it to source control.
.env

Step 2. Expose a session route on your server

Create a route that exchanges your API key for a short-lived session token. The App Kit SDK ships createSessionRouteHandler as a drop-in Request → Response handler. The following example uses the Next.js App Router:
app/api/onramp/sessions/route.ts
The handler accepts POST requests, validates the body, calls server.onramp.createSession(), and returns the session as JSON. It maps thrown errors to the appropriate HTTP status codes and sets Cache-Control: no-store so session tokens are never cached.
This route doesn’t perform authentication. Before deploying, add an authorize callback that checks the user’s session. See Customize session minting.

Step 3. Add a container element to your page

The Onramp widget renders inside an <iframe> that fills its container. The container must already be attached to the DOM and must have an explicit, non-zero height, or the iframe collapses to 0px. The snippet shows only the container markup. Step 4 extends this file with the full mounting logic.

Step 4. Mint a session and mount the widget

In your browser code, mint the session by sending a POST request to the route you created in step 2, then mount the widget into the container element.
onramp.ts
Replace USER_WALLET_ADDRESS with the signed-in user’s Arc wallet address before running the flow. Keep the widget controller returned by mountIframe. Call widget.close() when the user leaves this view, closes the modal, or starts a new widget session. In a framework, call stopOnramp() from that framework’s cleanup lifecycle.

Step 5. Allow the widget origin in your Content Security Policy (CSP)

If your site sends a CSP header, the iframe fails to load silently unless you allow the widget origin:
The widget handles its own requests through its CSP, so your page doesn’t need connect-src for Onramp. Other App Kit capabilities (Bridge, Swap, Earn, Borrow, Unified Balance) need connect-src https://api.circle.com for error reporting if used in the browser. See Hosting requirements for the complete list of host-side constraints.

Step 6. Set up a browser event receiver

The browser emits DEPOSIT_SUBMITTED when the user finishes the widget flow. For card, Apple Pay, and Google Pay purchases, DEPOSIT_SETTLED may follow, but only if the widget is still open when settlement happens. Bank transfer deposits don’t emit DEPOSIT_SETTLED. In production, bank transfer users receive an email when the deposit lands in their wallet. Sandbox doesn’t send this email.