Your First Integration
Build your first 0Bit integration by choosing a product track, creating the first product object, and reconciling trusted state.
This walkthrough is for all 0Bit products. It starts with the product decision, then shows the shared implementation pattern. The detailed code sample uses 0Gate as the concrete example because it exercises the most visible server-to-browser-to-webhook loop, but 0Pools, 0Base, and 0Link follow the same backend ownership and reconciliation rules with product-specific objects.
Pick the integration track
| Track | Build first | Continue in product docs |
|---|---|---|
| 0Gate | Server-created session, hosted/embed flow, signed event handler. | 0Gate quickstart |
| 0Pools | Entitled pool discovery, quote request, quote execution, trade-status reconciliation. | 0Pools quickstart |
| 0Base | Checkout/payment intent/payment link/invoice object plus settlement/report status. | 0Base quickstart |
| 0Link | Route/workflow review record plus route confirmation and fallback-state handling. | 0Link quickstart |
| 0Pools Scan | Activity/status read and support-facing investigation view. | 0Pools Scan |
End-to-end flow
1. Model your internal record
Create your own record before calling 0Bit:
type CheckoutRecord = {
id: string;
userId: string;
amount: string;
currency: string;
status: 'draft' | 'session_created' | 'pending' | 'completed' | 'failed' | 'cancelled';
obitProduct: '0gate' | '0pools' | '0base' | '0link' | 'scan';
obitObjectId?: string;
obitEventIds: string[];
idempotencyKey: string;
};This record is the anchor for support and finance. Do not make the 0Bit session id your only record id.
2. Create the first product object from your backend
The object depends on the track:
| Product | First backend call |
|---|---|
| 0Gate | Create a Gate session. |
| 0Pools | List entitled pools, then create or lock a quote. |
| 0Base | Create a checkout, payment intent, payment link, or invoice. |
| 0Link | Create or review route/workflow context where enabled. |
| 0Pools Scan | Read activity/status records by id or filter. |
Example 0Gate track:
import { GateClient } from '@0bit/gate';
const gate = new GateClient({
apiKey: process.env.OBIT_SECRET_KEY!,
baseUrl: 'https://gate-api-sandbox.0bit.app',
});
export async function createCheckoutSession(record: CheckoutRecord) {
const session = await gate.sessions.create(
{
amount: record.amount,
currency: record.currency,
return_url: 'https://app.partner.example/checkout/done',
metadata: {
checkout_id: record.id,
user_id: record.userId,
},
},
{
idempotencyKey: record.idempotencyKey,
},
);
await saveCheckout({
...record,
status: 'session_created',
obitObjectId: session.id,
});
return {
checkoutId: record.id,
clientSecret: session.client_secret,
};
}If your SDK version does not support an options object for idempotency, send the same call through REST and include the Idempotency-Key header.
3. Run the product UX or server flow
0Gate usually has a browser-visible hosted/embed flow. 0Pools is usually headless and server-first. 0Base can be hosted checkout, payment link, or object-first. 0Link is route/workflow review. Match the client behavior to the product contract.
Example 0Gate browser flow:
import { RampCheckout } from '@0bit/gate/react';
export function CheckoutPage({ clientSecret }: { clientSecret: string }) {
return (
<RampCheckout
publishableKey={process.env.NEXT_PUBLIC_OBIT_PUBLISHABLE_KEY!}
clientSecret={clientSecret}
onSuccess={({ sessionId }) => {
console.log('Show confirmation UI while backend verifies', sessionId);
}}
onError={({ code, message }) => {
console.warn(code, message);
}}
/>
);
}The browser can show progress. Your backend decides final state after a verified event or trusted status read.
4. Receive and verify the webhook or trusted status
import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.post('/webhooks/0bit', express.raw({ type: 'application/json' }), async (req, res) => {
const rawBody = req.body.toString('utf8');
const signature = req.header('Gate-Signature') ?? '';
if (!verifyGateSignature(rawBody, signature, process.env.OBIT_WEBHOOK_SECRET!)) {
return res.sendStatus(401);
}
const event = JSON.parse(rawBody);
if (await eventAlreadyProcessed(event.id)) {
return res.sendStatus(200);
}
await storeEvent(event.id, event);
await applyCheckoutEvent(event);
return res.sendStatus(200);
});
function verifyGateSignature(rawBody: string, header: string, secret: string) {
const parts = Object.fromEntries(header.split(',').map((part) => part.split('=')));
const timestamp = Number(parts.t);
const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(parts.v1, 'hex'));
}5. Apply business state
Keep the state transition narrow:
| Event type or status | Backend action |
|---|---|
| Completed/succeeded terminal state | Mark your record complete and fulfill once. |
| Cancelled | Mark the record cancelled and let the user restart. |
| Failed | Mark failed, store reason/code, and show a recoverable path where appropriate. |
| Pending/processing | Keep your record pending and wait for the next trusted state. |
| Unknown event type | Store it, return 2xx if verified, and alert for review without breaking delivery. |
Do not run fulfillment twice. Store processed event ids and also guard by your own record status.
6. Reconcile
Your support and finance view should be able to answer:
| Question | Record field |
|---|---|
| Which user/order started this? | Your record id and user id. |
| Which 0Bit object did it create? | obitSessionId or product-specific object id. |
| Which request created it? | Idempotency key and request timestamp. |
| Which event closed it? | Webhook event id and event timestamp. |
| What did the user see? | Browser callback logs and return URL outcome. |
| What does 0Bit show? | Trusted API read, report/ledger row, or Scan activity where applicable. |
Production checklist
| Check | Pass condition |
|---|---|
| Sandbox flow | Session create, hosted flow, callback, webhook, and reconciliation all work in test mode. |
| Webhook endpoint | Uses raw body, verifies Gate-Signature, dedupes event ids, and returns 2xx on duplicates. |
| Secret handling | No sk_* or whsec_* in browser bundle, logs, analytics, or screenshots. |
| Allowed domains | Local, staging, and production origins are configured before each environment test. |
| Live switch | Production uses live host, sk_live_*, pk_live_*, and live webhook secret together. |
Where to go next
0Gate quickstart
Continue with the product-specific hosted ramp docs.
0Pools quickstart
Continue with headless liquidity, quotes, execution, and trade-status reconciliation.
0Base quickstart
Continue with merchant checkout/payment-object infrastructure.
0Link quickstart
Continue with route review and connected workflow boundaries.