Skip to content

Webhooks

Webhooks

Webhooks võimaldavad sul vastu võtta reaalajas teavitusi, kui sinu töölaual (workspace) toimuvad sündmused — näiteks kui skannitakse QR-koodi.

Webhooki loomine

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"
}

Sündmuste tüübid

SündmusKirjeldus
*Kõik sündmused
qr.createdQR-kood loodud
qr.updatedQR-kood uuendatud (URL, staatus, sildid)
qr.deletedQR-kood kustutatud
qr.scannedQR-kood skannitud
qr.flaggedQR-kood märgitud ebaturvaliseks
webhook.pingTest-ping (läbi /ping otspunkti)

Payload-vorming

Kõik webhooki payloadid on järgmises vormingus:

{
"id": "evt_4f0c2a91d7e84b3c9a1f",
"type": "qr.scanned",
"created": "2026-03-15T10:00:00.000Z",
"data": {
"code_id": "qr_abc123",
"short_code": "r7f3Kx",
"scanned_at": "2026-03-15T10:00:00.000Z",
"country": "AT",
"device_type": "mobile",
"os": "iOS",
"browser": "Safari",
"language": "de",
"ab_variant": null,
"redirected_to": "https://example.com/landing"
}
}

Koodisündmused: qr.created ja qr.updated

Nende mõlema sündmuse puhul on data kood täpselt selline, nagu GET /v1/codes/:id seda tagastab. Selle hulka kuulub appearance ehk koodi juurde salvestatud värvid (null tähistab vaikimisi musta või valget):

{
"id": "evt_9b2e41c07a5d4f18b3c6",
"type": "qr.updated",
"created": "2026-09-28T10:00:00.000Z",
"data": {
"id": "qr_abc123",
"short_code": "r7f3Kx",
"status": "live",
"appearance": { "foreground_color": "#1F4E79", "background_color": null },
"updated_at": "2026-09-28T10:00:00.000Z"
}
}

Näide on lühendatud. Kõik väljad on loetletud koodide API-s.

Allkirja kontrollimine

qr3.app allkirjastab iga webhooki päringu kasutades HMAC-SHA256 algoritmi:

X-QR3-Signature: sha256=a1b2c3d4e5f6...
X-QR3-Event: qr.scanned
X-QR3-Delivery: wdl_abc123
X-QR3-Attempt: 1
User-Agent: qr3-webhooks/1.0

Verifitseerimise rakendamine

import crypto from "crypto";
function verifySignature(
payload: string,
signature: string | undefined,
secret: string
): boolean {
const expected = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
const expectedBytes = Buffer.from(`sha256=${expected}`);
const receivedBytes = Buffer.from(signature ?? "");
return (
expectedBytes.length === receivedBytes.length &&
crypto.timingSafeEqual(expectedBytes, receivedBytes)
);
}
// In Express: verify the raw body — re-serialised JSON breaks the signature.
app.post(
"/webhooks/qr3",
express.raw({ type: "application/json" }),
(req, res) => {
const raw = req.body.toString("utf8");
const signature = req.headers["x-qr3-signature"] as string | undefined;
if (!verifySignature(raw, signature, process.env.QR3_WEBHOOK_SECRET!)) {
return res.status(401).json({ error: "Invalid signature" });
}
const event = JSON.parse(raw);
console.log(event.type, event.data);
res.json({ received: true });
},
);

Uuesti proovimise loogika

Tõrgete korral (HTTP >= 300 või ajalõpp) proovib qr3.app kohaletoimetamist uuesti:

KatseViivitus
1Kohe
21 minut
35 minutit

Pärast 10 järjestikust tõrget lülitatakse webhook automaatselt välja.

Kohaletoimetamise garantii

qr3.app toimetab kohale vähemalt üks kord, mitte täpselt üks kord. Sama sündmus võib seetõttu jõuda sinu otspunkti rohkem kui üks kord: korduskatsena pärast tõrget või juba saadetud katse kordusena.

  • Dubleerimise tuvastamiseks kasuta payload’i välja id (evt_…). See kuulub sündmuse juurde ja jääb iga katse ja iga korduse puhul samaks. X-QR3-Delivery tähistab üksikut katset: selle katse kordus kannab sama väärtust, uus katse uut. Kinnita juba tuntud id vastusega 2xx, mitte 4xx: 4xx loetakse nurjunud katseks ning pärast 10 järjestikust tõrget lülitatakse webhook automaatselt välja.
  • Katse, mis on tund aega pärast loomist endiselt pending (näiteks seetõttu, et selle järjekorrasõnum läks kaduma), seatakse igapäevase puhastuse käigus olekusse failed; status_code ja response_time_ms jäävad väärtusele null. See ei ole sinu otspunkti tõrge ega lähe arvesse 10 järjestikuse tõrke hulka. Logi salvestab selle kohta teksti Delivery was not completed in time — closed by cleanup; kohaletoimetamise logide lõpp-punkt seda ei tagasta. Sulgemine ei ole lõplik: kui sõnum siiski saabub, toimetatakse see kohale ja selle tegelik tulemus asendab selle teksti.

Kohaletoimetamise logid

Terminal window
GET /v1/webhooks/:id/deliveries
{
"data": [
{
"id": "wdl_abc123",
"event_type": "qr.scanned",
"status": "success",
"status_code": 200,
"response_time_ms": 145,
"attempt": 1,
"created_at": "2026-03-15T10:00:00.000Z"
}
]
}

Kohaletoimetamiskatseid säilitatakse 90 päeva (jooksev UTC-päev ja 89 eelnevat päeva), seejärel kustutatakse need automaatselt. Lisaks näidatud väljadele salvestab logi sündmuse payload’i ja lõpp-punkti vastuse esimese kilobaidi (1 KB); see lõpp-punkt ei tagasta kumbagi.

Test-ping

Testi webhooki kohe:

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

See saadab sinu otspunkti URL-ile sündmuse webhook.ping.