splide/code/technical proof

A public GS1-conformant resolver. Test the claim yourself.

Splide operates id.splide.com against version 1.2.1 of the GS1-Conformant Resolver Standard. The endpoint, the examples and the test suite are all public, so the evidence does not depend on a badge or a sales claim.

Conformance without theatre

GS1 publishes the standard and a browser-based conformance test suite, and this endpoint passes it. GS1 operates no certification, accreditation or badge programme for resolvers, so we do not claim to be GS1-certified or GS1-accredited. The narrower claim is the useful one: the service is public, the standard is public, and anyone can run the published tests against it.

What it is

The service, stated precisely

Every value below is answered by the live service, not by documentation.

Standard
GS1-Conformant Resolver Standard 1.2.1
Endpoint
https://id.splide.com
Primary keys
GTIN and the other fourteen GS1 keys
Qualifiers
/01/{gtin}[/22/{cpv}][/10/{lot}][/21/{serial}]
Linksets
application/linkset+json, RFC 9264
Description file
/.well-known/gs1resolver
Transport
HTTPS, CORS, GET HEAD OPTIONS
Resolution

A request, and what it answers

Run these against the live service and you get the same thing. This is the whole argument for operating one.

curl -I https://id.splide.com/01/09520123456788
HTTP/2 307
location: https://demo.splide.com/karoo-roast
link: <https://id.splide.com/01/09520123456788?linkType=linkset>;
      rel="linkset"; type="application/linkset+json",
      <https://ref.gs1.org/standards/resolver/linkset-context>;
      rel="http://www.w3.org/ns/json-ld#context"

The default link for that GTIN, with the linkset and the JSON-LD context both advertised in the Link header as the standard requires.

curl -H 'Accept: application/linkset+json' https://id.splide.com/01/09520123456788
HTTP/2 200
content-type: application/linkset+json

link types: pip, allergenInfo, nutritionalInfo,
            recipeInfo, sustainabilityInfo,
            defaultLink, defaultLinkMulti

One pack, seven answers. Which one a scanner gets depends on what it asked for and what language it asked in.

curl -I -H 'Accept-Language: af' https://id.splide.com/01/09520123456788
HTTP/2 307
location: https://demo.splide.com/karoo-roast/af

The same printed code, a different destination, because the request asked in a different language.

Behaviour

What the endpoint does with an awkward request

Re-verified against production on 4 September 2026. The two that matter most are the two easiest to get wrong: an unmatched link type must not fall back to the default, and the qualifier order is fixed.

Known GTIN, no link type
307 to the default link
Link type with a match
307 to that link
Link type with no match
404, never a silent fallback
Unknown GTIN
404
Invalid check digit
400
Qualifiers out of the fixed order
400
GTIN-13 given unpadded
307, normalised to 14 digits
Serial with no entry of its own
307, walked up to its batch
linkType=all
200, application/linkset+json
/.well-known/gs1resolver
200
HEAD
307, same headers, no body
OPTIONS
204, Allow: GET, HEAD, OPTIONS
POST
405

What the URI structure actually addresses

The part that gets undersold, including by us until recently. A Digital Link URI is not a redirect with extra steps. It is an addressing scheme with four independent axes, and we implement all four.

Identifier type. GTIN is one of fifteen primary keys we answer on:

00 SSCC logistics units, cases and pallets 01 GTIN trade items 253 GDTI documents 255 GCN coupons 401 GINC / 402 GSIN consignments and shipments 414 GLN / 417 PARTY physical locations and parties 8003 / 8004 GRAI / GIAI returnable and individual assets 8006 ITIP components and pieces of a trade item 8010 CPID components and parts 8013 GMN product models 8017 / 8018 GSRN service relationships

So the addressable estate is not just retail packs. It is cases, pallets, locations, assets, equipment, models, parts and service relations.

Granularity. Within a GTIN, the qualifier chain narrows the subject:

  • /01/{gtin} identifies the product.
  • /01/{gtin}/22/{cpv} identifies a consumer product variant.
  • /01/{gtin}/10/{lot} identifies a specific batch or lot.
  • /01/{gtin}/10/{lot}/21/{serial} identifies one individual unit.

The order is fixed and enforced. Anything else is malformed and returns 400 rather than a best guess.

Resolution walks up the chain. A request for a serial we hold no entry for falls back to its batch, and then to the product, rather than 404ing. Verified live: /01/09520123456801/10/AB2143/21/0001 resolves today even though no serial-level entry exists for it. That is what lets a customer start at product level and add batch or unit depth later, against packaging that is already printed and already in the field.

Link type. The request names which kind of answer it wants, from GS1's published vocabulary, so a machine can ask a precise question. We currently serve pip, recipeInfo, nutritionalInfo, allergenInfo, sustainabilityInfo and the default link on the demonstration data, and the vocabulary itself is open, covering instructions, safety data sheets, certification, traceability, warranty, recall status, repair and end-of-life information.

Request context. Accept-Language and Accept both participate, so the same URI returns a different destination for a different language, and a different representation for a machine than for a browser.

The four axes are independent, which is the point. One printed code, and the answer is a function of who asked, what they asked for, when, and how precisely they named the subject.

The linkset is a discovery surface, not product master data

?linkType=all with Accept: application/linkset+json returns every link the subject has, as RFC 9264, anchored on the canonical URI.

The response contains typed links and language metadata. It does not contain the authoritative allergen, nutrition or compliance record itself. A retailer, marketplace, distributor or regulator can discover the destinations associated with a product identifier, but access to the data behind those destinations still follows the owner's permissions and the relevant trading relationship.

That distinction matters in South Africa. GDSN and Trusted Source data is published and subscribed to between authorised trading partners. A public linkset does not turn it into an open product database. A real implementation has to connect the link destinations to an approved source and preserve the data owner's publication rules.

For Digital Product Passport work under the EU's ESPR, GS1 identifiers and a Digital Link URI can provide a compatible persistent identity and web access pattern. The regulation requires an interoperable data carrier connected to a persistent unique product identifier. It does not mandate GS1 Digital Link or a conformant resolver, and the product-specific delegated acts determine the actual data and carrier requirements.

Resolution changes are applied at the source

The live service applies link changes without a restart or deployment. The Cloudflare Worker handles resolution directly and the service does not configure an application or edge cache for those responses. It emits no Cache-Control, Expires, ETag, Age or Pragma header.

That describes what Splide controls at the source. It is not a claim that an external client or intermediary can never retain a response. Safety-critical workflows still need connected applications and retailer processes designed for their own freshness requirements. A batch notice changes what a fresh connected request receives; it does not by itself remove stock or stop a checkout.

What is running

  • Cloudflare Workers with D1 for link data, so there is no origin server, no home connection and no single machine in the path.
  • Multi-tenant from the first line of code. The service reads the request Host header and answers from that customer's link set, which is what allows a brand's codes to carry their own domain while we operate what answers. A GTIN registered under one host returns 404 on another.
  • A previous deployment, on a hardened Debian host behind a Cloudflare Tunnel, is still running as a rollback target. Reverting is one DNS record.
  • Written from scratch rather than adopted. We evaluated GS1's community reference implementation first and rejected it: it disclaims conformance, is not maintained by GS1 and has community-only support. Operating the service is the point, so the code had to be something we could actually answer for.

Latency, since somebody always asks: roughly 210ms from Pretoria. D1 has no African region, so the database sits in Western Europe and that is the floor. This was a deliberate trade of about 175ms against removing every single-point-of-failure from the path, and it is the right way round for something that has to answer for years.

Where the demo is

demo.splide.com carries a demonstration brand on the GS1 952 prefix, which is reserved for exactly this purpose.

  • /01/09520123456788 resolves to a product page.
  • The same code with linkType=gs1:recipeInfo reaches a brewing guide, and there are nutritional, allergen and sustainability link types alongside it.
  • Accept-Language: af returns a genuine Afrikaans page, translated, not the English page wearing a language tag.
  • Batch AB2143 of a second product carries a pre-written recall notice that can be switched on and off. When it is on, that batch answers with the notice while the product page and every other batch are untouched. No restart, no redeploy, and the change is live in about a second.

What we are looking for

Splide is an operations company, not a printer or product-data owner. We are looking for one controlled retailer or brand pilot in which product identity, packaging, printing, verification, authorised product data and branded digital destinations are implemented as one operating system.

Our role is to coordinate that implementation and remain accountable for the infrastructure and destinations we operate after launch. We work alongside the printers, verification providers, data specialists and internal retail teams that already own their parts of the process rather than competing with them.

Where this leads commercially

The machinery above exists to serve one thing: a controlled product-range pilot that keeps answering after the packaging is printed.

Get in touch

Building a resolver is finite. Operating its answers is not.

Plan one controlled product-range pilot