A QR code that opens a page in a browser does not yet prove that the underlying resolver is dependable. For a GS1 Digital Link resolver, the complete HTTP contract matters: Which identifiers are accepted? Which target is the default? Can the service return a machine-readable linkset? Do browser clients on other domains work? And do invalid or unavailable requests produce the correct errors?
The GS1-Conformant Resolver Standard 1.2.0 was published on 16 January 2026. The related public GS1 test suite is now described as stable, with its code last updated on 29 June 2026. That makes it possible to turn an abstract standard into a concrete acceptance test. This guide explains what to verify before go-live, where the public suite stops, and which evidence belongs in a technical release decision.
A successful scan is only the beginning
A GS1 Digital Link carries a GS1 identifier in an HTTPS URI. A resolver connects that identifier to one or more resources, such as a product page, instructions, a data sheet, or an API. Our primer explains the GS1 Digital Link resolver with a live example. A single successful default redirect, however, is not enough for production acceptance.
The Resolver Standard 1.2.0 requires, among other things, HTTPS, support for GET, HEAD, and OPTIONS, Cross-Origin Resource Sharing (CORS), a recognised default link, and linkset output. When linkType=linkset is supplied, or the Accept header is application/linkset+json, the resolver must not redirect. It must return the available typed links as a standalone representation.
This distinction matters. The human browser path can work while machine access, languages, link types, or error cases remain broken. A scan-only check will not reveal those differences.
A seven-step acceptance plan
1. Define representative test URIs
Do not start with a single showcase product. Build a small, versioned fixture set:
- at least one valid identifier for every supported GS1 primary key;
- a GTIN case without a qualifier;
- cases with a batch or serial number where that granularity is supported;
- a syntactically invalid identifier;
- a valid but unknown identifier;
- a known identifier without the requested link type.
The standard allows a resolver to support only a subset of GS1 primary keys. For every supported primary key, however, its qualifiers and data attributes must be fully supported. The fixtures therefore need to match the resolver's declared capability, not a broad marketing statement.
2. Check the default redirect and HTTP methods
First call the URI without special headers. The result should be a deterministic default link. Then test HEAD and OPTIONS: HEAD must not use different routing logic from GET, while OPTIONS should make the supported methods clear.
A minimal manual check looks like this:
curl -sS -D - -o /dev/null \
"https://id.gs1.org/01/09506000134352"
curl -sS -I \
"https://id.gs1.org/01/09506000134352"
Record the status code, Location, cache headers, and redirect count. A loop, a non-deterministic target, or method-specific routing is a release defect even if a smartphone eventually shows a page.
3. Request a linkset instead of a web page
The central machine-facing check is the linkset:
curl -sS \
-H "Accept: application/linkset+json" \
"https://id.gs1.org/01/09506000134352"
RFC 9264 defines application/linkset+json as a standalone JSON representation of typed web links. GS1 tightens that contract: the response must validate against the normative linkset schema for version 1.2.0. Do not merely check that the body parses as JSON. Verify the media type, schema, absolute target URIs, anchor, and link relations.
Formally valid but semantically wrong linksets are particularly dangerous. An instruction manual might be assigned the relation for a product information page, or a serial-level target may be registered at GTIN level. Schema validation and domain fixtures therefore belong together.
4. Inspect the resolver description
A conformant resolver publishes a machine-readable description at /.well-known/gs1resolver. It declares the resolver root and supported primary keys, among other capabilities. The document must validate against the GS1 schema for Resolver Description Files.
This test catches a common inconsistency: the service implements more or less than its own description claims. Acceptance should therefore include both schema validation and comparison with live test cases.
5. Test CORS and content negotiation
CORS is not an optional convenience. The standard requires it so browser-based applications can call the resolver across domains. Test at least one permitted browser origin and the preflight path. Also confirm that Accept: application/linkset+json and linkType=linkset produce consistent results.
Add a negative case for an unsupported media type. A service that always returns HTML regardless of the Accept header may be reachable by people but is not reliably machine-readable.
6. Cover language, context, and granularity
The standard provides Accept-Language and the context query parameter to distinguish among multiple matching links. A resolver does not have to offer every variant. If it supports language or context, however, its selection rules must be reproducible.
Test an available language, an unavailable language, and a defined fallback order. Apply the same principle to GTIN, batch, and serial granularity. A more granular identifier may incorporate relevant links from broader levels without obscuring their business meaning. Store the expected link set as a fixture; snapshots that assert only array order are too brittle.
7. Distinguish errors by meaning
Status codes are part of the contract. The resolver standard calls for HTTP 400 when a GS1 identifier is syntactically invalid. When a specific unavailable link type is requested, redirecting to the default target is not the correct behaviour. That case must also remain distinct from a syntactically valid but unknown identifier.
Check that error responses do not expose internal details, tokens, or stack traces, and that GET, HEAD, and browser-based requests preserve the same semantics. A polished HTML error page cannot compensate for a wrong status code.
How to use the GS1 test suite
The public suite accepts a Digital Link URI and checks the service against Resolver 1.2.0. It is useful as an independent smoke and conformance check. For release evidence, record the test date, URI, standard version, result, and any reproducible failures.
The suite does not replace your own regression coverage. GS1 explicitly notes that compression is not currently tested. If your resolver handles EPC binary strings or additional compressed forms, you need separate test vectors. The public suite also cannot know your domain-specific link relations, authorisation rules, tenant isolation, or availability targets.
A dependable process therefore combines three layers:
- the public GS1 suite as an external conformance check;
- schema tests for linksets and the resolver description in CI;
- owned end-to-end tests for real identifiers, roles, languages, and outages.
What belongs in the release record
An acceptance result is repeatable only when it is documented rather than merely visible in a browser. The release record should include the standard and suite versions, test time, target environment, test URIs, expected link types, HTTP results, schema validation, CORS result, and known exceptions.
Automate the stable checks in CI, while retaining a targeted run against the public suite before every material resolver change. This turns “the QR code opens” into a verifiable statement about identity, routing, and machine-readable product information.