Real-time HTTP notifications.
Tenant workspace → Integration → Webhooks: add a URL, pick the events (or * for all), and keep the generated secret — unsigned webhooks are never sent.
POST your-url
Content-Type: application/json
{ "event": "order.created", "data": { … }, "tenant_id": 42 }
| Event | When | Payload highlights |
|---|---|---|
order.created | An order is placed from the configurator | Full 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.paid | Payment confirmed (Stripe) | Order row |
order.updated | Status change (production, shipping) | id, status |
design.saved | A visitor saves a design without ordering | config_id, share_token, guest_email (lead), product ids/SKU, summary, export_url, bat_url |
config.saved | A logged-in customer saves a design | config_id, user_id |
When adding a webhook (Tenant workspace → Integration), choose its payload mode:
| Mode | Content | Use case |
|---|---|---|
light (default) | Summaries (texts, named zones with Pantone refs, sizes) + export_url/bat_url links | Most integrations — pull heavy media on demand |
full | The complete raw feed: full config JSON, production pattern SVG inline, preview images (base64) — everything needed to build your own proof (BAT) without any callback | ERP/production integrations. ⚠️ Payloads can weigh several MB per order |
Every delivery is signed with HMAC-SHA256 of the raw body using your webhook secret:
| Header | Content |
|---|---|
X-PrintWearAI-Event | Event name (e.g. order.created) |
X-PrintWearAI-Signature | hex(hmac_sha256(raw_body, secret)) |
X-Flare-Event / X-Flare-Signature | Legacy 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'] || ''));
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.