Digital Product Passports mit Webhooks automatisieren

Ein Digital Product Passport ist keine statische Seite — jeder Scan ist ein Event, auf dem du aufbauen kannst. Reagiere auf qr.scanned für Analytics, Nachbestellung und Rückruf-Flags, halte Passport-Daten aus deinem ERP frisch und verifiziere jedes Payload mit HMAC-SHA256.

von QR3 Redaktion

Digital Product Passports mit Webhooks automatisieren

Die meisten Teams behandeln einen Digital Product Passport wie eine Seite: anlegen, QR drucken, vergessen. Damit bleibt das nützlichste Signal liegen. Jedes Mal, wenn jemand den QR auf einem Produkt scannt, ist das ein Event — eine echte Person, in einem echten Land, mit einer echten Einheit in der Hand, zu einem echten Zeitpunkt. Verdrahte diese Events mit deinem Stack, und der Passport ist nicht mehr eine statische Seite, sondern das Frontend einer Automatisierungs-Pipeline. Dieser Leitfaden zeigt, wie du qr.scanned abonnierst, jedes Payload verifizierst und Scans sowie Updates mit dem qr3 SDK in echte Workflows verwandelst.

Warum ein DPP eine Event-Quelle ist, keine statische Seite

Der Wert eines Passports ist nicht die Seite, die ein Konsument einmal sieht. Es ist der Strom an Interaktionen drumherum: Scans im Feld, Datenänderungen aus deinem ERP, Lebenszyklus-Übergänge. Jedes davon ist etwas, worauf deine Systeme in Echtzeit reagieren können.

Webhooks kehren das übliche Polling-Modell um. Statt im Takt zu fragen „ist etwas passiert?", ruft qr3 dich in dem Moment, in dem es passiert. Zu den Event-Typen der Plattform gehören qr.scanned sowie qr.created, qr.updated und qr.deleted für Lebenszyklus-Änderungen. Das am meisten unterschätzte ist qr.scanned: Es feuert, wenn ein Konsument, Techniker oder Zollbeamter ein Produkt tatsächlich in freier Wildbahn scannt.

Ein qr.scanned-Payload trägt den Kontext, den du zum Handeln brauchst — darunter das Land des Scans und die dpp/code id, die identifiziert, welche Einheit gescannt wurde. Das reicht, um Analytics, Nachschub und Rückruf-Logik ohne Mensch in der Schleife anzustoßen.

qr.scanned abonnieren

Richte einen Webhook-Endpoint auf deinen Dienst und behandle das Event. Das qr3 SDK liefert einen Verifier mit, damit du keine rohen Bodies von Hand parst:

import express from "express";
import { verifyWebhook } from "@qr3/sdk";

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

// Nutze den Raw-Body, damit die Signatur zu exakt den Bytes passt, die qr3 signiert hat.
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") {
    // Payload enthält Felder wie das Scan-Land und die dpp/code id
    handleScan(event);
  }

  res.sendStatus(200);
});

Der Handler ist bewusst schlank: verifizieren, auf event.type verzweigen, schnell mit 200 quittieren. Die schwere Arbeit (Analytics-Schreibvorgänge, ERP-Aufrufe) erledigst du asynchron, damit ein langsames Downstream die Quittung nie blockiert.

Signaturen verifizieren (verifyWebhook, HMAC-SHA256) — immer machen

Ein Webhook-Endpoint ist eine öffentliche URL. Jeder, der sie findet, kann darauf POSTen. Vertraust du dem Body, ohne zu prüfen, wer ihn gesendet hat, kann ein Angreifer „Scans" fälschen, falsche Nachbestellungen auslösen oder falsche Rückruf-Flags feuern. Verifiziere immer die Signatur, bevor du auf ein Payload reagierst.

qr3 signiert jeden Webhook mit HMAC-SHA256 über den Request-Body, mit deinem Endpoint-Secret. Die Signatur kommt im qr3-signature-Request-Header an. verifyWebhook(body, signature, secret) berechnet den HMAC neu und vergleicht ihn; passt er nicht, wirft die Funktion und du weist den Request ab:

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 {
    // Signatur passt nicht → nicht von qr3 (oder Body unterwegs verändert)
    res.sendStatus(401);
  }
});

Drei Regeln, die das ehrlich halten:

  • Gegen die rohen Bytes verifizieren. Erneutes Serialisieren von JSON kann Schlüssel umsortieren und Whitespace ändern, was den HMAC bricht. Erfasse den Raw-Body (oben, express.raw).
  • Das Secret bleibt geheim. Es lebt in deiner Umgebung, nie im Client-Code oder in einem Repo.
  • Im Zweifel abweisen. Keine gültige Signatur → 401, keine Seiteneffekte. Niemals bei Mismatch „trotzdem verarbeiten".

Muster: Analytics / Nachbestellung / Rückruf

Sobald du dem Event traust, deckt eine Handvoll Muster das meiste ab, was Teams wollen:

function handleScan(event: { type: string; data: { country?: string; dpp_id?: string } }) {
  // 1) Analytics — wo und wie oft werden Produkte gescannt?
  metrics.increment("dpp.scan", { country: event.data.country });

  // 2) Nachbestellung — ein Scan kann Verbrauch oder Feldaktivität signalisieren
  if (event.data.country) maybeReplenish(event.data.dpp_id, event.data.country);

  // 3) Rückruf-Flag — Scans einer markierten Einheit alarmieren dein Team
  if (isRecalled(event.data.dpp_id)) alertRecall(event.data.dpp_id, event.data.country);
}
  • Analytics: Scans nach Land und Einheit aggregieren, um echtes Engagement zu sehen — welche Märkte tatsächlich scannen und welche SKUs die meiste Interaktion nach dem Verkauf erfahren.
  • Nachbestellung / Nachschub: Ein Schwung Scans in einer Region kann Bedarfssignale speisen oder Restock-Workflows in deinem ERP auslösen.
  • Rückruf / Sicherheit: Steht eine Einheit unter Rückruf, ist ein Scan die Chance, wer sie auch hält zu erreichen — alarmiere dein Team oder zeige einen Hinweis auf dem Passport selbst.

Nichts davon braucht Polling oder einen nächtlichen Batch. Es passiert in dem Moment, in dem das Produkt gescannt wird.

Daten aktuell halten via client.dpp.update

Auf Scans zu reagieren ist die eine Hälfte der Schleife; die andere ist, den Passport selbst korrekt zu halten. Verordnungen wie die ESPR (EU 2024/1781) und die Batterieverordnung (EU 2023/1542) erwarten, dass Passport-Daten über die Produktlebensdauer die Realität widerspiegeln — neu berechneter CO₂-Fußabdruck, aktualisierte Reparaturhinweise, erreichte Rezyklatziele.

Treibe diese Updates aus dem führenden System. Ändert sich ein Wert in deinem ERP, schiebe ihn in den Passport:

import { QR3 } from "@qr3/sdk";

const client = new QR3({ apiKey: process.env.QR3_API_KEY! });

// GTIN und Seriennummer sind unveränderlich; Datenfelder sind aktualisierbar.
await client.dpp.update(dppId, {
  battery_data: { carbon_footprint_kg: 58, recycled_content_pct: 16 },
});

Weil der QR eine stabile Resolver-URL kodiert (https://qr3.app/dpp/{gtin}/{serial}, mit ?format=jsonld für JSON-LD), druckst du nie ein Etikett neu, um Daten zu ändern. Die Identität bleibt fix; der Inhalt dahinter bleibt aktuell. Kombiniere das mit qr.updated und du kannst eine Benachrichtigung ausfächern, wann immer sich ein Passport ändert — und schließt so die Schleife zwischen deinem ERP, dem Passport und allen, die downstream zusehen.

Eine Event-Tabelle: Event → was automatisieren

Event Feuert, wenn Was automatisieren
qr.scanned Ein Produkt-QR wird im Feld gescannt Analytics nach Land, Nachschub-Signale, Rückruf-Alarme
qr.created Ein neuer Passport wird angelegt Indexieren, in PIM/ERP synchronisieren, Katalog-Team benachrichtigen
qr.updated Passport-Daten ändern sich Öffentliche Seite neu cachen, Änderungs-Benachrichtigungen ausfächern
qr.deleted Ein Passport wird entfernt Interne Datensätze als gelöscht markieren, Downstream-Referenzen widerrufen

Beginne mit qr.scanned für Engagement und Feldsignale; ergänze die Lebenszyklus-Events, sobald du Passports in deine weiteren Systeme synchronisierst.

FAQ

Muss ich die Signatur verifizieren, wenn meine Endpoint-URL geheim ist? Ja. Eine URL ist kein Secret — sie leakt in Logs, Proxys und im Browser-Verlauf. HMAC-Verifikation mit verifyWebhook ist das Einzige, was beweist, dass ein Payload wirklich von qr3 kam.

Was passiert, wenn mein Endpoint ausfällt, während ein Event feuert? Quittiere nach der Verifikation schnell mit 200 und erledige langsame Arbeit asynchron, damit vorübergehende Downstream-Probleme die Antwort nie blockieren. Halte eigene Idempotenz auf der dpp/code id, damit eine erneut zugestellte Lieferung nicht doppelt zählt.

Kann ich GTIN oder Seriennummer via client.dpp.update ändern? Nein — GTIN und Seriennummer sind unveränderlich; sie sind die stabile Identität des Produkts. Nur die Datenfelder sind aktualisierbar. Genau diese Unveränderlichkeit lässt den gedruckten QR für immer gültig bleiben.

Quellen

Kostenlos starten und deinen ersten DPP-Webhook verdrahten: app.qr3.app/sign-up