Un passeport numérique de produit est destiné à être lu par des personnes et par des machines : le système de réception d'un recycleur, une API douanière, le robot d'exploration d'une marketplace, le script d'un auditeur en développement durable. Une page HTML réservée aux humains ne suffit pas. Le passeport doit être lisible par les machines — une charge utile structurée qu'un programme peut analyser, relier et exploiter sans avoir à faire du scraping.
Ce guide s'adresse aux développeurs qui se posent la question évidente suivante : une fois que j'ai un DPP, comment une machine le lit-elle concrètement ? La réponse pour qr3, c'est le JSON-LD servi par le résolveur public. Nous allons montrer la véritable réponse, expliquer comment la même URL sert les humains et les machines, puis replacer EPCIS 2.0 — le standard d'événements GS1 complémentaire — dans son contexte.
Ce que signifie la lisibilité par les machines pour un DPP
La lisibilité par les machines, c'est bien plus que « renvoyer du JSON ». Pour un passeport produit, cela suppose trois choses :
- Structuré — des champs qu'un analyseur peut adresser (
gtin,name, …), et non du texte à scraper. - Typé et relié — des termes ancrés dans des vocabulaires partagés, de sorte que
Productait la même signification pour tout le monde. C'est le Linked Data du JSON-LD. - Stable à récupérer — une URL durable par article, qu'un script peut interroger avec un
GETpendant toute la durée de vie du produit.
JSON-LD (JSON for Linking Data) apporte ces trois propriétés. C'est du JSON ordinaire auquel s'ajoute un @context qui associe chaque clé à un terme d'un vocabulaire public — ici schema.org et le GS1 Web Vocabulary. Un robot d'exploration qui comprend déjà schema.org comprend le passeport sans aucune intégration sur mesure.
Le DPP sous forme de JSON-LD (vrai curl + réponse vérifiée)
Chaque passeport qr3 se résout à une URL GS1 Digital Link : https://qr3.app/dpp/{gtin}/{serial}. Ajoutez ?format=jsonld pour demander la vue Linked Data. Avec la démo de batterie en direct :
curl -s "https://qr3.app/dpp/04019999999902/DEMO-BAT-01?format=jsonld"
renvoie :
{
"@context": ["https://schema.org", "https://gs1.org/voc/"],
"@type": "Product",
"gtin": "04019999999902",
"name": "EcoMax 5000 (Demo)"
}
Trois points à noter :
@contextest un tableau de deux vocabulaires — schema.org pour le web en général etgs1.org/voc/pour les termes produits de GS1. Les clés se résolvent dans les deux.@type: "Product"indique à tout consommateur de Linked Data exactement de quel type d'entité il s'agit.- Les valeurs (
gtin,name) sont réelles et en direct — il s'agit de la charge utile effective, pas d'une maquette.
C'est là tout l'intérêt : le script d'un recycleur n'a pas besoin d'un client spécifique à qr3. Il effectue un GET HTTP, analyse du JSON-LD qu'il comprend déjà, et lit directement le GTIN et le nom du produit.
Une URL, deux publics : la négociation de contenu
La même URL https://qr3.app/dpp/{gtin}/{serial} sert un passeport HTML lisible par les humains et la vue machine — le serveur décide quoi renvoyer en fonction de ce que demande l'appelant. Deux façons de demander :
| Vous voulez | Paramètre de requête | Ou en-tête Accept |
|---|---|---|
| Page HTML pour humains | (par défaut) | Accept: text/html |
| JSON-LD (Linked Data) | ?format=jsonld |
Accept: application/ld+json |
| JSON brut | ?format=json |
— |
| Linkset (ressources liées) | ?format=linkset |
— |
| DCAT-AP (métadonnées de jeu de données) | ?format=dcat-ap |
— |
Ainsi, l'appareil photo d'un téléphone qui ouvre le QR code arrive sur le passeport HTML lisible, tandis qu'un script demande à l'URL identique du application/ld+json et obtient des données structurées :
# Vue machine via négociation d'en-tête — même URL, sans chaîne de requête
curl -s -H "Accept: application/ld+json" \
"https://qr3.app/dpp/04019999999902/DEMO-BAT-01"
Un identifiant, une URL, de multiples représentations. Le couple GTIN/numéro de série reste stable ; c'est la vue qui s'adapte à l'appelant. C'est exactement ce qui rend un DPP à la fois durable et interopérable.
Où s'inscrit EPCIS 2.0 (événements vs. passeport)
Une question récurrente : et EPCIS — n'est-ce pas le standard GS1 pour cela ? Distinction importante :
- Un DPP est la description statique d'un article produit — son identité, ses matériaux, son empreinte carbone, sa recyclabilité. Il répond à la question « qu'est-ce que cette chose ? » Le JSON-LD ci-dessus est ce cliché.
- EPCIS 2.0 est le standard GS1 pour les événements de la chaîne d'approvisionnement — les données de visibilité décrivant ce qui s'est passé, où, quand et pourquoi : un article a été commissionné, expédié, réceptionné, recyclé. Il répond à la question « qu'est-il arrivé à cette chose, et où se trouve-t-elle ? »
Ils sont complémentaires, pas concurrents. Le passeport vous dit que le produit est une batterie de 5,2 kWh avec 35 % de contenu recyclé ; un journal d'événements EPCIS vous dirait qu'elle a été fabriquée à Hambourg à une date donnée, qu'elle a transité par un centre de distribution et est arrivée chez un recycleur. EPCIS 2.0 est lui-même compatible JSON/JSON-LD, de sorte que les deux partagent la même vision du monde Linked Data et les mêmes identifiants GS1 (GTIN + numéro de série) comme clé de jointure.
Périmètre de qr3 (soyons précis) : qr3 produit le DPP au format JSON-LD — c'est ce que démontre cet article. qr3 ne fournit pas la capture d'événements EPCIS ni de points d'accès EPCIS. Considérez ici EPCIS 2.0 comme le standard conceptuel et complémentaire que vous adopteriez aux côtés d'un DPP pour une traçabilité complète de la chaîne d'approvisionnement, et non comme une fonctionnalité de qr3.
Le modèle mental est donc le suivant : le DPP (qr3, JSON-LD) est la fiche d'identité du produit ; EPCIS 2.0 (système distinct) est son journal de voyage. Mêmes identifiants, deux questions auxquelles on répond.
Générer un DPP qui expose du JSON-LD
Vous n'avez rien de particulier à faire pour « activer » le JSON-LD — créez le passeport et le résolveur sert automatiquement chaque représentation :
import { QR3 } from "@qr3/sdk";
const client = new QR3({ apiKey: process.env.QR3_API_KEY! });
const passport = await client.dpp.create({
gtin: "04019999999902",
serial: "SN-00012345",
product_name: "PowerCell 5 kWh LFP",
manufacturer: "ExampleTech GmbH",
origin_country: "DE",
category: "battery",
market_countries: ["DE", "FR", "AT"],
status: "live",
battery_data: {
capacity_kwh: 5,
carbon_footprint_kg: 62,
recycled_content_pct: 12,
recyclability_pct: 95,
},
});
// The passport now resolves at https://qr3.app/dpp/04019999999902/SN-00012345
// Humans get HTML; machines append ?format=jsonld (or send Accept: application/ld+json).
console.log(passport.qr.svg); // QR encodes the GS1 Digital Link to the resolver
Une fois créée, l'URL de l'article répond immédiatement aux deux publics — aucune étape de publication supplémentaire n'est nécessaire pour la vue machine.
FAQ
Pourquoi JSON-LD et pas du JSON brut ?
Le JSON brut est structuré mais pas auto-descriptif : un consommateur doit apprendre vos noms de champs. JSON-LD ajoute @context, qui associe chaque clé à des termes schema.org / GS1, de sorte que tout consommateur de Linked Data le comprend sans intégration sur mesure. Si vous avez seulement besoin d'une lecture rapide, ?format=json reste disponible.
qr3 implémente-t-il EPCIS 2.0 ? Non. qr3 produit le DPP au format JSON-LD. EPCIS 2.0 est le standard GS1 distinct et complémentaire pour les événements de la chaîne d'approvisionnement ; vous le feriez tourner en parallèle, relié par le GTIN + numéro de série partagés.
Comment obtenir la vue machine ?
Ajoutez ?format=jsonld à l'URL du résolveur, ou envoyez Accept: application/ld+json. Les deux renvoient la même charge utile Linked Data.
Le @context est-il stable ?
Il épingle schema.org ainsi que le GS1 Web Vocabulary (gs1.org/voc/) — deux vocabulaires publics et versionnés, de sorte que les consommateurs peuvent se fier au sens des termes.
Sources
- JSON-LD 1.1 (W3C Recommendation)
- GS1 Web Vocabulary
- GS1 EPCIS and CBV 2.0
- schema.org Product
- ESPR — Regulation (EU) 2024/1781
Commencez gratuitement et créez un DPP qui expose du JSON-LD : app.qr3.app/sign-up