Skip to content

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:

AcceptResponse
text/htmlconsumer HTML
application/ld+jsonJSON-LD
application/jsonraw DPP JSON
application/linkset+jsonlinkset 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 resolver
  • GET /dpp/:gtin/:serial?lot=... is an HTML alias
  • GET /v1/dpp/:id/qr.svg serves SVG
  • GET /v1/dpp/:id/qr.png serves PNG
  • GET /v1/dpp/:id/qr.pdf serves PDF
  • GET /v1/dpp/:id/qr.eps serves EPS

QR asset visibility follows the DPP status:

  • live is public without authentication
  • draft and archived require 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:

  1. 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.
  2. 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%2F1
307 Location: https://id.gs1.org/01/{GTIN}/10/LOT%2F1/21/UNKNOWN
GET /dpp/{GTIN}/UNKNOWN?lot=.
422 Content-Type: application/problem+json

Practical flow

  1. Create the DPP in the dashboard.
  2. Use the GS1 URI as the QR target.
  3. Let consuming systems request the representation they need via Accept.