0Bit Documentation

Authentication

How 0Bit uses publishable keys, secret keys, client secrets, webhook secrets, idempotency keys, and environment modes.

0Bit authentication is built around organization credentials and product entitlements. A credential identifies your organization. Product access then depends on entitlements and product-specific configuration such as allowed domains, webhook setup, KYC/KYB state, pool access rows, payout settings, and enabled corridors.

Credential types

CredentialShapeLivesUsed for
Publishable keypk_test_* / pk_live_*Browser/mobile where allowed.Bootstrapping hosted or embedded flows.
Secret keysk_test_* / sk_live_*Server only.Creating sessions, reading protected records, executing approved writes.
Client secretProduct/session scoped, for example gsec_...Browser-safe for one server-created object.Binding a hosted/embed flow to that object.
Webhook signing secretwhsec_*Server only.Verifying inbound webhook authenticity.
Idempotency keyYour generated stringServer generated and stored.Retrying one logical write safely.

The most common mistake

sk_* and whsec_* never belong in browser code, mobile bundles, logs, analytics tools, or customer-visible configuration. pk_* and client_secret are browser-safe only because their abilities are intentionally limited.

Request authentication

Use Bearer authentication for server calls. The route and object differ by product, but the boundary is the same: sk_* stays on the server, product access is checked after authentication, and state-changing writes should be idempotent.

curl -X POST https://gate-api-sandbox.0bit.app/v1/gate_sessions \
  -H "Authorization: Bearer $OBIT_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_123_create_gate_session" \
  -d '{"amount":"100.00","currency":"EUR","return_url":"https://app.partner.example/done"}'
ProductCommon server actionCredential pattern
0GateCreate/retrieve/cancel sessions, read capability and transaction state.Authorization: Bearer sk_*; pk_* for browser/embed bootstrap where allowed.
0PoolsList entitled pools, create quotes, execute quotes, read trade status.Authorization: Bearer sk_*; product entitlement and pool access must also pass.
0BaseCreate payment objects, read ledgers/reports, manage payment links or intents.Authorization: Bearer sk_*; product enablement and merchant settings must also pass.
0LinkReview routes, quote availability, fallback, and settlement-handling state.Authorization: Bearer sk_*; route/workflow access must also pass.
0Pools ScanRead public-safe indexed activity.Public-safe reads or approved access depending on endpoint.

The API should treat authentication and product access as separate checks:

CheckFailure meaning
Key formatThe key is missing, malformed, wrong type, or sent to the wrong route.
Key modeA test key is sent to live, or a live key is sent to sandbox.
Organization stateThe key is revoked or not attached to the expected organization.
EntitlementThe organization is not enabled for the product.
Product configThe organization is enabled but missing product-specific setup.
Object/corridorThe requested country, currency, asset, flow, pool, route, or object state is unavailable.

Publishable key boundary

Publishable keys are safe to expose because they cannot create privileged objects by themselves. They are mainly relevant to hosted or embedded flows such as 0Gate, where they are used alongside a server-created object secret such as a client_secret. Headless product surfaces like 0Pools may not need a browser publishable-key path at all.

import { GateRamp } from '@0bit/gate/browser';

const ramp = new GateRamp({
  publishableKey: process.env.NEXT_PUBLIC_OBIT_PUBLISHABLE_KEY!,
  clientSecret,
  environment: 'sandbox',
});

Publishable keys still matter. Protect them with allowed domains, correct environment mode, and product-specific bootstrap checks.

Secret key boundary

Secret keys are equivalent to server credentials. Use them only from trusted backend services.

DoDo not
Store in a secret manager.Put in frontend .env public variables.
Send as Authorization: Bearer sk_*.Put in a query string.
Rotate if exposed.Log raw headers or config dumps.
Scope use through backend routes.Let the browser decide amount, destination, or quote execution.

Webhook signature verification

Webhook verification requires the raw request body. Parse JSON only after verification.

import crypto from 'node:crypto';

export function verifyGateSignature(rawBody: string, header: string, secret: string) {
  const parts = Object.fromEntries(header.split(',').map((part) => part.split('=')));
  const timestamp = Number(parts.t);
  const signature = parts.v1;

  if (!Number.isFinite(timestamp) || !signature) return false;
  if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;

  const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex');

  return crypto.timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(signature, 'hex'));
}

After verification:

  1. Store the event id before applying business logic.
  2. If the event id already exists, return 2xx without repeating fulfillment.
  3. Join the event to your internal record using your reference and the 0Bit object id.
  4. Apply the state transition only if it is valid for your current record state.

Idempotency

Idempotency protects create and execute calls from duplicate effects during retries. Use one key for one logical operation.

OperationGood idempotency key
Create 0Gate session for order 123order_123_gate_session_create
Execute pool quote quote_abc oncequote_abc_execute_order_123
Create payment intent for invoice 456invoice_456_payment_intent_create

Do not reuse one key after changing amount, currency, user, quote id, destination, or product.

Key rotation

  1. Create the replacement key in the approved management surface.
  2. Deploy the new key to your secret manager or client config.
  3. Confirm traffic succeeds with the new key.
  4. Revoke the old key.
  5. Check logs for any old-key traffic and stale deployment targets.

Rotate webhook secrets with the same discipline. If your webhook worker supports dual-secret verification during a short migration window, record which secret matched and remove the old one after traffic moves.

Continue

On this page