---
title: "Digitale productpaspoorten automatiseren met Webhooks — qr3.app Blog"
description: "Een digitaal productpaspoort is geen statische pagina — elke scan is een gebeurtenis waarop je kunt voortbouwen. Reageer op qr.scanned voor analytics, herbestellingen en recall-meldingen, houd paspoortgegevens actueel vanuit je ERP en verifieer elke payload met HMAC-SHA256. Een gids van ontwikkelaarsniveau met code."
canonical: "https://qr3.app/nl/blog/dpp-webhooks-automation/"
lang: "nl"
robots: "index,follow,max-image-preview:large,max-snippet:-1"
---

# Digitale productpaspoorten automatiseren met Webhooks — qr3.app Blog

> Een digitaal productpaspoort is geen statische pagina — elke scan is een gebeurtenis waarop je kunt voortbouwen. Reageer op qr.scanned voor analytics, herbestellingen en recall-meldingen, houd paspoortgegevens actueel vanuit je ERP en verifieer elke payload met HMAC-SHA256. Een gids van ontwikkelaarsniveau met code.

Canonical: <https://qr3.app/nl/blog/dpp-webhooks-automation/>

[← Blog](/nl/blog/) [Tutorials](/nl/blog/category/tutorials/)

30 mei 2026 5 min leestijd [Tutorials](/nl/blog/category/tutorials/) [dpp](/nl/blog/tag/dpp/)[webhooks](/nl/blog/tag/webhooks/)[automation](/nl/blog/tag/automation/)[qr-scanned](/nl/blog/tag/qr-scanned/)[sdk](/nl/blog/tag/sdk/)

# Digitale productpaspoorten automatiseren met Webhooks

Een digitaal productpaspoort is geen statische pagina — elke scan is een gebeurtenis waarop je kunt voortbouwen. Reageer op qr.scanned voor analytics, herbestellingen en recall-meldingen, houd paspoortgegevens actueel vanuit je ERP en verifieer elke payload met HMAC-SHA256. Een gids van ontwikkelaarsniveau met code.

door **QR3 Redaktion**

![Digitale productpaspoorten automatiseren met Webhooks](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/dpp-webhooks-automation/hero.png)

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. Verifieer de handtekening aan de hand van de ruwe body voordat je deze parsed:

```
import express from "express";
import { createHmac, timingSafeEqual } from "crypto";

const app = express();
const secret = process.env.QR3_WEBHOOK_SECRET!;

// Recompute the HMAC over the exact bytes qr3 signed and compare in constant time.
function verify(raw: Buffer, header: string | undefined): boolean {
  const expected = createHmac("sha256", secret).update(raw).digest("hex");
  const expectedBytes = Buffer.from(`sha256=${expected}`);
  const receivedBytes = Buffer.from(header ?? "");
  return (
    expectedBytes.length === receivedBytes.length &&
    timingSafeEqual(expectedBytes, receivedBytes)
  );
}

// Use the raw body so the signature matches the exact bytes qr3 signed.
app.post("/webhooks/qr3", express.raw({ type: "application/json" }), (req, res) => {
  if (!verify(req.body, req.headers["x-qr3-signature"] as string)) return res.sendStatus(401);
  const event = JSON.parse(req.body.toString("utf8"));

  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 (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 ruwe request-body, met behulp van je endpoint-secret. De handtekening komt binnen in de `X-QR3-Signature`-request-header, als `sha256=` gevolgd door de hex-digest. Bereken de HMAC opnieuw over dezelfde bytes en vergelijk de twee in constante tijd; als ze verschillen, wijs je de request af:

```
app.post("/webhooks/qr3", express.raw({ type: "application/json" }), (req, res) => {
  if (!verify(req.body, req.headers["x-qr3-signature"] as string)) {
    // signature mismatch → not from qr3 (or body was altered in transit)
    return res.sendStatus(401);
  }
  process(JSON.parse(req.body.toString("utf8")));
  res.sendStatus(200);
});
```

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. Het controleren van de `X-QR3-Signature` HMAC tegen de ruwe body 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

- [EU ESPR — Verordening (EU) 2024/1781](https://eur-lex.europa.eu/eli/reg/2024/1781/oj)

- [EU Batterijverordening 2023/1542](https://eur-lex.europa.eu/eli/reg/2023/1542/oj)

- [HMAC — RFC 2104](https://www.rfc-editor.org/rfc/rfc2104)

**Begin gratis** en koppel je eerste DPP-webhook: [app.qr3.app/sign-up](https://app.qr3.app/sign-up)

## Gerelateerde artikelen

- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/gs1-resolver-test-suite-dpp-links/hero.png) Tutorials GS1 Resolver Test Suite: DPP-links vóór de livegang betrouwbaar testen De stabiele GS1-testsuite maakt Resolver 1.2 toetsbaar. Zo test u redirects, linksets, CORS, talen en foutgevallen vóór de livegang.](/nl/blog/gs1-resolver-test-suite-dpp-links/)
- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/dpp-battery-passport-2027-20260715/hero.png) Branche-nieuws BatteryPass-Ready start testomgeving voor het digitale batterijpaspoort Het consortium BatteryPass-Ready heeft op 24 juni 2026 een openbare testomgeving voor het digitale batterijpaspoort gestart, met het oog op de EU-verplichting vanaf februari 2027.](/nl/blog/dpp-battery-passport-2027-20260715/)
- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/sector-20260713/hero.png) Branche-nieuws Digitale batterijpas 2027: wat fabrikanten nu moeten weten Webinars, opensourcetools en nieuwe normen: de EU-batterijpas komt op stoom. Een overzicht van de stand van zaken in juli 2026 en de openstaande vragen tot februari 2027.](/nl/blog/sector-20260713/)
- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/sector-20260711/hero.png) Branche-nieuws Digitale batterijpas 2026: testomgevingen, normen en open vragen Waar staat de industrie met de digitale batterijpas? Een overzicht van testomgevingen, CEN/CENELEC-normen, opensourcetools en regelgevende koersbepalingen in juli 2026.](/nl/blog/sector-20260711/)

[← Alle artikelen](/nl/blog/) [Gratis starten](https://app.qr3.app/sign-up)
