Skip to content

Developers

The OnBio API and webhooks

Read the sales, contacts and invoices of your store from your own software and get every change as soon as it happens.

Base URL
https://api.onbio.es/public/v1
Authentication
Send the key in the Authorization: Bearer ob_live_… header or in X-API-Key. Keys are created in Integrations in the panel, with read or read and write permission.
Quota
120 requests per minute per store, adding up all its keys, Zapier and Make included. Beyond that, the answer is 429 with the Retry-After header.

Webhook events

Each delivery is a POST with the event in JSON. If the destination does not answer with 2xx within 10 s, it is retried up to 8 times with waits growing from 10 s to 3600 s; after 10 failures in a row the webhook is turned off.

EventResourceWhen it arrives
sale.createdsaleA buyer has paid an order.
refund.createdrefundA sale has been refunded, in full or in part.
subscription.createdsubscriptionA buyer has started a subscription.
subscription.cancelledsubscriptionA subscription has ended.
lead.createdleadA visitor has downloaded a lead magnet.
entitlement.grantedentitlementA buyer has received access to a product or got it back.
entitlement.revokedentitlementAccess to a product has been suspended or withdrawn.
invoice.createdinvoiceAn invoice of the creator has been issued.

Verify the signature

Each delivery carries X-Onbio-Timestamp and X-Onbio-Signature, the hexadecimal HMAC-SHA256 of “timestamp.body” with the whsec_ secret of the webhook. Compute the signature over the body exactly as it arrives, before parsing it as JSON. A timestamp more than 300 s away from your clock is rejected even if the signature matches.

Node.js
import crypto from "node:crypto";

export function verifyOnbioSignature(rawBody, headers, secret, nowSeconds = Math.floor(Date.now() / 1000)) {
  const timestamp = headers["x-onbio-timestamp"];
  const signature = headers["x-onbio-signature"];
  if (!timestamp || !signature || Math.abs(nowSeconds - Number(timestamp)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
  return signature.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

API reference

Every route of /public/v1 with its parameters, responses and examples, read from the OpenAPI document the API publishes.