---
title: "Generate EU Digital Product Passports via API — qr3.app Blog"
description: "Most DPP guides tell you what a passport must contain. This one shows how to create EU-compliant Digital Product Passports programmatically — with curl, the qr3 SDK, batch creation, validation, GS1 QR codes and webhooks."
canonical: "https://qr3.app/en/blog/dpp-api-generate-passports/"
lang: "en"
robots: "index,follow,max-image-preview:large,max-snippet:-1"
---

# Generate EU Digital Product Passports via API — qr3.app Blog

> Most DPP guides tell you what a passport must contain. This one shows how to create EU-compliant Digital Product Passports programmatically — with curl, the qr3 SDK, batch creation, validation, GS1 QR codes and webhooks.

Canonical: <https://qr3.app/en/blog/dpp-api-generate-passports/>

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

May 30, 2026 4 min read [Tutorials](/en/blog/category/tutorials/) [dpp](/en/blog/tag/dpp/)[api](/en/blog/tag/api/)[gs1-digital-link](/en/blog/tag/gs1-digital-link/)[developers](/en/blog/tag/developers/)[eu-2024-1781](/en/blog/tag/eu-2024-1781/)

# Generate EU Digital Product Passports via API

Most DPP guides tell you what a passport must contain. This one shows how to create EU-compliant Digital Product Passports programmatically — with curl, the qr3 SDK, batch creation, validation, GS1 QR codes and webhooks.

by **QR3 Redaktion**

![Generate EU Digital Product Passports via API](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/dpp-api-generate-passports/hero.png)

Most articles about the EU Digital Product Passport (DPP) explain *what* a passport must contain. Far fewer show you *how* to create one — and almost none show you how to do it for a catalog of 500 or 50,000 SKUs without clicking through a form 50,000 times.

This guide is the developer's version. Every step below is a real, working call against the qr3.app API (`https://qr3.app/v1`). If you manage product data in an ERP, a PIM or a database, you can wire DPP generation straight into your existing pipeline.

## Why an API matters for DPPs

A Digital Product Passport is not a one-off document. Under the [Ecodesign for Sustainable Products Regulation (ESPR, EU 2024/1781)](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1781) and the [EU Battery Regulation 2023/1542](https://eur-lex.europa.eu/eli/reg/2023/1542/oj), every regulated unit needs a passport that stays current over its entire lifetime. For a manufacturer that means:

- **Scale** — hundreds to tens of thousands of products, each with its own GTIN/serial.

- **Freshness** — data (carbon footprint, recycled content, repair info) changes and must be updated, not re-created.

- **Integration** — the source of truth is your ERP/PIM, not a web form.

That is an API problem. A manual web tool gets you the first ten passports; an API gets you all of them.

## 1. Authentication

Every request uses a bearer token (create an API key in the dashboard). The base URL is `https://qr3.app/v1`.

```
curl https://qr3.app/v1/dpp \
  -H "Authorization: Bearer $QR3_API_KEY"
```

Or with the official SDK:

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

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

## 2. Create a battery passport

A DPP is created with `POST /dpp`. The top-level fields are the same for every category; the category-specific data goes into `battery_data`, `textile_data` or `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"]
    }
  }'
```

The same call with the 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);  // print-ready GS1 Digital Link QR
```

The response includes a consumer-facing landing page (localized into 25 EU languages) and a **GS1 Digital Link** QR code ready for label printing — no separate QR step required.

## 3. Validate before you create

Want to catch missing or invalid fields before persisting? `POST /dpp/validate` runs the exact EU validation rules without creating anything. Ideal as a 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. Batch-create a whole catalog

For a product catalog, send up to **100 passports per request** to `POST /dpp/batch`. Loop over your ERP export and you have your entire range in minutes.

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

// Chunk into batches of 100
const result = await client.dpp.batch({ items: items.slice(0, 100) });
```

## 5. Get the QR code for label printing

Each passport exposes its GS1 Digital Link QR in four print formats. Pull them via the passport object or directly:

```
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` and `qr.eps` are all available — SVG/EPS for your label printer, PNG for the web.

## 6. Keep data current (without breaking the QR)

The GTIN/serial/lot are **immutable** after creation — that keeps the printed GS1 URI stable forever. Everything else can be updated with `PUT /dpp/{id}`:

```
await client.dpp.update(passport.id, {
  battery_data: {
    capacity_kwh: 5,
    carbon_footprint_kg: 58, // re-measured, lower footprint
    recycled_content_pct: 16, // 2031 target reached early
    recyclability_pct: 95,
    manufacturer_warranty_years: 8,
  },
});
```

The QR on the physical product never changes; the data behind it does. That is the entire point of a *dynamic* passport.

## 7. Submit to the EU registry

When the EU central DPP registry is in scope for your product, submit a passport with one call (Business plan and up):

```
const reg = await client.dpp.registerForEuRegistry(passport.id);
console.log(reg.data.eu_registry_status);          // "pending"
console.log(reg.data.registry_request_id);
```

> **Status today:** the EU has not yet published the API of its central DPP registry. Until it does, this call is a test path — the status stays `pending` and no authority receives the passport. Once the API is live, the same call becomes the real submission.

## 8. React to scans with webhooks

DPP scans are events. Subscribe to `qr.scanned` and you can stream them into your analytics, trigger re-orders, or flag a recall — in real time. Payloads are signed (HMAC-SHA256); always verify the signature.

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

app.post("/webhooks/qr3", express.raw({ type: "application/json" }), (req, res) => {
  const expected = createHmac("sha256", secret).update(req.body).digest("hex");
  const expectedBytes = Buffer.from(`sha256=${expected}`);
  const receivedBytes = Buffer.from(String(req.headers["x-qr3-signature"] ?? ""));
  const ok =
    expectedBytes.length === receivedBytes.length &&
    timingSafeEqual(expectedBytes, receivedBytes);
  if (!ok) return res.sendStatus(401);

  const event = JSON.parse(req.body.toString("utf8"));
  if (event.type === "qr.scanned") {
    console.log(event.data.country, event.data.dpp_id);
  }
  res.sendStatus(200);
});
```

## Putting it together: DPP generation in CI

The end state most manufacturers want: product data lives in the ERP/PIM, and a scheduled job keeps the passports in sync.

1. Export changed products from your ERP.

2. `client.dpp.validate(...)` each one — fail the build on validation errors.

3. `client.dpp.batch(...)` new products; `client.dpp.update(...)` changed ones.

4. Push the returned `qr.svg` URLs to your label-printing system.

No web form, no copy-paste, no drift between your master data and your passports.

## FAQ

**Do I need a separate QR-code tool?**
No. Every DPP returns a GS1 Digital Link QR in SVG/PNG/PDF/EPS. The QR *is* the access point to the passport.

**Can I update a passport after the label is printed?**
Yes — that is the core idea. GTIN/serial are immutable so the printed URI stays valid; all data fields are updatable via `PUT /dpp/{id}`.

**How many passports can I create at once?**
Up to 100 per `POST /dpp/batch` request. Chunk larger catalogs; the limit is 60 requests per minute per API key, on every plan.

**Which categories are supported?**
`battery` and `textile` ship with full EU-validation today; `general` covers other product types. Battery and textile include a live EU compliance check (ESPR / AGEC).

## Sources

- [ESPR — Regulation (EU) 2024/1781](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1781)

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

- [GS1 Digital Link](https://www.gs1.org/standards/gs1-digital-link)

**Start for free** and create your first DPP via API: [app.qr3.app/sign-up](https://app.qr3.app/sign-up)

## Related posts

- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/gs1-resolver-test-suite-dpp-links/hero.png) Tutorials GS1 Resolver Test Suite: Reliably Test DPP Links Before Go-Live The stable GS1 test suite makes Resolver 1.2 testable. Verify redirects, linksets, CORS, languages, and error handling before go-live.](/en/blog/gs1-resolver-test-suite-dpp-links/)
- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/dpp-battery-passport-2027-20260715/hero.png) Industry News BatteryPass-Ready Launches Test Environment for the Digital Battery Passport The BatteryPass-Ready consortium launched a public test environment for the Digital Battery Passport on June 24, 2026 — ahead of the EU mandate taking effect in February 2027.](/en/blog/dpp-battery-passport-2027-20260715/)
- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/sector-20260713/hero.png) Industry News Digital Battery Passport 2027: What Manufacturers Need to Know Now Webinars, open-source tools, and new standards: the EU Battery Passport is gaining momentum. A July 2026 status overview and the open questions ahead of the February 2027 deadline.](/en/blog/sector-20260713/)
- [![](https://qr3-blog-agent.meistern.workers.dev/cdn/blog/sector-20260711/hero.png) Industry News Digital Battery Passport 2026: Test Environments, Standards, and Open Questions Where does industry stand on the Digital Battery Passport? An overview of test environments, CEN/CENELEC standards, open-source tools, and regulatory developments as of summer 2026.](/en/blog/sector-20260711/)

[← All articles](/en/blog/) [Start for free](https://app.qr3.app/sign-up)
