Skip to content

Webhookok

Webhookok

A webhookok segítségével valós idejű értesítéseket kaphatsz, ha események történnek a Workspace-edben — például amikor egy QR-kódot beolvasnak.

Webhook létrehozása

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

Válasz

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

Eseménytípusok

EseményLeírás
*Minden esemény
qr.createdQR-kód létrehozva
qr.updatedQR-kód frissítve (URL, állapot, címkék)
qr.deletedQR-kód törölve
qr.scannedQR-kód beolvasva
qr.flaggedQR-kód nem biztonságosként megjelölve
webhook.pingTeszt ping (a /ping végponton keresztül)

Payload-formátum

Minden webhook payload az alábbi formátummal rendelkezik:

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

Kódesemények: qr.created és qr.updated

Mindkét esemény esetében a data pontosan úgy tartalmazza a kódot, ahogyan azt a GET /v1/codes/:id végpont visszaadja. Ide tartozik az appearance is, amely a kódhoz mentett színeket jelöli (a null az alapértelmezett fekete, illetve fehér színt jelenti):

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

A példa rövidített. Minden mező megtalálható a Codes API-ban.

Aláírás-ellenőrzés

A qr3.app minden webhook kérést HMAC-SHA256 használatával ír alá:

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

Ellenőrzés implementálása

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 });
},
);

Újrapróbálkozási logika

Hibák esetén (HTTP >= 300 vagy időtúllépés) a qr3.app megkísérli az újbóli kézbesítést:

KísérletKésleltetés
1Azonnal
21 perc
35 perc

10 egymást követő hiba után a webhook automatikusan deaktiválásra kerül.

Kézbesítési garancia

A qr3.app legalább egyszer kézbesít, nem pontosan egyszer. Ugyanaz az esemény ezért többször is megérkezhet a végpontodra: hiba utáni újrapróbálkozásként vagy egy már elküldött kísérlet megismétlésként.

  • A duplikátumokat a payload id mezője alapján szűrd ki (evt_…). Az eseményhez tartozik, és minden kísérletnél és minden ismétlésnél ugyanaz marad. Az X-QR3-Delivery az egyes kísérletet azonosítja: egy kísérlet ismétlése ugyanazt az értéket viseli, egy új kísérlet újat. A már ismert id-ra 2xx-es állapotkóddal válaszolj, ne 4xx-szel: a 4xx sikertelen kísérletnek számít, és 10 egymást követő hiba után a webhook automatikusan deaktiválásra kerül.
  • Az a kísérlet, amely a létrehozása után egy órával még mindig pending (például mert az üzenete elveszett a sorban), egy napi takarítás során failed állapotba kerül; a status_code és a response_time_ms null marad. Ez nem a végpontod hibája, és nem számít bele a 10 egymást követő hibába. A napló erre a Delivery was not completed in time — closed by cleanup szöveget tárolja; a kézbesítési naplók végpontja nem adja vissza. A lezárás nem végleges: ha az üzenet mégis megérkezik, kézbesítésre kerül, és a tényleges eredménye lecseréli ezt a szöveget.

Kézbesítési naplók

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

A kézbesítési kísérletek 90 napig maradnak meg (az aktuális UTC-nap és az azt megelőző 89 nap), utána automatikusan törlődnek. A megjelenített mezőkön túl a napló tárolja az esemény payloadját és a végpont válaszának első 1 KB-ját; ez a végpont egyiket sem adja vissza.

Teszt ping

Tesztelj egy webhookot azonnal:

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

Ez egy webhook.ping eseményt küld a végpontod URL-jére.