GS1 Resolver
GS1 Resolver
The GS1 resolver is the public read surface for a DPP. The canonical URLs look like this:
https://qr3.app/01/{GTIN}https://qr3.app/01/{GTIN}/10/{LOT}https://qr3.app/01/{GTIN}/21/{SERIAL}https://qr3.app/01/{GTIN}/10/{LOT}/21/{SERIAL}When creating a DPP (POST /v1/dpp), the following rules apply: serial and lot must use safe GS1 path segments only: A-Z, a-z, 0-9, ., _, ~, -, with a length of 1 to 20 characters. Reserved URL separators are rejected so the canonical link stays resolvable.
Content negotiation
The same resolver returns different representations depending on the Accept header:
| Accept | Response |
|---|---|
text/html | consumer HTML |
application/ld+json | JSON-LD |
application/json | raw DPP JSON |
application/linkset+json | linkset with alternates |
The JSON representation (application/json, ?format=json) is the public passport: product data, links and registration status, without internal identifiers. workspace_id, organization_id, code_id and created_by (the ID of the API key that created the passport) are not part of it; the authenticated GET /v1/dpp/:id returns them. The internal validation result of the passport, is_valid and validation_errors, is not part of it either; the authenticated GET /v1/dpp/:id returns it.
Public routes
GET /01/...is the canonical resolverGET /dpp/:gtin/:serial?lot=...is an HTML aliasGET /v1/dpp/:id/qr.svgserves SVGGET /v1/dpp/:id/qr.pngserves PNGGET /v1/dpp/:id/qr.pdfserves PDFGET /v1/dpp/:id/qr.epsserves EPS
QR asset visibility follows the DPP status:
liveis public without authenticationdraftandarchivedrequire a valid auth context plus workspace access- Invalid auth returns
401 - Non-visible or foreign-workspace passports return
404
Which organization a GTIN resolves to
Several organizations can hold passports with the same GTIN. The resolver only returns passports of the organization that owns the GTIN:
- Verified: the organization that verified the GTIN, or a GS1 Company Prefix the GTIN starts with. A self-registered identifier (
POST /v1/gs1/identifiers) is not a verification. - Otherwise first: the organization that has held the GTIN the longest without a break. An organization holds a GTIN as long as it has at least one passport for it that has not been deleted, whatever its status; its claim counts from the first passport of that period, so editing or deleting individual passports does not change it. Once it has no passport left, the claim ends; a passport it creates later starts a new claim.
A deleted organization counts for neither rule.
Within that organization, the most recently updated live passport with the requested GTIN, serial and lot is returned. If it has none, the resolver delegates to GS1 (see Fallback), even if another organization has a matching passport. The same applies to /dpp/…, /dpp/dpp_… and, without authentication, to the QR assets and the image list of a passport: a passport of another organization returns 404. With your own key you always see your own passports.
Fallback
Without a local match, the GS1 resolver redirects with 307 to https://id.gs1.org. For the GTIN alias /dpp/:gtin/:serial?lot=..., this also applies to an invalid GTIN check digit: gtin, lot, and serial are encoded individually as URL path segments, including reserved separators. The redirect confirms neither GTIN validity nor data availability at GS1.
Exception: if a decoded identifier is only . or .., the alias without a local match responds with 422, application/problem+json, type https://docs.qr3.app/errors/validation, and the affected field in errors[], without a redirect. URL parsers normalize these segments even in encoded form. Values such as LOT.1 and ... remain eligible for delegation. This exception concerns only this alias without a match; creation validation, the canonical resolver, and existing matches remain unchanged.
GET /dpp/{GTIN}/UNKNOWN?lot=LOT%2F1307 Location: https://id.gs1.org/01/{GTIN}/10/LOT%2F1/21/UNKNOWN
GET /dpp/{GTIN}/UNKNOWN?lot=.422 Content-Type: application/problem+jsonPractical flow
- Create the DPP in the dashboard.
- Use the GS1 URI as the QR target.
- Let consuming systems request the representation they need via
Accept.