DPP Agent docs

The resolve endpoint — the passport's own address

Every passport answers at its own address. The same address serves the passport page to a person, JSON or JSON-LD to a program, and a linkset of related links. No key is needed. The formats follow EN 18216 and the addressing follows GS1 Digital Link.

Address pattern

https://{slug}.dpp.dppagent.com/{scheme}/{id}[/{qualifier}/{value}…]

{slug} is the brand's tenant slug. A brand with its own verified domain (for example dpp.example.com, pointed at DPP Agent by DNS) serves the same paths there, and that domain becomes the passport's public address.

Path Identifier EN 18219
/01/{GTIN} GS1 GTIN, padded to 14 digits ID scheme 1
/8004/{GIAI} GS1 Individual Asset Identifier ID scheme 1
/products/{article} The brand's article number ID scheme 2
/battery/{id} Battery identifier ID scheme 2
/vin/{VIN} Vehicle identification number ID scheme 2
/c/{id} Another scheme the brand already runs ID scheme 2
/?.P={model}&.10B={batch}&.S={serial} EN IEC 61406-2 Identification Link ID scheme 2

GTIN qualifiers:

  • /22/{cpv} — consumer product variant
  • /10/{batch} — batch or lot
  • /21/{serial} — serial number

Examples:

https://example.dpp.dppagent.com/01/09506000134352
https://example.dpp.dppagent.com/01/09506000134352/10/AW26-001
https://example.dpp.dppagent.com/01/09506000134352/10/AW26-001/21/SR-00451

Content negotiation

The Accept header picks the form. Every response lists the others in its Link header (rel="alternate" for JSON and JSON-LD, rel="linkset" for the linkset) and carries Vary: Accept, Accept-Language.

text/html — the passport page

The default, and what a phone gets after scanning. The brand's page, rendered on the server, in the best language Accept-Language allows (Content-Language says which). Passport pages carry X-Robots-Tag: noindex, nofollow, noarchive unless the brand allows indexing.

application/json and application/ld+json

GET /01/09506000134352 HTTP/2
Accept: application/ld+json
{
  "@context": ["https://schema.org", "https://dppagent.com/vocab/dpp/v1"],
  "@id": "https://example.dpp.dppagent.com/01/09506000134352",
  "@type": "DigitalProductPassport",
  "dppId": "3f2a9b1c-e0d8-4f8e-b308-d2541886e331",
  "productIdentification": {
    "uniqueProductIdentifier": "https://example.dpp.dppagent.com/01/09506000134352",
    "gtin": "09506000134352",
    "cpv": null,
    "batch": null,
    "serial": null,
    "category": "textile"
  },
  "dppMetadata": {
    "digitalProductPassportId": "https://example.dpp.dppagent.com/01/09506000134352",
    "granularity": "model",
    "dppSchemaVersion": "1.0.0",
    "dppStatus": "active",
    "lastUpdated": "2026-06-11T07:54:32Z",
    "economicOperatorId": "PEPPOL:0007:5560000000",
    "facilityId": null,
    "linkToPreviousDPP": null,
    "backupHost": { "url": "…", "name": "…" }
  },
  "productData": {
    "espr.pid.product_name": "Pro Winter Jacket",
    "tex.journey.steps": ["…"]
  },
  "services": [
    { "type": "support", "label": "Support", "url": "https://example.com/help", "linkType": "gs1:support" }
  ]
}

application/json returns the same object without @context and @type. Restricted fields (for example the battery data Article 77(2) of the Battery Regulation reserves for authorities) are never in the public response. ?schema=cirpass-2 returns the data in the CIRPASS-2 shape instead.

?linkType=all returns every link the passport has as an RFC 9264 linkset, with Content-Type: application/linkset+json:

GET /01/09506000134352?linkType=all HTTP/2
{
  "linkset": [
    {
      "anchor": "https://example.dpp.dppagent.com/01/09506000134352",
      "itemDescription": "Pro Winter Jacket",
      "gs1:dpp": [
        { "href": "https://example.dpp.dppagent.com/01/09506000134352", "title": "Digital Product Passport (ESPR)", "type": "text/html", "hreflang": ["en"], "defaultLinkType": true }
      ],
      "gs1:instructions": [
        { "href": "https://example.dpp.dppagent.com/01/09506000134352#care", "title": "Care & use instructions" }
      ],
      "gs1:certificationInfo": [
        { "href": "https://example.dpp.dppagent.com/01/09506000134352#certifications", "title": "Certifications" }
      ]
    }
  ]
}

Link types, named as in GS1's registry:

Link type Present when
gs1:dpp always; the passport itself (the default link)
gs1:sustainabilityInfo always; an alias of gs1:dpp
gs1:pip the brand has a product page address
gs1:certificationInfo the passport lists certificates
gs1:traceability the passport has supply-chain steps or countries
gs1:instructions the passport has care or use instructions
gs1:safetyInfo the passport has safety information
gs1:recallStatus the passport is recalled
gs1:epcisRepository the passport names an EPCIS endpoint
service links (gs1:support and others) the brand has set up the service

A single link type, ?linkType=gs1:instructions:

  • from a browser, 303 See Other to the link's target;
  • with Accept: application/json, a linkset holding just that link;
  • 404 if the passport has no such link.

gs1:dpp (or no linkType) serves the passport itself. An unknown link type answers 404 with the supported list. Older names (gs1:digitalProductPassport, gs1:productInstructions, gs1:epcis, gs1:productSustainabilityInfo) are still accepted.

Lifecycle

dpp_status HTTP
active, replaced 200
recalled 200, with the recall shown and gs1:recallStatus
withdrawn, archived 410: a page explaining it for browsers, { "error": "DPP is no longer publicly resolvable", "status": "…" } for JSON
draft 404, unless opened with a preview link

?preview=1 shows a draft (or a withdrawn passport) with a preview banner, when the brand allows preview links; otherwise a signed preview link from the dashboard is needed.

Caching

Response Cache-Control
active or replaced passport, linkset public, s-maxage=300, stale-while-revalidate=86400
draft preview, withdrawn, archived public, s-maxage=10
not found public, s-maxage=10

s-maxage applies to the CDN, which holds a published passport for up to five minutes and serves the previous copy while it refreshes. A change to a passport is therefore public within about five minutes.

Rate limits

Reads are free and need no key, but one address gets at most 120 requests a minute; above that the answer is 429 with Retry-After and a plain-text body. Search-engine crawlers that identify themselves (Googlebot, Bingbot, Applebot and others) are not counted.

Query parameters

Param Values Effect
linkType all, or a link type See Links
schema cirpass-2 JSON in the CIRPASS-2 shape
src tag, label, web Where the code was scanned from; recorded with the scan
preview 1 Preview of a draft, see above

Sharing

The HTML page carries Open Graph tags (og:type, og:title, og:description, og:image, og:url), so a shared passport link shows the product. The image is the product's hero image, then the brand logo, then a placeholder.

Errors

Errors are JSON, or a page in the brand's style when the client asked for HTML.

Code Reason
400 Malformed path
404 No passport at this address, a draft, or a link type the passport does not have
410 Withdrawn or archived
429 Too many requests from one address