Die meisten Artikel über den EU Digital Product Passport (DPP) erklären, was ein Passport enthalten muss. Deutlich seltener zeigt jemand, wie man einen erstellt — und fast nie, wie man das für einen Katalog mit 500 oder 50.000 Artikeln tut, ohne 50.000-mal ein Formular auszufüllen.
Dieser Leitfaden ist die Entwickler-Version. Jeder Schritt unten ist ein echter, funktionierender Aufruf gegen die qr3.app-API (https://qr3.app/v1). Wenn deine Produktdaten in einem ERP, PIM oder einer Datenbank liegen, kannst du die DPP-Erstellung direkt in deine bestehende Pipeline einbinden.
Warum eine API für DPPs entscheidend ist
Ein Digital Product Passport ist kein Einmal-Dokument. Unter der Ökodesign-Verordnung (ESPR, EU 2024/1781) und der EU-Batterieverordnung 2023/1542 braucht jede regulierte Einheit einen Passport, der über die gesamte Lebensdauer aktuell bleibt. Für Hersteller bedeutet das:
- Skalierung — Hunderte bis Zehntausende Produkte, jedes mit eigener GTIN/Seriennummer.
- Aktualität — Daten (CO₂-Fußabdruck, Rezyklatanteil, Reparaturinfos) ändern sich und müssen aktualisiert, nicht neu erstellt werden.
- Integration — die Datenquelle ist dein ERP/PIM, nicht ein Web-Formular.
Das ist ein API-Problem. Ein manuelles Web-Tool bringt dir die ersten zehn Passports; eine API bringt dir alle.
1. Authentifizierung
Jeder Request nutzt einen Bearer-Token (API-Key im Dashboard erstellen). Die Basis-URL ist https://qr3.app/v1.
curl https://qr3.app/v1/dpp \
-H "Authorization: Bearer $QR3_API_KEY"
Oder mit dem offiziellen SDK:
import { QR3 } from "@qr3/sdk";
const client = new QR3({ apiKey: process.env.QR3_API_KEY! });
2. Einen Batterie-Passport anlegen
Ein DPP wird mit POST /dpp erstellt. Die Top-Level-Felder sind für jede Kategorie gleich; die kategoriespezifischen Daten landen in battery_data, textile_data oder general_data.
curl -X POST https://qr3.app/v1/dpp \
-H "Authorization: Bearer $QR3_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"gtin": "09506000134376",
"serial": "SN-00012345",
"product_name": "PowerCell 5 kWh LFP",
"manufacturer": "ExampleTech GmbH",
"origin_country": "DE",
"category": "battery",
"market_countries": ["DE", "FR", "AT"],
"status": "live",
"battery_data": {
"capacity_kwh": 5,
"carbon_footprint_kg": 62,
"carbon_footprint_class": "B",
"recycled_content_pct": 12,
"recyclability_pct": 95,
"manufacturer_warranty_years": 8,
"lithium_content_pct": 6.5,
"certifications": ["CE", "UN38.3"]
}
}'
Derselbe Aufruf mit dem SDK:
const passport = await client.dpp.create({
gtin: "09506000134376",
serial: "SN-00012345",
product_name: "PowerCell 5 kWh LFP",
manufacturer: "ExampleTech GmbH",
origin_country: "DE",
category: "battery",
market_countries: ["DE", "FR", "AT"],
battery_data: {
capacity_kwh: 5,
carbon_footprint_kg: 62,
recycled_content_pct: 12,
recyclability_pct: 95,
manufacturer_warranty_years: 8,
},
});
console.log(passport.id); // dpp_xxxxxxxx
console.log(passport.qr.svg); // druckfertiger GS1-Digital-Link-QR
Die Antwort enthält eine verbrauchergerechte Landingpage (lokalisiert in 25 EU-Sprachen) und einen GS1-Digital-Link-QR-Code, fertig für den Etikettendruck — kein separater QR-Schritt nötig.
3. Validieren, bevor du anlegst
Fehlende oder ungültige Felder vor dem Speichern abfangen? POST /dpp/validate führt exakt die EU-Validierungsregeln aus, ohne etwas anzulegen. Ideal als Pre-Commit-Check in CI.
const result = await client.dpp.validate({
gtin: "09506000134376",
product_name: "PowerCell 5 kWh LFP",
manufacturer: "ExampleTech GmbH",
origin_country: "DE",
category: "battery",
battery_data: {
capacity_kwh: 5,
carbon_footprint_kg: 62,
recycled_content_pct: 12,
recyclability_pct: 95,
manufacturer_warranty_years: 8,
},
});
if (!result.valid) {
console.error(result.errors);
// [{ field: "battery_data.recyclability_pct", message: "..." }]
}
4. Einen ganzen Katalog per Batch anlegen
Für einen Produktkatalog sendest du bis zu 100 Passports pro Request an POST /dpp/batch. Über deinen ERP-Export iterieren — und dein ganzes Sortiment steht in Minuten.
const items = products.map((p) => ({
gtin: p.gtin,
serial: p.serial,
product_name: p.name,
manufacturer: "ExampleTech GmbH",
origin_country: "DE",
category: "battery" as const,
battery_data: {
capacity_kwh: p.capacityKwh,
carbon_footprint_kg: p.co2Kg,
recycled_content_pct: p.recycledPct,
recyclability_pct: p.recyclablePct,
manufacturer_warranty_years: p.warrantyYears,
},
}));
// In Blöcke à 100 aufteilen
const result = await client.dpp.batch({ items: items.slice(0, 100) });
5. QR-Code für den Etikettendruck holen
Jeder Passport stellt seinen GS1-Digital-Link-QR in vier Druckformaten bereit. Über das Passport-Objekt oder direkt:
curl https://qr3.app/v1/dpp/dpp_xxxxxxxx/qr.svg \
-H "Authorization: Bearer $QR3_API_KEY" -o label.svg
qr.svg, qr.png, qr.pdf und qr.eps sind verfügbar — SVG/EPS für den Etikettendrucker, PNG fürs Web.
6. Daten aktuell halten (ohne den QR zu brechen)
GTIN/Seriennummer/Charge sind nach der Erstellung unveränderlich — das hält die gedruckte GS1-URI für immer stabil. Alles andere lässt sich mit PUT /dpp/{id} aktualisieren:
await client.dpp.update(passport.id, {
battery_data: {
capacity_kwh: 5,
carbon_footprint_kg: 58, // neu gemessen, niedriger
recycled_content_pct: 16, // 2031-Ziel früh erreicht
recyclability_pct: 95,
manufacturer_warranty_years: 8,
},
});
Der QR auf dem physischen Produkt ändert sich nie; die Daten dahinter schon. Genau das ist der Sinn eines dynamischen Passports.
7. An das EU-Register übermitteln
Sobald das zentrale EU-DPP-Register für dein Produkt relevant ist, übermittelst du einen Passport mit einem Aufruf (ab Business-Plan):
const reg = await client.dpp.registerForEuRegistry(passport.id);
console.log(reg.data.eu_registry_status); // "pending"
console.log(reg.data.registry_request_id);
8. Auf Scans mit Webhooks reagieren
DPP-Scans sind Events. Abonniere qr.scanned und du kannst sie in deine Analytics streamen, Nachbestellungen auslösen oder einen Rückruf markieren — in Echtzeit. Payloads sind signiert (HMAC-SHA256); verifiziere die Signatur immer.
import { verifyWebhook } from "@qr3/sdk";
app.post("/webhooks/qr3", async (req, res) => {
const event = verifyWebhook(req.body, req.headers["qr3-signature"], secret);
if (event.type === "qr.scanned") {
console.log(event.data.country, event.data.dpp_id);
}
res.sendStatus(200);
});
Alles zusammen: DPP-Generierung in CI
Der Endzustand, den die meisten Hersteller wollen: Produktdaten leben im ERP/PIM, und ein geplanter Job hält die Passports synchron.
- Geänderte Produkte aus dem ERP exportieren.
- Jedes per
client.dpp.validate(...)prüfen — Build bei Validierungsfehlern abbrechen. - Neue Produkte per
client.dpp.batch(...), geänderte perclient.dpp.update(...). - Die zurückgegebenen
qr.svg-URLs an dein Etiketten-Drucksystem schieben.
Kein Web-Formular, kein Copy-Paste, keine Drift zwischen Stammdaten und Passports.
FAQ
Brauche ich ein separates QR-Code-Tool? Nein. Jeder DPP liefert einen GS1-Digital-Link-QR in SVG/PNG/PDF/EPS. Der QR ist der Zugangspunkt zum Passport.
Kann ich einen Passport nach dem Etikettendruck noch ändern?
Ja — das ist die Kernidee. GTIN/Seriennummer sind unveränderlich, damit die gedruckte URI gültig bleibt; alle Datenfelder sind über PUT /dpp/{id} aktualisierbar.
Wie viele Passports kann ich auf einmal anlegen?
Bis zu 100 pro POST /dpp/batch-Request. Größere Kataloge aufteilen; Rate-Limits gelten je Plan.
Welche Kategorien werden unterstützt?
battery und textile haben heute volle EU-Validierung; general deckt weitere Produkttypen ab. Batterie und Textil enthalten eine Live-EU-Compliance-Prüfung (ESPR / AGEC).
Quellen
Kostenlos starten und deinen ersten DPP per API erstellen: app.qr3.app/sign-up