Skip to main content

Webhooks reference

Fabrixa webhooks reference — order state events, signed payloads, real-time integration
DEVELOPERS — WEBHOOKS REFERENCE

Order lifecycle events, signed and retry-safe.

Webhooks fire on every order state transition: received, printed, dispatched, failed. JSON over HTTPS, HMAC-SHA256 signed for verification, retry queue with exponential backoff up to 24 hours. Event reference, signature verification code samples, and retry / dead-letter policy below.

HMAC-SHA256 SIGNED · AT-LEAST-ONCE · 24h RETRY · DEAD-LETTER QUEUE

EVENT TYPES

Five order lifecycle events.

Subscribe to any subset on the PUT /v1/account/webhook endpoint. Most integrations subscribe to all five.

Event Fires when Typical action
order.receivedFabrixa accepted the order and assigned an order_id. Ack within seconds of POST.Update internal order status to "in production"; surface to end customer.
order.printedReactive print step complete. Garment moves to cut-and-sew. Mid-production milestone.Optional — some teams use this for end-customer "your order is being made" emails.
order.dispatchedQuality-checked, packaged, handed to carrier. Tracking number issued.Update order status to "shipped"; trigger end-customer shipping notification with tracking URL.
order.deliveredCarrier confirmed delivery to recipient address.Trigger post-purchase flows: review request, related-product upsell, etc.
order.failedOrder can’t complete — artwork unreachable, recipient address invalid, fabric out of stock for an extended period.Open ticket / notify ops. Payload includes error.code for switch-on logic.
PAYLOAD SHAPE

Same envelope, event-specific data.

Common envelope (event, order_id, order_ref, timestamp) plus an event-specific data object. Consume the envelope first; switch on event for the data shape.

order.dispatched
# order.dispatched payload — POST to your webhook URL

POST /your-webhook-endpoint
Content-Type: application/json
X-Fabrixa-Event: order.dispatched
X-Fabrixa-Signature: t=1715173928,v1=ab3c4...
X-Fabrixa-Delivery-Id: del_94kQ7r2L

{
  "event":        "order.dispatched",
  "order_id":     "ord_8e6f4b2a",
  "order_ref":    "shopify-1042",
  "timestamp":    "2026-05-15T11:32:08Z",
  "production_hub": "PT",
  "data": {
    "tracking": {
      "carrier":         "DHL",
      "tracking_number": "JJD0123456789",
      "tracking_url":    "https://dhl.com/track/JJD0123456789",
      "estimated_delivery": "2026-05-19"
    },
    "recipient": {
      "name":    "Lena Costa",
      "city":    "Porto",
      "country": "PT"
    }
  }
}
SIGNATURE VERIFICATION

HMAC-SHA256 over (timestamp + raw body).

Verify the signature before processing. Use the raw request body — not a re-serialised JSON object — or the HMAC will mismatch. The signing secret is issued once when you set up the webhook URL; rotate via dashboard.

verify-signature.js
// Node.js / Express example
const crypto = require("crypto");

app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  const signature = req.headers["x-fabrixa-signature"];
  const [tPart, v1Part] = signature.split(",");
  const timestamp = tPart.split("=")[1];
  const received  = v1Part.split("=")[1];

  // Reject events older than 5 minutes (replay protection)
  if (Math.abs(Date.now() / 1000 - timestamp) > 300) return res.status(400).end();

  const payload  = `${timestamp}.${req.body.toString()}`;
  const expected = crypto
    .createHmac("sha256", process.env.FABRIXA_WEBHOOK_SECRET)
    .update(payload)
    .digest("hex");

  if (!crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected))) {
    return res.status(401).end();
  }

  // Signature valid — process the event
  const event = JSON.parse(req.body);
  handleEvent(event);
  res.status(200).end();
});

Equivalent samples for Python (Flask), PHP, Ruby, and Go are in the Postman collection’s scripts folder. timingSafeEqual matters — don’t use string equality, it’s vulnerable to timing attacks.

RETRY POLICY

Exponential backoff up to 24 hours.

Webhook delivery is at-least-once. If your endpoint returns 5xx or times out (10s timeout), we retry on an exponential backoff schedule for up to 24 hours. After 24h of failure, the event lands in a dead-letter queue you can replay manually.

IMMEDIATE

Initial delivery + retry 1

First delivery on event. If 5xx or timeout, retry 30 seconds later.

BACKOFF

Retries 2-8, exponential

60s → 5min → 30min → 2h → 6h → 12h → 24h. Each retry waits longer.

DEAD-LETTER

After 24h of failure

Event moved to dead-letter queue. Replay manually via dashboard or POST /v1/webhooks/replay/:delivery_id.

ORDER.FAILED EVENT

Structured error reasons for switch-on logic.

The most operationally important event. Payload includes a stable error.code string — safe to switch on for automated routing, ticket creation, or end-customer messaging.

order.failed
{
  "event":     "order.failed",
  "order_id":  "ord_8e6f4b2a",
  "order_ref": "shopify-1042",
  "timestamp": "2026-05-13T09:14:22Z",
  "data": {
    "error": {
      "code":    "artwork_unreachable",
      "message": "GET on artwork_url failed (timeout 30s) after 3 attempts",
      "retryable": true,
      "context": {
        "artwork_url": "https://cdn.yourbrand.com/art/drop-001.png"
      }
    }
  }
}

# Common error.code values:
#   artwork_unreachable      — your artwork URL didn't respond
#   artwork_invalid_format   — couldn't parse the file (try PNG / vector PDF)
#   artwork_resolution_low   — DPI too low for the chosen product
#   address_invalid          — recipient address didn't validate
#   fabric_unavailable       — fabric base out of stock for >7 days
#   payment_method_failed    — billing on file declined
#   compliance_flag          — order flagged by compliance review
TESTING

Trigger sample events without real orders.

POST /v1/webhooks/test sends a synthetic event of any type to your registered webhook URL. Useful for testing your handler before placing real orders, or for verifying a new endpoint after a deploy.

Sandbox webhooks deliver to your sandbox URL. Use a tunnelling tool (ngrok, Cloudflare Tunnel) to point sandbox webhooks at localhost during development.

POST /v1/webhooks/test
curl -X POST $BASE_URL/v1/webhooks/test \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "order.dispatched",
    "sample_order_id": "sample"
  }'

# 200 OK
{
  "delivery_id": "del_test_94kQ",
  "posted_to":   "https://your-tunnel.ngrok.io/webhook",
  "status":      "queued"
}
Set up Fabrixa webhooks — real-time order events for your platform
REGISTER YOUR WEBHOOK

Set the URL once. We’ll handle delivery.

One webhook URL per account, all event types fire to it. Filter on the event field in your handler. Set up via the integration guide.

Cart (0 items)

Create your account