Skip to content

Webhooks

Webhooks

Webhooks deliver real-time notifications when events occur in your workspace — for example when a QR code is scanned.

Create a Webhook

Terminal window
POST /v1/webhooks
{
"url": "https://example.com/webhooks/qr3",
"events": ["qr.scanned", "qr.created"],
"secret": "my-secret-key-min-16-chars"
}

Response

{
"id": "wh_abc123",
"url": "https://example.com/webhooks/qr3",
"events": ["qr.scanned", "qr.created"],
"is_active": true,
"secret": "my-secret-key-min-16-chars",
"secret_hint": "my-s…",
"created_at": "2026-03-15T10:00:00.000Z"
}

Available Events

EventTrigger
*All events (wildcard)
qr.createdNew QR code created
qr.updatedQR code updated (URL, status, tags)
qr.deletedQR code deleted
qr.scannedQR code scanned
qr.flaggedQR code flagged as unsafe by Web Risk
scan.createdNew scan event (same as qr.scanned, higher granularity)
workspace.updatedWorkspace settings changed

Signature Verification

Every delivery includes the X-QR3-Signature header. Verify it with HMAC-SHA256:

import crypto from 'node:crypto';
function verifySignature(secret: string, body: string, signature: string): boolean {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Retry Policy

Failed deliveries are retried 3 times with exponential backoff:

AttemptDelay
1Immediate
260 seconds
3300 seconds (5 min)

After 3 failures the webhook is automatically deactivated (is_active: false).

List Deliveries

Terminal window
GET /v1/webhooks/:id/deliveries?limit=20

Returns the delivery history with status, status code, and response time.

Test a Webhook

Terminal window
POST /v1/webhooks/:id/ping

Sends a webhook.ping test event to verify the endpoint is reachable.