Webhooks

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.

Subscribe

HTTP request
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"]
}

Delivery headers

Signature headers
CG-Event: order.shipped
CG-Id: evt_12345
CG-Signature: t=1731456000,v1=hex_signature

Use CG-Signature to verify payload integrity before processing.

Verify signature

Create an HMAC SHA256 with your webhook secret over timestamp and the raw request body. Compare digests with a constant time check.

Node example
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);
}

Event payload

Sample payload
{
  "id": "evt_12345",
  "type": "order.shipped",
  "created": 1731456000,
  "data": {
    "order_id": "ord_98765",
    "carrier": "CGX",
    "tracking": "CGX123456"
  }
}

Idempotency

Use CG-Id to dedupe deliveries. Store processed ids for at least 7 days.

Retries

We retry with backoff when your endpoint returns 429 or any 5xx. Return a 2xx to acknowledge and stop retries.

Test mode

Send test events from Settings and Developer. Use a tunnel for localhost endpoints.

Back to API docs