A barcode is not a product. prodid is.
A permanent, open identifier for every physical product. Every barcode and part number resolves to it, and every fact about it names the source that said it.
Item · Acme
Trail Jacket
navy · M · sold in TR, DE
- material100% recycled polyester✓ acme.example
- weight480 g✓ acme.example
- nameAcme Trail Jacket, navy, Mlapsed · shop.example
The problem
Four codes, one jacket, and nothing joining them.
A product gets a new barcode for every market, pack size and packaging change, and its data sits in a different system for each one. When two of them disagree, one is quietly overwritten.
prodid gives the product itself an identifier that does not change when the barcode does.
09506000134352
retail unit for DE and TR
another GTIN
the same jacket in a two-pack
another GTIN
next year’s packaging
TJ-2041-NVY-M
manufacturer part number
One variant
9p2d4kv7mq3nbhxf
Never reused, never deleted. Every code that ever pointed here keeps working.
The model
Family, variant, item. Codes point at them; they are not them.
Each level has its own opid: 16 characters that encode nothing, so nothing about the product can make them wrong.
family · 3n7k2q9vdfhb4mta
Acme Trail Jacket
The product as people talk about it.
variant · 9p2d4kv7mq3nbhxf
navy · size M
One combination of colour, size and the like.
item · kq7m3v9dn2hb4t5x
Retail unit for DE and TR
The thing that carries a barcode.
- gtin09506000134352
- mpnTJ-2041-NVY-M
- skuTJ-2041-NVY-M
New packaging adds a new item with a new barcode, under the same variant and the same family. Nothing that pointed at the old one breaks.
How it works
Publish on your domain. prodid indexes it. Anyone resolves it.
01 · Publish
Three things on your domain
- /.well-known/prodid.json
- /prodid/items.ndjson
- _prodid TXT "v=prodid0; host=…"
A discovery document, a feed with one product per line, and a DNS record that proves the domain is yours.
How to publish →02 · Index
Checked, matched, attributed
- every line validated against the schema
- matched to an existing opid, or a new one
- each field stored as a claim by your domain
Retailers, registries and open datasets are sources the same way: beside the maker, never on top of it.
How claims work →03 · Resolve
One URL, printed on the product
prodid.org/01/09506000134352
Browser → a page
API → the JSON record
The path is GS1 Digital Link syntax, so it can be the QR code on the label itself.
How resolving works →
Claims
Every fact names its source. Disagreement stays visible.
Nothing is merged into one “truth”. When a source stops publishing, its claims are kept and marked lapsed, not deleted.
| Property | Value | Source | Trust | Seen |
|---|---|---|---|---|
| name | Trail Jacket | acme.example | verified | 2026-09-14 |
| brand | Acme | acme.example | verified | 2026-09-14 |
| material | 100% recycled polyester | acme.example | verified | 2026-09-14 |
| weight | 480 g | acme.example | verified | 2026-09-14 |
| media | image · CC-BY-4.0 | acme.example | verified | 2026-09-14 |
| markets | TR, DE | acme.example | verified | 2026-09-14 |
| name | Acme Trail Jacket, navy, M | shop.example | unverified · lapsed | 2026-08-02 |
- authoritative
- Controls the domain and is confirmed as the brand owner.
- verified
- Proved control of a domain through DNS or its own website.
- unverified
- A hosted name without a domain, a dataset, or a contribution.
GET /01/09506000134352 HTTP/1.1
Host: prodid.org
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Content-Location: /id/kq7m3v9dn2hb4t5x{
"$type": "org.prodid.entity",
"version": 1,
"opid": "kq7m3v9dn2hb4t5x",
"kind": "item",
"parents": {
"family": "3n7k2q9vdfhb4mta",
"variant": "9p2d4kv7mq3nbhxf"
},
"identifiers": [
{
"scheme": "gtin",
"value": "09506000134352"
},
{
"scheme": "mpn",
"value": "TJ-2041-NVY-M",
"scope": "acme"
},
{
"scheme": "sku",
"value": "TJ-2041-NVY-M",
"scope": "acme.example"
}
],
"claims": [
{
"property": "name",
"value": "Trail Jacket",
"lang": "en",
"source": {
"name": "acme.example",
"trust": "verified",
"lapsed": false
},
"seen_at": "2026-09-14T09:12:03Z"
},
{
"property": "brand",
"value": "Acme",
"source": {
"name": "acme.example",
"trust": "verified",
"lapsed": false
},
"seen_at": "2026-09-14T09:12:03Z"
},
{
"property": "properties.material",
"value": "100% recycled polyester",
"lang": "en",
"source": {
"name": "acme.example",
"trust": "verified",
"lapsed": false
},
"seen_at": "2026-09-14T09:12:03Z"
},
{
"property": "properties.weight",
"value": {
"value": 480,
"unit": "g"
},
"source": {
"name": "acme.example",
"trust": "verified",
"lapsed": false
},
"seen_at": "2026-09-14T09:12:03Z"
},
{
"property": "markets",
"value": "TR",
"source": {
"name": "acme.example",
"trust": "verified",
"lapsed": false
},
"seen_at": "2026-09-14T09:12:03Z"
},
{
"property": "markets",
"value": "DE",
"source": {
"name": "acme.example",
"trust": "verified",
"lapsed": false
},
"seen_at": "2026-09-14T09:12:03Z"
},
{
"property": "name",
"value": "Acme Trail Jacket, navy, M",
"lang": "en",
"source": {
"name": "shop.example",
"trust": "unverified",
"lapsed": true
},
"seen_at": "2026-08-02T17:41:55Z"
},
{
"property": "media",
"value": {
"sha256": "e3943ea26ce08ae81809e62936dc4f934fa04da6cd57bd9ab2a90b79da751c09",
"url": "https://acme.example/img/tj2041-navy.webp",
"media_url": "https://media.prodid.org/sha256/e3943ea26ce08ae81809e62936dc4f934fa04da6cd57bd9ab2a90b79da751c09",
"license": "CC-BY-4.0",
"kind": "image"
},
"source": {
"name": "acme.example",
"trust": "verified",
"lapsed": false
},
"seen_at": "2026-09-14T09:12:03Z"
}
]
}Who it is for
The people who make the data, and the people who need it.
Manufacturers
State your product data once, on your own domain. No reseller listing or marketplace owns the description of what you make.
Publish on your domain →E-commerce, ERP and PIM vendors
One discovery document and one feed per merchant domain, generated from data you already hold.
Choose a route →Developers
Resolve any code to an identifier that survives repackaging. Every fact says who said it, when, and whether that source still stands behind it.
Get the data →On the EU Digital Product Passport. ESPR asks for a passport reachable from a data carrier on the product, and GS1 Digital Link is one of the carrier syntaxes being standardised for it. prodid is not a passport service and publishing here is not compliance with anything; it is the same groundwork: one machine-readable record per product, at a stable address you control.
Status
Where this actually stands.
Spec v1. The index and the hosted publisher run on prodid.org. Anyone can publish, on their own domain or hosted.
- Stable
Specification v1. It changes only by addition; anything else would be v2. A v0 discovery document is accepted until 2027-01-26 00:00 UTC. Read it and say where it is wrong.
- Canary and one dataset
No publisher’s catalogue is indexed yet. The index holds two sources: the project's own canary, canary.prodid.org, which proves publishing, crawling and resolving end to end, and dataset:wikidata, a bounded test import of 5 Wikidata items, unverified and under CC0-1.0.
- By design
The index is replaceable. The spec, the schemas, the opids and the code mappings are CC0. Each claim keeps its source’s licence. The facts live on the domains that publish them, so anyone can crawl them again and printed codes keep their meaning.
Give your products an identity that outlives the barcode.
Two files and one DNS record on your own domain, or a hosted site with no domain at all.