Subscribe
POST https://api.canvasguru.co/v1/webhooks/subscribe
Authorization: Bearer <API_KEY>
Content-Type: application/json
{
"url": "https://example.com/webhook",
"events": ["order.created","order.shipped","payout.paid"]
}
Subscribe to events and keep your systems in sync. Each delivery includes a signature header and an event payload. Retries use exponential backoff for up to 72 hours.
POST https://api.canvasguru.co/v1/webhooks/subscribe
Authorization: Bearer <API_KEY>
Content-Type: application/json
{
"url": "https://example.com/webhook",
"events": ["order.created","order.shipped","payout.paid"]
}
CG-Event: order.shipped
CG-Id: evt_12345
CG-Signature: t=1731456000,v1=hex_signature
Use CG-Signature to verify payload integrity before processing.
Create an HMAC SHA256 with your webhook secret over timestamp and the raw request body. Compare digests with a constant time check.
import crypto from "node:crypto";
export function verifySignature(secret, signatureHeader, rawBody){
const parts = Object.fromEntries(signatureHeader.split(",").map(kv=>{
const [k,v] = kv.split("="); return [k.trim(), (v||"").trim()];
}));
const expected = crypto.createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
const given = parts.v1 || "";
const a = Buffer.from(expected, "hex");
const b = Buffer.from(given, "hex");
return a.length===b.length && crypto.timingSafeEqual(a,b);
}
{
"id": "evt_12345",
"type": "order.shipped",
"created": 1731456000,
"data": {
"order_id": "ord_98765",
"carrier": "CGX",
"tracking": "CGX123456"
}
}
Use CG-Id to dedupe deliveries. Store processed ids for at least 7 days.
We retry with backoff when your endpoint returns 429 or any 5xx. Return a 2xx to acknowledge and stop retries.
Send test events from Settings and Developer. Use a tunnel for localhost endpoints.