0Bit Documentation

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/gate
import { GateRamp } from '@0bit/gate/browser';
npm install @0bit/gate
import { 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

CallbackUse it forDo not use it for
onReadyStop loading placeholders and record widget availability.Mark payment as started or paid.
onSuccessMove the page to processing and poll your own status endpoint.Fulfillment, crediting, shipping, or balance updates.
onErrorShow a generic recoverable failure and capture a safe code.Display raw provider, compliance, or settlement diagnostics.
onCloseOffer retry, resume, or support.Automatically closing a server attempt as failed.
onUnavailableRender 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

GuardrailWhy 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.

On this page