Webhooks · v1
Webhooks — CD4CD pushes, your server receives.
Register one endpoint, receive a structured event stream. HMAC-signed payloads, smart retries, clean JSON.
Registration
Register via /dashboard/api → New webhook or via the REST API:
POST /v1/webhooks
Authorization: Bearer cd_live_xxx
{
"endpoint": "https://hooks.aljazera.sa/cd4cd",
"events": ["link.clicked", "link.created"],
"secret": "auto"
}
→ 201 Created
{ "id": "wh_8f3c", "endpoint": "...", "secret": "whsec_xyz" }Available events
| Event | Description |
|---|---|
| link.created | A new short link was created. |
| link.updated | Link destination or alias updated. |
| link.deleted | Link deleted. |
| link.clicked | Every click (with breakdown). |
| qr.created | A new QR was created. |
| qr.scanned | Every QR scan. |
| bio.visited | Every Bio page visit. |
| security.flagged | A link flagged by safety layers. |
Example: link.clicked
POST https://hooks.aljazera.sa/cd4cd
CD4CD-Signature: t=1715583720,v1=8f3c…a91
Content-Type: application/json
{
"id": "evt_18f3c_a91",
"type": "link.clicked",
"createdAt": "2026-05-13T05:42:00.123Z",
"data": {
"linkId": "lnk_8f3c_a91",
"shortCode": "promo-2026",
"longUrl": "https://example.com/long/path",
"country": "SA",
"device": "mobile",
"os": "iOS",
"referrer": "https://t.co/abc"
}
}Verify the signature
Every webhook carries a CD4CD-Signature. Compute HMAC_SHA256(secret, t + "." + body) and compare against v1.
// Node.js
import crypto from 'node:crypto';
const sig = req.headers['cd4cd-signature']; // t=..,v1=..
const [tPart, vPart] = sig.split(',');
const t = tPart.slice(2);
const v1 = vPart.slice(3);
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(`${t}.${req.rawBody}`)
.digest('hex');
if (expected !== v1) return res.status(401).end();Retries
If we don't get a 2xx within 10s, we retry with exponential backoff:
- 1m → 5m → 15m → 1h → 6h → 24h
- After 6 failed attempts we pause the webhook and email you.
Idempotency
Each event has a unique id. Store the last 7 days to dedupe replays.