Desarrolladores
La API y los webhooks de OnBio
Lee las ventas, los contactos y las facturas de tu tienda desde tus programas y recibe cada cambio en cuanto ocurre.
- Dirección base
https://api.onbio.es/public/v1- Autenticación
- Envía la clave en la cabecera Authorization: Bearer ob_live_… o en X-API-Key. Las claves se crean en Integraciones del panel, con permiso de lectura o de lectura y escritura.
- Cuota
- 120 peticiones por minuto por tienda, sumadas todas sus claves, Zapier y Make incluidos. Al pasarla, la respuesta es 429 con la cabecera Retry-After.
Eventos de los webhooks
Cada entrega es un POST con el evento en JSON. Si el destino no responde con 2xx en 10 s, se reintenta hasta 8 veces con esperas crecientes de 10 s hasta 3600 s; tras 10 fallos seguidos el webhook se desactiva.
| Evento | Recurso | Cuándo llega |
|---|---|---|
sale.created | sale | Un comprador ha pagado un pedido. |
refund.created | refund | Se ha reembolsado una venta, entera o en parte. |
subscription.created | subscription | Un comprador ha empezado una suscripción. |
subscription.cancelled | subscription | Una suscripción ha terminado. |
lead.created | lead | Un visitante ha descargado un lead magnet. |
entitlement.granted | entitlement | Un comprador ha recibido acceso a un producto o lo ha recuperado. |
entitlement.revoked | entitlement | Se ha suspendido o retirado un acceso a un producto. |
invoice.created | invoice | Se ha emitido una factura del creador. |
Verificar la firma
Cada entrega lleva X-Onbio-Timestamp y X-Onbio-Signature, que es el HMAC-SHA256 en hexadecimal de «marca.cuerpo» con el secreto whsec_ del webhook. Calcula la firma sobre el cuerpo tal como llega, antes de convertirlo a JSON. Una marca con más de 300 s de diferencia con tu reloj se rechaza aunque la firma coincida.
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));
}Referencia de la API
Todas las rutas de /public/v1 con sus parámetros, respuestas y ejemplos, leídas del documento OpenAPI que publica la API.