Setting up webhooks
In Settings → Integrations → Developers → Order notifications you can add several channels at once — e.g. Home Assistant and Discord together. Each channel has its own request body format:
- 3D Print Pricing / HA — a generic JSON payload with an HMAC signature, see the section below.
- Discord / Slack — their native incoming webhook format (no signature — the whole secret is already baked into the URL that Discord/Slack issues).
Add a channel, paste the receiver URL, enable it — 3D Print Pricing will show the secret once (only for the “3D Print Pricing / HA” format), copy it right away. Each channel’s “Send test event” button sends a synthetic webhook.test event right now, without waiting for a real order.
order.created / order.status_changed events
3D Print Pricing sends a POST with a JSON body to your URL when an order is created and on every workflow_status change. Delivery is best-effort (no retries on error in the MVP), so don’t rely on webhooks alone — use GET /print-jobs to reconcile.
POST <your URL>
Content-Type: application/json
X-3DP-Event: order.status_changed
X-3DP-Signature: sha256=<hex signature of the request body>
{
"event": "order.status_changed",
"occurred_at": "2026-08-27T18:32:10.000Z",
"data": {
"id": "b6b6c8b0-...",
"model_name": "Кронштейн",
"quantity_pieces": 4,
"material_name": "PETG",
"color_hex": "#000000",
"material_grams": 86.0,
"print_hours": 3.5,
"due_date": "2026-09-01",
"order_notes": "",
"workflow_status": "assigned",
"printer_id": null,
"printer_name": null
}
}Signature verification (pseudocode)
signature_header = "sha256=" + hex(HMAC_SHA256(webhook_secret, raw_request_body))
if signature_header != request.headers["X-3DP-Signature"]:
reject() # payload was tampered with, or the secret doesn't matchMore events (opt-in)
Each channel picks the events it wants (checkboxes in the channel card, or the events array in the API). Existing channels keep receiving only order.created and order.status_changed; the events below are opt-in. The envelope and HMAC signature are the same for all events.
printer.print_finished/printer.print_failed— a printer finished a print / reported an error during a printfilament.low_stock— a spool dropped to its low-stock threshold (set on the filament card)lead.created— a new request arrived from your masters-catalog profileinvoice.paid— an invoice was paid online (needs_review = a duplicate or stale-amount payment)
// printer.print_finished / printer.print_failed
{ "event": "printer.print_finished", "occurred_at": "2026-10-01T12:00:00+00:00",
"data": { "printer_id": "9d1c...", "printer_name": "Bambu P1S", "filename": "bracket.3mf", "at": "2026-10-01T12:00:00+00:00" } }
// filament.low_stock
{ "event": "filament.low_stock", "occurred_at": "...",
"data": { "filament_id": "5a2e...", "name": "PETG black", "remaining_grams": 180.0, "threshold_grams": 200.0 } }
// lead.created
{ "event": "lead.created", "occurred_at": "...",
"data": { "lead_id": "c0f4...", "description": "Need 20 brackets", "contact": "@client", "client_email": "client@example.com",
"budget": "up to 3000", "deadline": "next week", "has_file": true, "created_at": "..." } }
// invoice.paid
{ "event": "invoice.paid", "occurred_at": "...",
"data": { "document_id": "7b3a...", "number": "INV-12", "amount": 4500.0, "paid_at": "...",
"order_ids": ["b6b6c8b0-..."], "needs_review": false } }API: POST /webhook-subscriptions and PUT /webhook-subscriptions/{id} accept "events": ["order.created", "printer.print_finished", ...] (at least one; unknown names are rejected with 422).
Managing subscriptions via API
The same thing as the Settings → Integrations → Developers card, but programmatically — e.g. so n8n/a script can set up a channel on first run without going into the web UI. Up to 10 channels per account.
/webhook-subscriptionsSubscription list
All channels on the account (without secrets — those are returned only once, at creation/recreation).
/webhook-subscriptionsCreate subscription
The secret (for the "3D Print Pricing / HA" format) is returned in the response once — save it right away.
/webhook-subscriptions/{id}/testSend a test event
Sends a synthetic webhook.test event to an existing subscription's URL — doesn't touch real orders.
/webhook-subscriptions/{id}/deliveriesDelivery history
The last 20 delivery attempts for this subscription (status, error, time).
/webhook-subscriptions/{id}Delete subscription
Uses the same subscription id as the field above.