Skip to content

Webhooks

PrintStudio both sends webhooks (outbound to your systems) and receives them (inbound from Stripe and OpenClaw).

Register an endpoint to receive events when orders and jobs change state.

Terminal window
curl -X POST http://localhost:8787/api/webhooks/endpoints \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"url": "https://your-system.example.com/hooks/printstudio",
"events": ["order.created", "order.shipped", "job.failed"],
"secret": "your-signing-secret"
}'
EventDescription
order.createdNew order placed
order.paidPayment confirmed
order.printingProduction started
order.readyAll jobs complete
order.shippedTracking assigned
order.cancelledOrder cancelled
job.failedJob failed (includes error)
job.completedIndividual job completed
inventory.lowMaterial below reorder point
printer.offlinePrinter stopped responding

All outbound webhooks share a common envelope:

{
"id": "evt-uuid",
"event": "order.shipped",
"timestamp": "2024-01-15T14:30:00Z",
"data": {
"orderId": "ord-abc123",
"trackingNumber": "1Z999AA10123456784",
"carrier": "UPS",
"estimatedDelivery": "2024-01-17"
}
}

Each delivery includes an X-PrintStudio-Signature header — an HMAC-SHA256 of the raw request body signed with your endpoint’s secret:

import { createHmac } from "crypto";
function verifySignature(body: string, signature: string, secret: string): boolean {
const expected = createHmac("sha256", secret)
.update(body)
.digest("hex");
return `sha256=${expected}` === signature;
}

Failed deliveries (non-2xx response or timeout) are retried with exponential backoff: 1 min, 5 min, 25 min, 2 h, 10 h. After 5 failures the endpoint is automatically disabled and the operator is notified.

Stripe payment events are received at POST /webhooks/stripe. The endpoint validates the Stripe signature using STRIPE_WEBHOOK_SECRET.

Handled events:

Stripe eventAction
checkout.session.completedMark order as paid, create jobs
payment_intent.payment_failedMark order payment failed
charge.refundedMark order refunded

Use the Stripe CLI for local testing:

Terminal window
stripe listen --forward-to localhost:8787/webhooks/stripe

OpenClaw agent events are received at POST /webhooks/openclaw. This handles inbound commands from the AI skills (e.g., an operator asking the bot to pause a print):

{
"skill": "pause-print",
"params": { "jobId": "job-uuid" },
"userId": "whatsapp:+15551234567"
}