Developers
Core Concepts

Glossary

Reference definitions of the key 0Gate terms — credentials, the session object, flows, webhooks, compliance, and platform — each grounded in the real API and SDKs and linked to the page that covers it in depth.

A quick reference for the terms a 0Gate developer meets, grouped by category and linked to the concept or how-to page that goes deeper. If you are new, read Core Concepts first for the mental model, then use this page to look things up. The "On this page" panel nests each category so you can jump straight to credentials, flows, webhooks, and so on.

One product, today

The main partner-ready product is 0Gate — the embeddable fiat ↔ crypto buy / sell / swap ramp. 0Pools, 0Base, and 0Link are the shared liquidity spine and internal routing beneath it. 0Pools is a gated, approved-partner liquidity API (early access, provisioned per partner by 0Bit) — not the default public path; most integrations should use 0Gate.

Credentials and tokens

The five credentials below carry every 0Gate integration, and which side each lives on is the whole security model. See Authentication for the full reference.

TermMeaning
Publishable key (pk_test_… / pk_live_…)A browser-safe key that authorizes exactly one operation — POST /v1/embed/bootstrap — and nothing else. Safe to ship to the page; cannot create, read, or cancel sessions. See Authentication.
Secret key (sk_test_… / sk_live_…)Your privileged server key. It creates, retrieves, and cancels sessions and must never reach the browser. Sent as Authorization: Bearer sk_…. See Authentication.
client_secret (gsec_<sessionId>_<random>)The one-time, browser-safe capability returned when you create a session. It binds the widget to exactly that one session; shown once, in the create response. See Sessions.
Embed tokenA short-lived HS256 JWT (default 1h TTL) the widget mints for itself by exchanging pk_… + client_secret at POST /v1/embed/bootstrap. Sent on iframe → API calls in the X-Embed-Token header. See Authentication.
Webhook signing secret (whsec_…)The server-only HMAC secret used to verify inbound webhooks. Shown once when rotated in Partner Hub; never exposed to the browser. See Webhooks.

Keep secrets server-side

sk_… and whsec_… live on your server only. Only the publishable key (pk_…) and a session's client_secret are browser-safe.

Key formats and prefixes

Every credential is prefix-typed so the backend can route and reject it before a hash lookup. The prefix encodes both the kind of key and its mode.

CredentialExact formatIssued by
Publishable keypk_test_<32 alnum> / pk_live_<32 alnum>Partner Hub or POST /portal/keys (type: publishable)
Secret keysk_test_<32 alnum> / sk_live_<32 alnum>Partner Hub or POST /portal/keys (type: secret)
client_secretgsec_<sessionId>_<32 char>Returned by POST /v1/gate_sessions
Webhook secretwhsec_<32>POST /portal/webhook-secret/rotate

Only the SHA-256 hash plus a short display prefix is stored server-side; the raw sk_…, pk_…, and whsec_… values are shown exactly once at creation or rotation, never again. The mode (test / live) is read from the key prefix — there is no separate mode flag on the request.

How each credential travels on the wire

CredentialHeader(s) acceptedAllowed in query string?
Publishable keyAuthorization: Bearer pk_… or X-Publishable-Key: pk_…Yes (?publishable_key=) — bootstrap only
Secret keyAuthorization: Bearer sk_… or X-Secret-Key: sk_…Never
Embed tokenX-Embed-Token: <jwt>No

Authorization: Bearer <key> is the canonical form; the X-Publishable-Key / X-Secret-Key headers are accepted equivalents. There is no x-0bit-* auth header.

Embed token claims

The embed JWT is signed HS256 with the backend's EMBED_TOKEN_SECRET and carries these claims: partner_id, kid (signing key id), mode, origin, scope (always embed), and session_id (set only when the bootstrap was session-bound). Default TTL is 1h (EMBED_TOKEN_TTL_SECONDS=3600). See Authentication.

The session and its lifecycle

TermMeaning
GateSessionThe unit of work for one 0Gate checkout — a single buy, sell, or swap. Created server-side with the amount, currency, return_url, and flow bound in, then driven to a terminal outcome by webhooks. See Sessions.
Session idThe server-side handle for a session (a Mongo ObjectId hex string). You store it, retrieve and cancel with it, and correlate webhooks against it; it does nothing in a browser on its own. See Sessions.
StatusA session's lifecycle state: open (live and mountable), then exactly one terminal outcome — completed, expired, or cancelled. Terminal states are final. See Sessions.
flowThe kit-block lock on a session — on_ramp, off_ramp, or swap — or unset, letting the user pick the tab in the widget. See Sessions.

Session fields

These are the fields on a GateSession object as returned by the API. The object discriminator is always gate_session.

FieldTypeNotes
idstringMongo ObjectId hex, e.g. 67a1f3b9e4b0c10001234567.
objectstringAlways gate_session — discriminator for client-side type narrowing.
partner_idstringPartner that owns the session.
modetest | liveInherited from the sk_… that created it.
flowon_ramp | off_ramp | swap | nullKit-block flow lock; null = open widget.
amountstringDecimal string, server-bound at create; intents must match exactly.
currencystringISO 4217 three-letter code.
target_tokenstring | nullOptional constraint — user may only buy/swap to this token.
target_networkstring | nullOptional constraint — user may only operate on this network.
return_urluriWhere the iframe sends the user on success; origin must be in allowed_domains.
cancel_urluri | nullOptional cancel destination.
statusopen | completed | expired | cancelledLifecycle state.
expires_atdate-timeISO-8601, default 24h after creation.
created_atdate-time | nullCreation timestamp.
wallet_addressstring | nullEnterprise input — pre-filled destination wallet.
user_referencestring | nullEnterprise input, max 128 chars — opaque partner-side id, echoed in webhooks.
kyc_pre_verifiedbooleantrue when an accepted kyc_package was submitted. Default false.
metadataobjectOpaque partner notes, returned verbatim, not used for business logic.

Lifecycle states

A session is created open and moves once to a single terminal state. Terminal states never transition again.

StateMeaningTerminal?
openAccepting actions; mountable in the widget.No
completedAt least one linked intent succeeded; the gate_session.completed webhook carries tx_refid.Yes
expiredReached expires_at without completing — transitions lazily, on the first read past the deadline.Yes
cancelledPartner called POST /v1/gate_sessions/:id/cancel on an open session.Yes

Spec status enum vs. failure events

The GateSession.status enum in the API spec is open / completed / expired / cancelled. The backend also emits a gate_session.failed webhook for failed intents — treat it as a terminal signal in your handler even though it is not enumerated as a session status in the spec. See Webhooks.

Enterprise session inputs

Three optional create-time inputs let you pre-fill the flow. wallet_address and user_reference are accepted from any partner; kyc_package is contract-gated.

InputEffect
wallet_addressPre-fills the destination wallet; the iframe lands directly in the wallet step. Validated against the resolved network at flow time, not at session create.
user_referenceOpaque partner-side id (max 128 chars) echoed back in webhook payloads so you can join session events to your own user / order record.
kyc_packagePre-verified identity pass-through; only accepted when partner.kyc_trusted: true (otherwise 403 with code: kyc_package_not_trusted). See Compliance and settlement.

Flows

TermMeaning
On-ramp (on_ramp)A buy — the user pays fiat and crypto settles to their destination wallet. See Sessions.
Off-ramp (off_ramp)A sell — the user sends crypto and fiat settles to their payout method. See Sessions.
Swap (swap)A crypto-to-crypto exchange routed through the platform's shared liquidity spine. See Sessions.

Kit blocks and the flow lock

A kit block is a flow-locked entry point. Setting flow on a session forces the widget into that one flow and hides the buy / sell / swap tab strip — use it when you have already captured the user's intent on your own surface (a "Buy crypto" button). Leaving flow unset (or null) gives the legacy open widget where the user picks the tab.

The browser SDKs expose the same lock as factories — createGateOnRamp / createGateOffRamp / createGateSwap (and <GateOnRamp> / <GateOffRamp> / <GateSwap> in React) — each setting flow to on_ramp / off_ramp / swap. The lock is also echoed back from POST /v1/embed/bootstrap and forwarded to the iframe via the INIT_CONFIG postMessage. See Sessions.

Webhooks and request integrity

TermMeaning
Gate-SignatureThe webhook signature header, value t=<unix>,v1=<hex> — an HMAC-SHA256 over <timestamp>.<rawBody> keyed with your whsec_… secret, valid within a 300-second tolerance. The header is Gate-Signature; there is no x-0bit-signature. See Webhooks.
Idempotency-KeyA UUID sent on write requests so a retried call returns the original result instead of duplicating it. The SDKs attach one automatically; on session create, a retry with the same key + body returns the same session. See Authentication.
Webhook (source of truth)Signed event POSTs to your webhook_urlgate_session.created, .completed (carries tx_refid), .failed, .expired, .cancelled, plus operational events. The browser onSuccess is UX only; the webhook confirms settlement. See Webhooks.

Webhook headers

Every delivery carries the signature plus three companion headers and a fixed user agent. The t= value in Gate-Signature always equals X-0bit-Timestamp.

HeaderValue
Gate-Signaturet=<unix-ts>,v1=<sha256-hex>
X-0bit-Timestamp<unix-ts> — same value as t=
X-0bit-Event-Id<uuid> — stable across retries; use as your dedupe key
X-0bit-Event-Typethe event type, e.g. gate_session.completed
User-Agent0bit-webhooks/1.0

Event envelope

Every webhook body shares one envelope: id (UUID, stable across retries — your dedupe key), type (the event name), created_at (Unix epoch seconds), and data. For gate_session.{created,cancelled,expired} the data is a full GateSession; for gate_session.completed the GateSession gains a top-level tx_refid; for gate_session.kyc_package_accepted the data is a redacted KycPackageAcceptance (session_id, partner_id, mode, provider, accepted_at, user_reference — never raw PII). See Webhooks.

Event catalogue

EventTriggerIn OpenAPI spec?
gate_session.createdPOST /v1/gate_sessions succeeds.Yes
gate_session.completedA linked buy/sell succeeds; adds tx_refid.Yes
gate_session.expiredFirst read past expires_at.Yes
gate_session.cancelledPOST /v1/gate_sessions/:id/cancel succeeds.Yes
gate_session.kyc_package_acceptedA kyc_trusted partner's kyc_package is accepted.Yes
gate_session.failedA linked intent failed.Backend-only
kyc.requiredThe user must complete identity verification before proceeding.Backend-only
partner.quota.warningPartner usage approaching its quota.Backend-only
partner.quota.exhaustedPartner usage quota exhausted.Backend-only

Spec vs. wire

The OpenAPI document enumerates only the first five events. The backend also emits gate_session.failed, kyc.required, partner.quota.warning, and partner.quota.exhausted — handle unknown type values defensively rather than assuming the spec list is exhaustive.

Delivery, retries, and dead-lettering

A leader-elected worker (WEBHOOK_WORKER_ENABLED=true, 30s tick, batch of 20) POSTs each event to your webhook_url. Any 2xx is success. Failures retry on the schedule [1m, 5m, 30m, 2h] and dead-letter after 5 attempts. Past deliveries can be inspected (GET /portal/webhook-deliveries) and replayed (POST /portal/webhook-deliveries/:id/replay) from Partner Hub. See Webhooks.

Compliance, settlement, and the model

TermMeaning
KYCIdentity verification (Know Your Customer), run inside the 0Gate widget by 0Bit's verification partner. 0Bit owns KYC, AML, and sanctions screening on every tier — you never collect or store end-user identity. See Custody & compliance.
kyc.requiredA webhook event signalling that the user must complete identity verification before the session can proceed. See Webhooks.
kyc_packageA contract-gated trusted-KYC pass-through that lets approved partners forward already-verified identity, accepted via the gate_session.kyc_package_accepted event. Available only when 0Bit has marked your partner record kyc_trusted. See Custody & compliance.
Non-custodialThe model where you, the partner, never take custody of end-user funds and never rebuild the ramp or compliance stack; 0Bit is the regulated party of record. See Custody & compliance.
SettlementThe act of money reaching its destination — crypto to the user's wallet on a buy, fiat to their payout method on a sell. Funds settle to the destination, not through your balance sheet, and are confirmed by the gate_session.completed webhook. See Custody & compliance.

kyc_trusted and the kyc_package handshake

kyc_trusted is a flag on your partner record, set by 0Bit (admin) on PATCH /admin/partners/:id/kyc-trusted, that authorizes the kyc_package pass-through. The handshake:

  1. You submit an opaque kyc_package object on POST /v1/gate_sessions — its only required field is provider (string) for the audit trail; the rest is per your contract.
  2. If your record is not kyc_trusted, the call is rejected 403 with code: kyc_package_not_trusted.
  3. If accepted, the session is created with kyc_pre_verified: true, the value is forwarded to the iframe via INIT_CONFIG so the widget can route around its own KYC step, and a redacted gate_session.kyc_package_accepted webhook is delivered.

The raw kyc_package body is never echoed in any API response or webhook — the acceptance envelope carries correlation fields and the provider name only. See Custody & compliance.

tx_refid

The settlement join key. The gate_session.completed event carries a top-level tx_refid — the refid of the underlying crypto transaction — so you can deep-link to the receipt or join the event back to your own order record. It appears only on completed. See Webhooks.

Environments and platform

TermMeaning
Sandbox (test mode)Simulated end-to-end against https://gate-api-sandbox.0bit.app/v1 with …_test_ keys — test cards and bank flows, no real funds, no real KYC, no on-chain settlement. See Environments & modes.
Live (production mode)The real ramp against https://gate-api.0bit.app/v1 with …_live_ keys — real fiat rails, real KYC, real chargebacks, real settlement. The mode is read from the key prefix, not a request flag. See Environments & modes.
allowed_domainsThe exact-match origin allowlist on your partner record. The browser's pk_… bootstrap is rejected unless the page's Origin (or Referer fallback) is on this list (no wildcards). Managed in Partner Hub. See Authentication.
Partner HubThe partner self-service portal at portal.0bit.app for managing API keys, webhook secrets, allowed domains, and usage. See Authentication.
Liquidity spineThe shared treasury and routing (0Pools / 0Link) every product settles against. It is why the compliance and settlement guarantees are identical across surfaces. 0Pools is a gated, approved-partner liquidity API (early access, provisioned per partner by 0Bit) — not the default public path; most integrations should use 0Gate. See Core Concepts.

Hosts by environment

The same path lives on a different host per environment. Raw REST/OpenAPI examples use the /v1 base URL. SDK constructors take the API origin and append resource paths internally.

EnvironmentAPI baseWidget iframe
Productionhttps://gate-api.0bit.app/v1https://gate.0bit.app
Sandboxhttps://gate-api-sandbox.0bit.app/v1https://gate-sandbox.0bit.app
Local devhttp://localhost:4000/v1

See Environments & modes.

The SDK packages

The audited SDK package is @0bit/gate for npm and 0bit-gate for Python. The package source is version 0.1.4, while the Node runtime user agent still reports gate-node/0.1.0, so treat the SDK as pre-GA until release owners confirm the published version.

PackageInstallSurface
@0bit/gatenpm install @0bit/gateGateClientsessions.{create,retrieve,cancel}, embed.bootstrap, webhooks.constructEvent. Node ≥18.
0bit-gate (Python)pip install 0bit-gatefrom zerobit.gate import GateClientsessions.*, embed.bootstrap, webhooks.construct_event. Python package name 0bit-gate, import path zerobit.gate.
@0bit/gate/browsernpm install @0bit/gate or CDNBrowser SDK export; global GateJS in the IIFE build.
@0bit/gate/reactnpm install @0bit/gateReact export for hosted checkout components.

The server SDKs auto-attach Authorization: Bearer <key> and an Idempotency-Key UUID on writes, retry on 408/425/429/500/502/503/504 (2 retries, exponential backoff, honoring Retry-After), and normalize failures into a typed error hierarchy. See SDKs.

API surface, rate limits, and error shape

The public API has no global path prefix beyond /v1 on each route. Writes require an Idempotency-Key UUID.

EndpointAuthRate limit
POST /v1/gate_sessionsSecret key10 / min / key
GET /v1/gate_sessions/{id}Secret key60 / min
POST /v1/gate_sessions/{id}/cancelSecret key30 / min
POST /v1/embed/bootstrapPublishable key30 / min / IP

Errors use a single envelope: { statusCode, message, error }, where message is a string for a single error or an array (one entry per failed field) on validation failures, and error is a short class name (e.g. Forbidden) you can branch on. Status mapping: 400/422 invalid request, 401 missing/malformed credential, 403 rejected credential (revoked key, origin not in allowed_domains, mode mismatch, session of another partner, kyc_package_not_trusted), 404 not found / out of scope, 409 state conflict (e.g. cancelling a terminal session), 429 rate limited. See Environments & modes.

See also

On this page