Embed the 0Gate widget
Mount the hosted 0Gate iframe with the public browser SDK, keep session creation server-side, and use callbacks only for browser UX.
Embed the 0Gate widget when your web page can host an iframe and you want the full buy, sell, and swap experience on the page. Your backend creates the session, the browser receives only a publishable key and browser-safe session secret, and signed webhooks remain the source of truth.
The widget is hosted, not headless
The iframe owns KYC, payment-method collection, quote confirmation, and terminal checkout UX. Do not rebuild those screens from unsupported APIs or treat browser callbacks as proof of settlement.
Embed contract
Install
npm install @0bit/gateimport { GateRamp } from '@0bit/gate/browser';npm install @0bit/gateimport { RampCheckout } from '@0bit/gate/react';<script src="https://cdn.jsdelivr.net/npm/@0bit/gate/dist/browser/gate.iife.js"></script>The browser bundle exposes GateJS.GateRamp.
Create the session server-side
Create a 0Gate session from your server. Store the 0Gate session id next to your own attempt id, then return only the browser-safe values needed to mount the widget.
import { GateClient } from '@0bit/gate';
const gate = new GateClient({ apiKey: process.env.GATE_SECRET_KEY! });
export async function createCheckoutSession(input: CheckoutInput) {
const attempt = await checkoutAttempts.create({
accountId: input.accountId,
amount: input.amount,
currency: input.currency,
status: 'pending_session',
});
const session = await gate.sessions.create({
amount: input.amount,
currency: input.currency,
return_url: `https://app.example.com/checkout/${attempt.id}/return`,
cancel_url: `https://app.example.com/checkout/${attempt.id}/cancel`,
user_reference: attempt.id,
});
await checkoutAttempts.attachGateSession(attempt.id, session.id);
return {
attemptId: attempt.id,
clientSecret: session.client_secret,
};
}Mount the iframe
Construct one GateRamp per checkout attempt. Mount it into a stable container and unmount it when the page, modal, or route is torn down.
import { GateRamp } from '@0bit/gate/browser';
const ramp = new GateRamp({
publishableKey: import.meta.env.VITE_GATE_PUBLISHABLE_KEY,
clientSecret,
environment: 'sandbox',
theme: 'light',
});
await ramp.mount('#gate-checkout', {
onReady: () => setCheckoutReady(true),
onSuccess: ({ sessionId }) => {
showProcessingState(sessionId);
refreshAttemptStatus();
},
onError: ({ code }) => showRecoverableError(code),
onClose: ({ reason }) => showResumeOrRetry(reason),
onUnavailable: () => showUnavailableState(),
});
// Later, when this checkout surface closes:
ramp.unmount();Callback contract
| Callback | Use it for | Do not use it for |
|---|---|---|
onReady | Stop loading placeholders and record widget availability. | Mark payment as started or paid. |
onSuccess | Move the page to processing and poll your own status endpoint. | Fulfillment, crediting, shipping, or balance updates. |
onError | Show a generic recoverable failure and capture a safe code. | Display raw provider, compliance, or settlement diagnostics. |
onClose | Offer retry, resume, or support. | Automatically closing a server attempt as failed. |
onUnavailable | Render a neutral unavailable state. | Creating unlimited retry attempts. |
Origin checks are part of the public contract
The embed bootstrap uses your publishable key and the browser origin. Configure allowed origins before production, and expect exact-origin matching rather than wildcard behavior.
React mount
Use RampCheckout when your app is React-based. Keep the same server-created clientSecret and callback rules.
import { RampCheckout } from '@0bit/gate/react';
export function CheckoutFrame({ clientSecret }: { clientSecret: string }) {
return (
<RampCheckout
publishableKey={import.meta.env.VITE_GATE_PUBLISHABLE_KEY}
clientSecret={clientSecret}
environment="sandbox"
theme="light"
onSuccess={() => setView('processing')}
onError={({ code }) => setErrorCode(code)}
onClose={() => setView('retry')}
onMountError={() => setView('unavailable')}
/>
);
}Production guardrails
| Guardrail | Why it matters |
|---|---|
Keep sk_* credentials on the server. | The SDK accepts publishable keys in browser code and rejects secret keys. |
| Create one local attempt before opening 0Gate. | Every callback, webhook, and support action has a durable record to attach to. |
| Redact browser session secrets from logs. | The session secret is a browser capability, not a long-term audit value. |
| Verify signed webhooks before fulfillment. | Browser messages and return URLs can improve UX, but backend events close money state. |
| Unmount stale widgets. | Route changes, modals, and retry flows should not leave old iframe listeners alive. |
Related pages
Build a 0Gate payment flow
See the full server, browser, webhook, and reconciliation architecture.
Embed a single flow with kit blocks
Lock the same hosted iframe to on-ramp, off-ramp, or swap.
Handle widget callbacks
Map every browser callback to the correct backend behavior.
Configure return URLs and outcome pages
Build result pages that read trusted server state.
Handle failed or cancelled flows
Recover safely from failed, expired, cancelled, delayed, and interrupted hosted 0Gate flows.
Embed a single flow with kit blocks
Use 0Gate kit blocks to open the hosted iframe directly into on-ramp, off-ramp, or swap while keeping the session and webhook model unchanged.