---
title: "Automatisér digitale produktpas med Webhooks — qr3.app Blog"
description: "Et digitalt produktpas er ikke en statisk side — hver scanning er en hændelse, du kan bygge videre på. Reagér på qr.scanned til analyse, genbestillinger og tilbagekaldelsesmarkeringer, hold pasdata friske fra dit ERP, og verificér hver payload med HMAC-SHA256. En guide på udviklerniveau med kode."
canonical: "https://qr3.app/da/blog/dpp-webhooks-automation/"
lang: "da"
robots: "index,follow,max-image-preview:large,max-snippet:-1"
---

# Automatisér digitale produktpas med Webhooks — qr3.app Blog

> Et digitalt produktpas er ikke en statisk side — hver scanning er en hændelse, du kan bygge videre på. Reagér på qr.scanned til analyse, genbestillinger og tilbagekaldelsesmarkeringer, hold pasdata friske fra dit ERP, og verificér hver payload med HMAC-SHA256. En guide på udviklerniveau med kode.

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

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

30. maj 2026 5 min læsning [Tutorials](/da/blog/category/tutorials/) [dpp](/da/blog/tag/dpp/)[webhooks](/da/blog/tag/webhooks/)[automation](/da/blog/tag/automation/)[qr-scanned](/da/blog/tag/qr-scanned/)[sdk](/da/blog/tag/sdk/)

# Automatisér digitale produktpas med Webhooks

Et digitalt produktpas er ikke en statisk side — hver scanning er en hændelse, du kan bygge videre på. Reagér på qr.scanned til analyse, genbestillinger og tilbagekaldelsesmarkeringer, hold pasdata friske fra dit ERP, og verificér hver payload med HMAC-SHA256. En guide på udviklerniveau med kode.

af **QR3 Redaktion**

![Automatisér digitale produktpas med Webhooks](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/dpp-webhooks-automation/hero.png)

De fleste teams behandler et digitalt produktpas som en side: du opretter det, printer QR-koden og glemmer det. Dermed lader du det mest brugbare signal ligge. Hver gang nogen scanner QR-koden på et produkt, er det en **hændelse** — en rigtig person, i et rigtigt land, der holder en rigtig enhed, på et rigtigt tidspunkt. Kobl de hændelser ind i din stack, og passet holder op med at være en statisk side og bliver frontenden på en automatiseringspipeline. Denne guide viser, hvordan du abonnerer på `qr.scanned`, verificerer hver payload og forvandler scanninger og opdateringer til rigtige workflows med qr3 SDK'et.

## Hvorfor et DPP er en hændelseskilde, ikke en statisk side

Værdien af et pas er ikke den side, en forbruger ser én gang. Det er strømmen af interaktioner omkring det: scanninger i felten, dataændringer fra dit ERP, livscyklusovergange. Hver enkelt er noget, dine systemer kan reagere på i realtid.

Webhooks vender den sædvanlige polling-model på hovedet. I stedet for at spørge *"er der sket noget?"* med jævne mellemrum, ringer qr3 til **dig** i samme øjeblik, det sker. De hændelsestyper, platformen udsender, omfatter `qr.scanned`, plus `qr.created`, `qr.updated` og `qr.deleted` til livscyklusændringer. Den, de fleste teams udnytter for lidt, er `qr.scanned`: den udløses, når en forbruger, tekniker eller toldofficer rent faktisk scanner et produkt ude i den virkelige verden.

En `qr.scanned`-payload bærer den kontekst, du har brug for for at handle — herunder **landet** for scanningen og det **dpp/code id**, der identificerer, hvilken enhed der blev scannet. Det er nok til at drive analyse, genopfyldning og tilbagekaldelseslogik uden et menneske i loopet.

## Sådan abonnerer du på qr.scanned

Peg et webhook-endpoint mod din tjeneste, og håndtér hændelsen. Verificer signaturen mod den rå body, før du parser den:

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

Handleren er bevidst tynd: verificér, forgren på `event.type`, kvittér hurtigt med et `200`. Lad det tunge arbejde (analyse-skrivninger, ERP-kald) foregå asynkront, så et langsomt downstream-system aldrig blokerer kvitteringen.

## Verificering af signaturer (HMAC-SHA256) — gør altid dette

Et webhook-endpoint er en offentlig URL. Alle, der finder den, kan POST'e til den. Hvis du stoler på bodyen uden at tjekke, hvem der sendte den, kan en angriber forfalske "scanninger", udløse falske genbestillinger eller affyre falske tilbagekaldelsesmarkeringer. **Verificér altid signaturen, før du handler på en payload.**

qr3 signerer hver webhook med **HMAC-SHA256** over den rå request-body ved hjælp af din endpoint-hemmelighed. Signaturen ankommer i `X-QR3-Signature`-request-headeren som `sha256=` efterfulgt af hex-digestet. Genberegn HMAC'en over de samme bytes, og sammenlign de to i konstant tid; hvis de er forskellige, afviser du requesten:

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

Tre regler, der holder dette ærligt:

- **Verificér mod de rå bytes.** Re-serialisering af JSON kan omarrangere nøgler og ændre whitespace, hvilket bryder HMAC'en. Fang den rå body (ovenfor, `express.raw`).

- **Hold hemmeligheden hemmelig.** Den lever i dit miljø, aldrig i klientkode eller et repo.

- **Fejl lukket.** Ingen gyldig signatur → `401`, ingen sideeffekter. "Behandl alligevel" aldrig ved et mismatch.

## Mønstre: analyse / genbestilling / tilbagekaldelse

Når du først stoler på hændelsen, dækker en håndfuld mønstre det meste af, hvad teams ønsker:

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

- **Analyse:** aggregér scanninger efter land og enhed for at se engagement i den virkelige verden — hvilke markeder der faktisk scanner, og hvilke SKU'er der ser mest interaktion efter salget.

- **Genbestilling / genopfyldning:** en byge af scanninger i en region kan fodre efterspørgselssignaler eller udløse genopfyldnings-workflows i dit ERP.

- **Tilbagekaldelse / sikkerhed:** hvis en enhed er under tilbagekaldelse, er en scanning en chance for at nå den, der holder den — advar dit team, eller vis en meddelelse på selve passet.

Ingen af disse kræver polling eller et natligt batch-job. De sker i samme øjeblik, produktet scannes.

## Hold data aktuelle via client.dpp.update

At reagere på scanninger er halvdelen af loopet; den anden halvdel er at holde selve passet korrekt. Forordninger som **ESPR (EU 2024/1781)** og **batteriforordningen (EU 2023/1542)** forventer, at pasdata afspejler virkeligheden over produktets levetid — genberegnet CO2-aftryk, opdaterede reparationsinstruktioner, nåede mål for genanvendt indhold.

Driv de opdateringer fra det system, der fører registret. Når en værdi ændres i dit ERP, skub den til passet:

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

Fordi QR-koden indkoder en stabil resolver-URL (`https://qr3.app/dpp/{gtin}/{serial}`, tilføj `?format=jsonld` for JSON-LD), genprinter du aldrig en etiket for at ændre data. Identiteten forbliver fast; indholdet bag den forbliver aktuelt. Kombinér dette med `qr.updated`, og du kan udsende en notifikation, hver gang et pas ændrer sig — så loopet mellem dit ERP, passet og enhver, der ser med downstream, lukkes.

## En hændelsestabel: hændelse → hvad der skal automatiseres

| Hændelse | Udløses, når | Hvad der skal automatiseres |
| --- | --- | --- |
| `qr.scanned` | En produkt-QR scannes i felten | Analyse efter land, genopfyldningssignaler, tilbagekaldelsesalarmer |
| `qr.created` | Et nyt pas oprettes | Indeksér det, synkronisér til PIM/ERP, underret katalogteamet |
| `qr.updated` | Pasdata ændres | Cach den offentlige side igen, udsend ændringsnotifikationer |
| `qr.deleted` | Et pas fjernes | Tombstone interne registreringer, tilbagekald downstream-referencer |

Start med `qr.scanned` til engagement og feltsignaler; tilføj livscyklushændelserne, efterhånden som du synkroniserer pas ind i dine bredere systemer.

## FAQ

**Skal jeg verificere signaturen, hvis min endpoint-URL er hemmelig?**
Ja. En URL er ikke en hemmelighed — den lækker i logfiler, proxyer og browserhistorik. Kontrol af `X-QR3-Signature` HMAC mod den rå body er det eneste, der beviser, at en payload faktisk kom fra qr3.

**Hvad sker der, hvis mit endpoint er nede, når en hændelse udløses?**
Kvittér hurtigt med `200`, når du har verificeret, og udfør langsomt arbejde asynkront, så forbigående downstream-problemer aldrig stopper svaret. Hold din egen idempotens på `dpp/code id`, så en gentaget levering ikke tælles dobbelt.

**Kan jeg opdatere GTIN eller serienummer via client.dpp.update?**
Nej — GTIN og serienummer er uforanderlige; de er produktets stabile identitet. Kun datafelterne kan opdateres. Det er netop den uforanderlighed, der lader den printede QR-kode forblive gyldig for altid.

## Kilder

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

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

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

**Kom i gang gratis** og kobl din første DPP-webhook op: [app.qr3.app/sign-up](https://app.qr3.app/sign-up)

## Relaterede indlæg

- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/gs1-resolver-test-suite-dpp-links/hero.png) Tutorials GS1 Resolver Test Suite: DPP-links pålideligt testet før go-live Den stabile GS1-testpakke gør Resolver 1.2 testbar. Sådan tester du redirects, linksets, CORS, sprog og fejltilfælde før go-live.](/da/blog/gs1-resolver-test-suite-dpp-links/)
- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/dpp-battery-passport-2027-20260715/hero.png) Branchenyheder BatteryPass-Ready lancerer testmiljø til den digitale batteripass Konsortiet BatteryPass-Ready lancerede den 24. juni 2026 et offentligt testmiljø til den digitale batteripass med fokus på EU-kravet fra februar 2027.](/da/blog/dpp-battery-passport-2027-20260715/)
- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/sector-20260713/hero.png) Branchenyheder Digitalt batteripas 2027: Hvad producenter skal vide nu Webinarer, open source-værktøjer og nye standarder: EU's batteripas vinder frem. Et overblik over status i juli 2026 og de åbne spørgsmål frem til februar 2027.](/da/blog/sector-20260713/)
- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/sector-20260711/hero.png) Branchenyheder Digitalt batteripas 2026: Testmiljøer, standarder og åbne spørgsmål Hvor langt er industrien nået med det digitale batteripas? Et overblik over testmiljøer, CEN/CENELEC-standarder, open source-værktøjer og lovgivningsmæssige tiltag i juli 2026.](/da/blog/sector-20260711/)

[← Alle artikler](/da/blog/) [Kom gratis i gang](https://app.qr3.app/sign-up)
