🔔 Webhooks

Real-time HTTP notifications.

Configuration

Tenant workspace → Integration → Webhooks: add a URL, pick the events (or * for all), and keep the generated secret — unsigned webhooks are never sent.

Payload

POST your-url
Content-Type: application/json

{ "event": "order.created", "data": { … }, "tenant_id": 42 }

Events

EventWhenPayload highlights
order.createdAn order is placed from the configuratorFull export: order, items with per-item customization summary (texts, numbers, colors), sizes breakdown, buyer, bat_url (print proof) and export_url (server-side JSON)
order.paidPayment confirmed (Stripe)Order row
order.updatedStatus change (production, shipping)id, status
design.savedA visitor saves a design without orderingconfig_id, share_token, guest_email (lead), product ids/SKU, summary, export_url, bat_url
config.savedA logged-in customer saves a designconfig_id, user_id

Payload modes (per webhook)

When adding a webhook (Tenant workspace → Integration), choose its payload mode:

ModeContentUse case
light (default)Summaries (texts, named zones with Pantone refs, sizes) + export_url/bat_url linksMost integrations — pull heavy media on demand
fullThe complete raw feed: full config JSON, production pattern SVG inline, preview images (base64) — everything needed to build your own proof (BAT) without any callbackERP/production integrations. ⚠️ Payloads can weigh several MB per order

Signature verification

Every delivery is signed with HMAC-SHA256 of the raw body using your webhook secret:

HeaderContent
X-PrintWearAI-EventEvent name (e.g. order.created)
X-PrintWearAI-Signaturehex(hmac_sha256(raw_body, secret))
X-Flare-Event / X-Flare-SignatureLegacy aliases (same values) — still sent for older integrations, will be removed. Use the X-PrintWearAI-* names in new code.
// Node.js
const crypto = require('crypto');
const expected = crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected),
                                  Buffer.from(req.headers['x-printwearai-signature'] || ''));

Retries

Respond with a 2xx within 4 seconds. Any failure (timeout, 4xx/5xx) is retried automatically with exponential backoff — about 5 min, 20 min, 80 min, 5 h, then ~21 h. After 5 failed attempts the delivery is marked dead and will not be retried. Make your handler idempotent: use event + payload identifiers to deduplicate.