The GS1 Web Vocabulary link types and audience contexts used to build and resolve GS1 Digital Link URIs — as a small Go package and as a plain JSON file.
A GS1 Digital Link can expose several destinations behind one product identifier, each labelled with a link type, which a client then asks for by name:
https://id.example.com/01/09506000134369?linkType=dpp
This repository is the canonical list of those tokens.
Anything that touches Digital Link — the thing that stores a destination, the thing that validates it, the resolver that serves it, the UI that offers the choice — needs the same vocabulary. Keeping a copy in each one guarantees they drift, and drift shows up as the same token being accepted in one place and rejected in another.
So: one list, in a form both Go and non-Go consumers can read.
go get github.com/UnitagEngineering/gs1import"github.com/UnitagEngineering/gs1"// Validate what a client asked you to store. Accepts "dpp" and "gs1:dpp",// returns the bare token you should persist and compare.token, ok:=gs1.NormalizeLinkType("gs1:dpp") // "dpp", true// Interpret a value arriving in a URL. Also accepts a full vocabulary URI,// because a client that read one out of a linkset may send it straight back.token, ok=gs1.ParseLinkType("https://ref.gs1.org/voc/dpp") // "dpp", true// Scope a destination to an audience.aud, ok:=gs1.NormalizeContext("patient") // "patient", true// Build the rel URI and title for a linkset entry or a Link header.gs1.RelURI("dpp") // "https://ref.gs1.org/voc/dpp"gs1.Label("dpp") // "Digital Product Passport"// Enumerate, e.g. to populate a picker.for_, lt:=rangegs1.LinkTypes() {
fmt.Println(lt.Token, lt.Label)
}Two entry points, deliberately separate:
| Accepts | Use for | |
|---|---|---|
NormalizeLinkType / NormalizeContext | dpp, gs1:dpp | validating what a client asks you to store |
ParseLinkType / ParseContext | the above, plus https://ref.gs1.org/voc/dpp and the legacy https://gs1.org/voc/dpp | interpreting a value arriving in a URL |
Being forgiving with inbound URLs is useful. Letting that leniency widen what a write may store is not — hence the split.
linktypes.json is the artifact, embedded into the Go
package at build time rather than duplicated. Read it directly:
{
"vocabulary": "https://ref.gs1.org/voc/",
"source": "https://ref.gs1.org/voc/ (GS1 Web Vocabulary)",
"linkTypes": [
{ "token": "dpp", "label": "Digital Product Passport" }
],
"contexts": ["consumer", "healthcareProfessional", "patient", "recycler", "retailer", "supplier"]
}Its shape is covered by tests, so it is a contract rather than an internal detail.
Tokens are bare.dpp, not gs1:dpp and not the full URI. The prefix is a
display form and the URI is a rel; both normalize back to the bare token, which
is what you should store and compare.
Tokens are case-sensitive, matching the vocabulary itself.
defaultLink and defaultLinkMulti are absent. They describe a code's
default destination rather than one you assign, so accepting them where a link
type is expected would let a caller configure something unreachable. A resolver
answers the default from the code itself.
ref.gs1.org is the namespace host. It dereferences, and it is the form the
GS1 resolver test suite uses. The bare gs1.org/voc/ host is the JSON-LD CURIE
expansion and redirects; it is accepted on input, never emitted.
The vocabulary is published by GS1 at
ref.gs1.org/voc. This repository redistributes the
link-type and audience identifiers for programmatic use; GS1 remains the source
of truth for the standard. When GS1 revises the vocabulary, update
linktypes.json and cut a release.
Semantic versioning. Adding tokens is a minor release; removing one, or changing the meaning of an existing function, is a major.