De meeste teams behandelen een digitaal productpaspoort als een pagina: je maakt het aan, drukt de QR-code af en vergeet het verder. Daarmee laat je het meest bruikbare signaal links liggen. Elke keer dat iemand de QR-code op een product scant, is dat een gebeurtenis — een echt persoon, in een echt land, met een echte eenheid in handen, op een echt moment. Koppel die gebeurtenissen aan je stack en het paspoort houdt op een statische pagina te zijn en wordt de voorkant van een automatiseringspijplijn. Deze gids laat zien hoe je je abonneert op qr.scanned, elke payload verifieert en scans en updates omzet in echte workflows met de qr3 SDK.
Waarom een DPP een gebeurtenisbron is, geen statische pagina
De waarde van een paspoort is niet de pagina die een consument één keer ziet. Het is de stroom van interacties eromheen: scans in het veld, gegevenswijzigingen vanuit je ERP, levenscyclusovergangen. Elk daarvan is iets waarop je systemen in realtime kunnen reageren.
Webhooks keren het gebruikelijke pollingmodel om. In plaats van op gezette tijden te vragen "is er iets gebeurd?", belt qr3 jou op het moment dat het gebeurt. De gebeurtenistypen die het platform uitzendt zijn onder meer qr.scanned, plus qr.created, qr.updated en qr.deleted voor levenscyclusveranderingen. Degene die de meeste teams onderbenutten is qr.scanned: die wordt afgevuurd wanneer een consument, technicus of douanebeambte daadwerkelijk een product in het wild scant.
Een qr.scanned-payload bevat de context die je nodig hebt om te handelen — inclusief het land van de scan en de dpp/code id die aangeeft welke eenheid is gescand. Dat is genoeg om analytics, aanvulling en recall-logica aan te sturen zonder dat er een mens aan te pas komt.
Abonneren op qr.scanned
Richt een webhook-endpoint op je service en verwerk de gebeurtenis. De qr3 SDK levert een verifier zodat je niet handmatig ruwe bodies hoeft te parsen:
import express from "express";
import { verifyWebhook } from "@qr3/sdk";
const app = express();
const secret = process.env.QR3_WEBHOOK_SECRET!;
// Use the raw body so the signature matches the exact bytes qr3 signed.
app.post("/webhooks/qr3", express.raw({ type: "application/json" }), (req, res) => {
const event = verifyWebhook(req.body, req.headers["qr3-signature"], secret);
if (event.type === "qr.scanned") {
// event payload includes fields like the scan country and the dpp/code id
handleScan(event);
}
res.sendStatus(200);
});
De handler is bewust dun gehouden: verifieer, vertak op event.type, bevestig snel met een 200. Doe het zware werk (analytics-writes, ERP-aanroepen) asynchroon, zodat een trage downstream nooit de bevestiging blokkeert.
Handtekeningen verifiëren (verifyWebhook, HMAC-SHA256) — doe dit altijd
Een webhook-endpoint is een publieke URL. Iedereen die hem vindt, kan eraan POSTen. Als je de body vertrouwt zonder te controleren wie hem heeft verstuurd, kan een aanvaller "scans" vervalsen, valse herbestellingen uitlokken of onterechte recall-meldingen afvuren. Verifieer altijd de handtekening voordat je op een payload handelt.
qr3 ondertekent elke webhook met HMAC-SHA256 over de request-body, met behulp van je endpoint-secret. De handtekening komt binnen in de qr3-signature-request-header. verifyWebhook(body, signature, secret) herberekent de HMAC en vergelijkt die; als ze niet overeenkomt, gooit de functie een error en wijs je de request af:
import { verifyWebhook } from "@qr3/sdk";
app.post("/webhooks/qr3", express.raw({ type: "application/json" }), (req, res) => {
try {
const event = verifyWebhook(req.body, req.headers["qr3-signature"], secret);
process(event);
res.sendStatus(200);
} catch {
// signature mismatch → not from qr3 (or body was altered in transit)
res.sendStatus(401);
}
});
Drie regels die dit eerlijk houden:
- Verifieer tegen de ruwe bytes. Het opnieuw serialiseren van JSON kan sleutels herordenen en witruimte veranderen, wat de HMAC breekt. Vang de ruwe body op (hierboven,
express.raw). - Houd het secret geheim. Het hoort in je omgeving, nooit in clientcode of een repo.
- Faal gesloten. Geen geldige handtekening →
401, geen neveneffecten. Verwerk een mismatch nooit "toch maar".
Patronen: analytics / herbestellen / recall
Zodra je de gebeurtenis vertrouwt, dekt een handvol patronen het meeste van wat teams willen:
function handleScan(event: { type: string; data: { country?: string; dpp_id?: string } }) {
// 1) Analytics — where and how often are products scanned?
metrics.increment("dpp.scan", { country: event.data.country });
// 2) Re-order — a scan can signal consumption or field activity
if (event.data.country) maybeReplenish(event.data.dpp_id, event.data.country);
// 3) Recall flag — scans of a flagged unit alert your team
if (isRecalled(event.data.dpp_id)) alertRecall(event.data.dpp_id, event.data.country);
}
- Analytics: aggregeer scans per land en eenheid om de betrokkenheid in de praktijk te zien — welke markten daadwerkelijk scannen, en welke SKU's de meeste interactie na verkoop kennen.
- Herbestellen / aanvulling: een piek aan scans in een regio kan vraagsignalen voeden of voorraad-aanvulworkflows in je ERP triggeren.
- Recall / veiligheid: als een eenheid onder recall valt, is een scan een kans om degene te bereiken die hem in handen heeft — waarschuw je team, of toon een melding op het paspoort zelf.
Geen van deze heeft polling of een nachtelijke batch nodig. Ze gebeuren op het moment dat het product wordt gescand.
Gegevens actueel houden via client.dpp.update
Reageren op scans is de helft van de lus; de andere helft is het paspoort zelf accuraat houden. Regelgeving zoals de ESPR (EU 2024/1781) en de Batterijverordening (EU 2023/1542) verwacht dat paspoortgegevens gedurende de levensduur van het product de werkelijkheid weerspiegelen — een herberekende CO2-voetafdruk, bijgewerkte reparatie-instructies, behaalde doelen voor gerecycled materiaal.
Stuur die updates aan vanuit het registratiesysteem. Wanneer een waarde verandert in je ERP, push die naar het paspoort:
import { QR3 } from "@qr3/sdk";
const client = new QR3({ apiKey: process.env.QR3_API_KEY! });
// GTIN and serial are immutable; data fields are updatable.
await client.dpp.update(dppId, {
battery_data: { carbon_footprint_kg: 58, recycled_content_pct: 16 },
});
Omdat de QR-code een stabiele resolver-URL codeert (https://qr3.app/dpp/{gtin}/{serial}, voeg ?format=jsonld toe voor JSON-LD), hoef je nooit een label opnieuw af te drukken om gegevens te wijzigen. De identiteit blijft vast; de inhoud erachter blijft actueel. Combineer dit met qr.updated en je kunt een notificatie uitwaaieren telkens als een paspoort verandert — waarmee je de lus sluit tussen je ERP, het paspoort en iedereen die downstream meekijkt.
Een gebeurtenistabel: gebeurtenis → wat te automatiseren
| Gebeurtenis | Wordt afgevuurd wanneer | Wat te automatiseren |
|---|---|---|
qr.scanned |
Een product-QR wordt in het veld gescand | Analytics per land, aanvulsignalen, recall-meldingen |
qr.created |
Een nieuw paspoort wordt aangemaakt | Indexeer het, synchroniseer naar PIM/ERP, informeer het catalogusteam |
qr.updated |
Paspoortgegevens veranderen | Cache de publieke pagina opnieuw, waaier wijzigingsnotificaties uit |
qr.deleted |
Een paspoort wordt verwijderd | Markeer interne records als tombstone, trek downstream-verwijzingen in |
Begin met qr.scanned voor betrokkenheid en veldsignalen; voeg de levenscyclusgebeurtenissen toe naarmate je paspoorten in je bredere systemen synchroniseert.
FAQ
Moet ik de handtekening verifiëren als mijn endpoint-URL geheim is?
Ja. Een URL is geen geheim — hij lekt in logs, proxy's en browsergeschiedenis. HMAC-verificatie met verifyWebhook is het enige dat bewijst dat een payload daadwerkelijk van qr3 afkomstig is.
Wat gebeurt er als mijn endpoint plat ligt wanneer een gebeurtenis wordt afgevuurd?
Bevestig snel met 200 zodra je hebt geverifieerd, en doe traag werk asynchroon, zodat tijdelijke downstream-problemen de respons nooit ophouden. Houd je eigen idempotentie aan op dpp/code id, zodat een opnieuw bezorgde levering niet dubbel wordt geteld.
Kan ik GTIN of serienummer bijwerken via client.dpp.update? Nee — GTIN en serienummer zijn onveranderlijk; ze vormen de stabiele identiteit van het product. Alleen de datavelden zijn bij te werken. Juist die onveranderlijkheid zorgt ervoor dat de afgedrukte QR-code voor altijd geldig blijft.
Bronnen
Begin gratis en koppel je eerste DPP-webhook: app.qr3.app/sign-up