Listen for 0Bit webhooks
Receive signed 0Bit backend events and route them through an idempotent worker.
0Gate webhooks are signed and documented. Other product webhook behavior should be followed from that product's API Reference and only used when the product surface is enabled for the account. Browser callbacks are useful for UX, but your backend should fulfill, close, or reconcile product state from verified webhook events.
Return quickly, work asynchronously
Your webhook endpoint should verify, record, enqueue, and return a 2xx response. Do expensive fulfillment, notifications, and reconciliation in workers after the event is safely recorded.
Delivery path
Product scope
| Surface | Use this intake for | Keep out of public handlers |
|---|---|---|
| 0Gate | Hosted sessions, rail events, quote/customer events, delivery records, and synthetic test events. | Provider, treasury, reserve, and internal settlement details. |
| 0Base | Enabled checkout, payment-intent, delivery, replay, and signed-test flows. | Live money-movement claims unless product review has approved them. |
| 0Pools | Entitled quote, trade, and settlement-adjacent events for approved partners. | Liquidity-engine, route, reserve, venue, and market-maker internals. |
| 0Link | Only review-approved routing boundary events. | Internal order router, desk, venue, or execution strategy details. |
Headers to support
| Header | Purpose |
|---|---|
| Product signature header | HMAC signature over the timestamp and raw body. 0Gate uses Gate-Signature; use the API reference for other product surfaces. |
| Timestamp header or signature timestamp | Timestamp used for replay-window checks. |
| Event id | Stable dedupe key for the event. |
| Event type | Event type for routing before deep payload handling. |
Content-Type | JSON event body. |
Handler pattern
async function obitWebhookEndpoint(request: Request) {
const rawBody = await request.text();
const signature = request.headers.get(signatureHeaderForProduct()) ?? '';
const event = verifyObitWebhookSignature({
rawBody,
signature,
secret: webhookSecretForProduct(),
});
const inserted = await eventLog.insertOnce({
eventId: event.id,
type: event.type,
receivedAt: new Date(),
rawBody,
});
if (inserted) {
await eventQueue.enqueue({ eventId: event.id });
}
return new Response(null, { status: 200 });
}Processing rules
| Rule | Reason |
|---|---|
| Preserve the raw body until verification completes. | JSON re-serialization changes the signed bytes. |
| Dedupe on event id. | Webhook delivery is at least once. |
| Route unknown events to a safe ignored state. | New event types should not break your endpoint. |
| Fulfill from terminal backend events only. | Client callbacks and return URLs can be lost or replayed. |
| Store request metadata with secrets redacted. | Support needs diagnostics without leaking credentials. |