Webhooks
Cuando la app está en modo HIOBuy warehouse fulfillment, HIOBuy envía eventos del ciclo de vida de fulfillment a tu endpoint HTTPS. Configúralos en Developer Portal → Webhooks . La entrega es asíncrona; las respuestas de la Public API no esperan a tu servidor webhook.
Requisito: Autorización de canal → modo de fulfillment = HIOBuy warehouse. En modo self solo ves la intro; no puedes crear/activar endpoints.
Resumen {#overview}
| Elemento | Valor |
|---|---|
| Transporte | POST JSON a tu endpoint |
| Tiempo de espera | 10 segundos |
| Éxito | HTTP 2xx |
| Secreto de firma | whsec_… (se muestra una sola vez al crear / rotar) |
| Cabecera de firma | HioBuy-Signature |
| Cabecera de ID de evento | HioBuy-Event-Id |
| User-Agent | HioBuy-Webhooks/1.0 |
| Reintentos | hasta 5 intentos: inmediato, luego 1m / 5m / 30m / 2h |
| Eventos de prueba | Portal Send test → livemode: false, prefijo id evt_test_ |
Registro, rotación de secreto, historial y retry manual son solo portal (auth de sesión). No hay API Public /v1/webhooks/* en v1.
Catálogo de eventos {#events}
Suscríbete por endpoint. Se requiere al menos un evento.
| Categoría | Tipo de evento | Cuándo |
|---|---|---|
| Procurement | procurement.failed | Falló el procurement de almacén |
| Procurement | procurement.out_of_stock | SKU no disponible en procurement |
| Almacén | package.received | Paquete doméstico recibido en almacén |
| Almacén | package.exception | Excepción de entrada (data.exception_type) |
| Consolidación | consolidation.completed | Consolidación completada |
| Envío | shipment.created | Envío internacional creado |
| Envío | shipment.dispatched | Entregado al transportista |
| Envío | shipment.delivered | Entregado al destinatario |
| Envío | shipment.exception | Excepción de salida (data.exception_type) |
| Cuenta | balance.low | Saldo del almacén bajo el umbral |
El push live warehouse→developer se activa de forma gradual; valida tu receptor con Send test hoy.
Envelope público {#envelope}
Cada cuerpo de entrega es JSON:
{
"id": "evt_01HXYZ…",
"type": "package.received",
"created_at": "2026-08-16T04:00:00.000Z",
"livemode": true,
"app_id": "app_…",
"data": {
"package_id": "pkg_…",
"order_id": "ord_…",
"status": "received"
}
}| Campo | Tipo | Descripción |
|---|---|---|
id | string | ID público del evento (evt_… live, evt_test_… test) |
type | string | Tipo del catálogo |
created_at | string | Marca de tiempo ISO-8601 |
livemode | boolean | false en pruebas del portal |
app_id | string | ID de tu app |
data | object | Payload sin campos internos de almacén |
Ejemplos de data {#data-shapes}
Igual que las muestras de prueba del portal; live usa las mismas claves.
procurement.failed
{
"order_id": "ord_…",
"status": "failed",
"reason": "supplier_rejected"
}package.exception
{
"package_id": "pkg_…",
"order_id": "ord_…",
"status": "exception",
"exception_type": "DAMAGED"
}shipment.dispatched
{
"shipment_id": "shp_…",
"tracking_number": "…",
"status": "dispatched"
}balance.low
{
"available_amount": 12.5,
"currency": "USD",
"threshold": 50
}Entrega HTTP {#delivery}
POST /your/webhook-path HTTP/1.1
Host: your-server.example
Content-Type: application/json
User-Agent: HioBuy-Webhooks/1.0
HioBuy-Event-Id: evt_01HXYZ…
HioBuy-Signature: t=1723780800,v1=abcdef0123456789…- En producción la URL debe ser HTTPS. Fuera de producción se permiten
http://localhost/ túneles. - Responde
2xxen 10 s. Cualquier otro caso programa reintento. - Entrega at-least-once. Deduplica con
id(y opcionalmenteHioBuy-Event-Id).
Verificación de firma {#signature}
- Lee
HioBuy-Signature(t=<unix_seconds>,v1=<hex_hmac>). - Construye
"{t}.{raw_body}"donderaw_bodyes el cuerpo exacto recibido (JSON UTF-8). - Calcula
HMAC-SHA256(secret, signed_payload)en hex. - Compara con
v1en tiempo constante. - Rechaza si
|now - t|es demasiado grande (tolerancia recomendada: 5 minutos).
Node.js ejemplo
import crypto from "node:crypto";
function verifyHioBuySignature(rawBody, signatureHeader, secret, toleranceSec = 300) {
const match = /^t=(\d+),v1=([0-9a-f]+)$/i.exec(signatureHeader || "");
if (!match) return false;
const t = Number(match[1]);
const expected = match[2].toLowerCase();
if (!Number.isFinite(t)) return false;
if (Math.abs(Math.floor(Date.now() / 1000) - t) > toleranceSec) return false;
const signed = `${t}.${rawBody}`;
const digest = crypto
.createHmac("sha256", secret)
.update(signed, "utf8")
.digest("hex");
const a = Buffer.from(digest, "utf8");
const b = Buffer.from(expected, "utf8");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Guarda
whsec_…solo en el servidor. El portal muestra máscara (últimos 6). Tras rotar, actualiza el servidor antes de la siguiente entrega.
Reintentos y estado {#retries}
| Intento | Retraso tras el fallo anterior |
|---|---|
| 1 | Inmediato (cola) |
| 2 | 1 minuto |
| 3 | 5 minutos |
| 4 | 30 minutos |
| 5 | 2 horas |
Tras el último fallo: failed. Puedes Retry now en el detalle del portal.
Estados: pending · success · retrying · failed.
Flujo en el portal {#portal}
- Pon la app en warehouse fulfillment en Channel Auth / setup.
- Abre Webhooks → Add endpoint.
- Introduce URL HTTPS, descripción opcional y eventos.
- Copia el secreto al mostrarlo (una sola vez).
- Usa Send test event e inspecciona deliveries / attempts.
- Rota el secreto, desactiva o elimina cuando haga falta.
Límites y retención {#limits}
| Límite | Valor |
|---|---|
| Payload | ≤ 64 KB |
| cuerpo de respuesta guardado en attempt | ≤ 4 KB |
| retención de events / deliveries | ~30 días |
| Attempt | ~14 días |
Relacionado
- Fulfillment setup — modo warehouse
- Fulfillment API — rutas de envío internacional
- Authentication — API keys (distintas del secreto webhook)
- Sandbox — los pedidos sandbox no empujan solos; usa Send test
Get Support
Need integration help? Contact Developer Support at support@hiobuy.com · Response within 1–2 business days