IoneShop Developers

Webhooks

Webhooks push domain events to your HTTPS endpoint so you do not poll.

Subscribe

POST /v1/webhooks
Authorization: Bearer isk_live_...
Idempotency-Key: wh_create_orders_01
Content-Type: application/json

{
  "url": "https://integrations.example.com/hooks/ioneshop",
  "events": ["order.created", "order.paid", "inventory.changed"],
  "description": "ERP bridge"
}

Response includes id, status, and a signing secret (shown once) — or the secret is managed in BO and never re-displayed.

Delivery request

POST /hooks/ioneshop HTTP/1.1
Host: integrations.example.com
Content-Type: application/json
X-IoneShop-Signature: <hex hmac sha256>
X-IoneShop-Timestamp: 1735689600
X-IoneShop-Delivery-Id: del_01J...
X-IoneShop-Event: order.paid

Body (canonical signed form):

{
  "event": "order.paid",
  "timestamp": "2026-08-01T12:00:00Z",
  "payload": {
    "id": "ord_01J...",
    "status": "paid",
    "total": { "amount": 4999, "currency": "EUR" }
  }
}

Header branding note

Public contract headers use the X-IoneShop-* prefix. During platform cutover, deliveries may also send legacy aliases (x-ecom-signature, x-ecom-timestamp, x-ecom-delivery-id). Verifiers should accept either until Sunset is announced in the changelog.

Security

HMAC verification (required in production)

Canonical algorithm (only): HMAC-SHA256 over the exact raw HTTP request body (UTF-8 bytes as received), hex-encoded. Do not re-serialize JSON before verify.

  1. Read raw body bytes (disable JSON body parsers that consume the stream first)
  2. Compute hex = HMAC_SHA256(webhook_secret, raw_body)
  3. Compare with X-IoneShop-Signature using a constant-time compare
  4. Reject if X-IoneShop-Timestamp skew > 5 minutes (replay window)
  5. Persist X-IoneShop-Delivery-Id and ignore duplicates

Node.js sketch:

import { createHmac, timingSafeEqual } from "node:crypto";

function verify(secret, rawBody, signatureHex) {
  const expected = createHmac("sha256", secret).update(rawBody, "utf8").digest("hex");
  const a = Buffer.from(expected, "hex");
  const b = Buffer.from(signatureHex, "hex");
  return a.length === b.length && timingSafeEqual(a, b);
}

Endpoint requirements

  • HTTPS only (TLS 1.2+; 1.3 preferred)
  • Respond 2xx within 10 seconds
  • Do heavy work async after ack
  • Optional Enterprise: IP allowlist for webhook egress

Retry policy

On non-2xx or timeout:

AttemptDelay after failure
11 minute
25 minutes
330 minutes
42 hours
524 hours

After exhausting retries → dead letter (dead). Merchant BO can replay. Enterprise may configure custom schedules.

Testing

  • BO Send test event (when available in Merchant BO)
  • Sandbox signed deliveries
  • Local: forward with a tunnel; never disable signature verify in shared code paths
  • Unit fixtures: Webhook HMAC test vectors

Event catalog

See Events.