Webhooks
HIOBuy pushes fulfillment lifecycle events to your HTTPS endpoint when an app runs in warehouse fulfillment mode. Configure endpoints in the Developer Portal → Webhooks . Delivery is asynchronous; Public API responses never wait on your webhook server.
Prerequisite: Channel Auth → fulfillment mode = HIOBuy warehouse. Self-fulfillment apps can view the portal intro but cannot create or enable endpoints.
Overview {#overview}
| Item | Value |
|---|---|
| Transport | POST JSON to your endpoint URL |
| Timeout | 10 seconds |
| Success | HTTP 2xx |
| Signing secret | whsec_… (shown once at create / rotate) |
| Signature header | HioBuy-Signature |
| Event id header | HioBuy-Event-Id |
| User-Agent | HioBuy-Webhooks/1.0 |
| Retries | Up to 5 attempts: immediate, then 1m / 5m / 30m / 2h |
| Test events | Portal Send test → livemode: false, id prefix evt_test_ |
Registration, secret rotation, delivery history, and manual retry are portal-only (session auth). There is no Public /v1/webhooks/* management API in v1.
Event catalog {#events}
Subscribe per endpoint. At least one event is required.
| Category | Event type | When it fires |
|---|---|---|
| Procurement | procurement.failed | Warehouse procurement failed |
| Procurement | procurement.out_of_stock | SKU unavailable during procurement |
| Warehouse | package.received | Domestic parcel received at warehouse |
| Warehouse | package.exception | Inbound package exception (exception_type in data) |
| Consolidation | consolidation.completed | Packages consolidated for outbound |
| Shipping | shipment.created | International shipment created |
| Shipping | shipment.dispatched | Shipment handed to carrier |
| Shipping | shipment.delivered | Delivered to recipient |
| Shipping | shipment.exception | Outbound exception (exception_type in data) |
| Account | balance.low | Warehouse wallet below threshold |
Live warehouse→developer push is rolled out progressively; use Send test in the portal to validate your receiver today.
Public envelope {#envelope}
Every delivery body is a JSON object:
{
"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"
}
}| Field | Type | Description |
|---|---|---|
id | string | Public event id (evt_… live, evt_test_… test) |
type | string | Event type from the catalog |
created_at | string | ISO-8601 timestamp |
livemode | boolean | false for portal test events |
app_id | string | Your app id |
data | object | Event-specific payload (no warehouse-internal fields) |
Example data shapes {#data-shapes}
Shapes below match portal test samples; live payloads follow the same keys with production ids.
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
}HTTP delivery {#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…- Endpoint URL must be HTTPS in production. Non-production environments may use
http://localhost/ tunnel hosts for local debugging. - Respond with
2xxwithin 10s. Any other status or network error schedules a retry (until attempts are exhausted). - Treat deliveries as at-least-once. Deduplicate on
id(and optionallyHioBuy-Event-Id).
Signature verification {#signature}
- Read
HioBuy-Signature(t=<unix_seconds>,v1=<hex_hmac>). - Build the signed payload:
"{t}.{raw_body}"whereraw_bodyis the exact request body bytes (UTF-8 JSON string as received). - Compute
HMAC-SHA256(secret, signed_payload)and hex-encode the digest. - Compare to
v1with a constant-time equality check. - Reject if
|now - t|is too large (recommended tolerance: 5 minutes) to limit replay.
Node.js example
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);
}Store the
whsec_…secret only on your server. Portal lists show a masked hint (whsec_••••…+ last 6 characters). Rotate anytime; update your server before the next delivery.
Retries & delivery status {#retries}
| Attempt | Delay after previous failure |
|---|---|
| 1 | Immediate (queued) |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
After the final failed attempt the delivery is marked failed. You can Retry now from the portal delivery detail for a manual re-queue.
Delivery statuses: pending · success · retrying · failed.
Portal workflow {#portal}
- Set the app to warehouse fulfillment under Channel Auth .
- Open Webhooks → Add endpoint.
- Enter HTTPS URL, optional description, and subscribe to events.
- Copy the signing secret when shown (once).
- Use Send test event and inspect recent deliveries / attempt history.
- Rotate secret, disable, or delete when needed.
Limits & retention {#limits}
| Limit | Value |
|---|---|
| Payload size | ≤ 64 KB |
| Attempt response body stored | ≤ 4 KB |
| Event / delivery retention | ~30 days |
| Attempt retention | ~14 days |
Related
- Fulfillment setup — warehouse mode
- Fulfillment API — international shipping routes
- Authentication — API keys (separate from webhook secrets)
Get Support
Need integration help? Contact Developer Support at support@hiobuy.com · Response within 1–2 business days