Identification physique, QR et NFC

Choisir le porteur physique de vos produits, connaître la forme exacte du lien GS1 Digital Link, et savoir ce que chaque porteur demande avant la mise en production.

Sur cette page

Un produit physique doit porter quelque chose qu'un téléphone peut lire. Cette page vous donne les deux porteurs disponibles, le QR imprimé et le sceau NFC. En la quittant, vous saurez quelle adresse exacte est imprimée ou écrite dans la puce, ce que le serveur répond quand vous la lisez, ce que chaque porteur apporte au moment du scan, et le travail que chacun demande avant de lancer une production.

Le règlement ESPR autorise le passeport à trois niveaux : le modèle, le lot et l'exemplaire. L'acte délégué de votre groupe de produits décide lequel s'applique. Les formes d'adresse décrites ci-dessous couvrent les trois. Un passeport de modèle couvre tous les exemplaires qui partagent le même code produit, un passeport de lot tous les exemplaires d'un même lot.

Voici le trajet complet, du porteur physique jusqu'à la page que voit la personne qui scanne. Le reste de la page reprend chaque étape en détail.

Le chemin d'un scan, du porteur physique à la page publique

Deux colonnes séparées, une par porteur, qui se rejoignent en bas. À gauche, le QR imprimé sur l'étiquette porte une adresse fixe, toujours la même, sealtrust.io/p/0ABCDEFGHJKM, ou sa forme GS1 sealtrust.io/01/{gtin}/21/{serial}. Le résolveur remet le numéro en forme, retrouve l'unité, puis répond une seule redirection 302 : vers la page produit par défaut, vers la page passeport avec le paramètre linkType=dpp. À droite, le sceau NFC, une puce NTAG 424 DNA, complète lui-même l'adresse sealtrust.io/verify avec les paramètres e et c, et cette adresse change à chaque lecture. La page /verify appelle ensuite GET /sdm/verify-url, la signature de la puce et son compteur sont vérifiés, puis la page affiche un verdict suivi de la fiche : produit, marque, historique, compteur de lectures. Les deux colonnes aboutissent à une page web publique du site, sans application à installer, qui répond aux questions du scan et renvoie vers le passeport. Le QR identifie l'objet, le sceau NFC y ajoute une signature calculée par la puce, différente à chaque lecture.

Une marque, ou son revendeur, peut afficher ses passeports dans la page d'un partenaire. Quand elle l'a activé, le QR mène à la page du partenaire, et la page /verify, une fois la puce vérifiée, y envoie le visiteur avec un reçu de cette vérification : la puce n'est vérifiée qu'une fois. Voir Afficher le passeport dans votre page.

#Les trois combinaisons possibles

Chaque produit porte une valeur de méthode d'authentification. Le produit en stocke une parmi trois.

ValeurCe que porte le produit
qrUn code imprimé seul.
nfcUn sceau NFC seul.
nfc+qrLes deux sur le même produit.

Vous choisissez cette valeur à la création du produit, dans le formulaire de la console ou dans son import CSV. Renseignez-la toujours. Une valeur absente vaut nfc. Le serveur refuse alors la création en 403 si votre offre n'autorise que le QR. Pour un produit QR seul, écrivez explicitement qr.

Le serveur accepte aussi l'écriture nfc,qr et la casse haute. Écrivez exactement l'une des trois valeurs du tableau, dans l'une de ces écritures. Une autre valeur ne vous donne pas le porteur que vous demandez.

Demander une valeur qui contient nfc exige que votre offre autorise l'authentification NFC. Sinon le serveur répond un 403 portant le code AUTH_METHOD_NOT_ALLOWED, avec la méthode demandée et la liste de celles que votre offre autorise. Une demande qr seule n'exige pas cette autorisation.

#Le QR imprimé

#Ce qu'il encode

Le QR imprimé sur une unité encode une seule adresse, de cette forme :

Texte
https://sealtrust.io/p/0ABCDEFGHJKM

Le dernier segment est le numéro de série public de l'unité. Cette forme /p/{serial} est l'identifiant unique de produit destiné au registre européen, et c'est elle que porte l'étiquette. La génération du code refuse de produire une image pour une unité qui n'a pas de numéro de série.

#Ce qui se passe quand on le scanne

Trois lecteurs savent lire cette étiquette : l'appareil photo du téléphone, qui ouvre simplement l'adresse, l'application iOS, et le lecteur intégré à la page de vérification du site.

Ce lecteur du site n'accepte que les adresses de SealTrust, et cette restriction n'est pas une formalité : un QR est un texte écrit par un inconnu, et suivre son contenu sans le vérifier permettrait de coller une étiquette sur un produit pour envoyer un client vers un site de hameçonnage aux couleurs de la marque. Les formes acceptées sont celles que nous générons : /p/{serial}, /product/{serial}, /01/{gtin}, /01/{gtin}/21/{serial}, /passport/01/{gtin}, /verify, /certificate/{number} et /claim, avec ou sans préfixe de langue.

Le lecteur du site a aussi besoin de la caméra. La page l'autorise pour elle-même et pour elle seule : aucun cadre tiers embarqué ne peut la demander à travers nos pages.

#Le numéro de série

Le numéro fait douze caractères. Son alphabet compte trente-deux caractères : les chiffres de 0 à 9 et les lettres de A à Z privées de I, L, O et U. Nous retirons ces quatre lettres parce qu'elles se confondent avec des chiffres sur une étiquette.

Trois conséquences pratiques :

  • Le serveur corrige un numéro recopié à la main. Il lit un I et un L comme un 1, et un O comme un 0.
  • La casse n'a aucune importance. Le serveur remet le numéro en majuscules avant toute recherche.
  • Un numéro qui n'a pas la bonne longueur ou qui contient un caractère hors de cet alphabet reçoit un 404 immédiat.

Nous tirons le numéro au hasard. Il ne suit pas l'ordre de production et ne révèle donc ni vos volumes ni votre ancienneté.

#Ce qui se passe au scan

L'appareil photo d'un téléphone ouvre l'adresse. Le serveur répond une seule redirection 302 vers la page produit, sur le site public.

curl
curl -sS -i "https://sealtrust.io/p/0ABCDEFGHJKM"
HTTP
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/product/0ABCDEFGHJKM

Le serveur choisit la langue de la page à partir de l'en-tête Accept-Language du lecteur, parmi le français et l'anglais. Un lecteur qui n'en demande aucune des deux reçoit la langue déclarée pour la marque lorsqu'il scanne sur le domaine de cette marque, et l'anglais sinon. Il n'y a jamais qu'un seul saut de redirection.

La page produit répond aux questions qu'une personne se pose en scannant : ce qu'est l'objet, ce que la lecture prouve, qui le détient, où se trouve la preuve. Elle renvoie vers le passeport numérique.

Elle commence par un verdict, dans un cadre en tête de page, qui dit seulement ce que cette page peut prouver. Elle dit « Numéro enregistré » : le numéro existe bien chez la marque, mais un QR code se copie, il ne prouve donc pas à lui seul que l'objet tenu en main est l'original. Seule la lecture de la puce, sur la page de vérification, prouve l'objet. Sur la page produit, un certificat révoqué ou expiré est annoncé à la même place. La page du passeport commence par le même cadre ; pour un passeport de modèle ou de lot, elle le dit aussi : il décrit tous les exemplaires, pas celui que vous tenez.

Sur la page du passeport, une section dont aucun champ n'est rempli n'apparaît pas. Un passeport publié depuis un modèle sans rien compléter ne montre donc pas de titres vides : il ne montre que ce que la marque a réellement déclaré. Une section fermée affiche, quand c'est possible, un court résumé de ses premières valeurs, pour qu'on sache ce qu'elle contient avant de l'ouvrir. Les détails techniques de la preuve (empreinte, copie IPFS, ancrage sur Base) sont rangés à la fin, sous « Ce que prouve cette page, et ce qu'elle ne prouve pas ».

Quand notre service ne répond pas à temps, la page produit, la page du passeport et celle du certificat le disent : « Vérification momentanément indisponible », avec un bouton pour réessayer. Elles ne disent « introuvable » que lorsque notre service a répondu qu'il n'y a rien à cette adresse. Une panne ne dit rien de l'objet, et un visiteur ne doit jamais lire qu'un produit authentique n'existe pas.

La page produit propose aussi l'action qui suit la lecture, et la page du passeport la propose de la même manière. Tant que l'unité est encore au coffre de la marque, la page offre de la revendiquer, et le bouton mène droit à l'écran de revendication : il n'y a aucune adresse à deviner, et le numéro de série voyage dans le lien, donc personne ne le retape. C'est bien le numéro de série imprimé sur le produit, même quand la page a été ouverte par une adresse qui porte l'empreinte de la puce ou l'identifiant du jeton : la revendication n'accepte que le numéro de série. Une unité que la personne détient déjà lui propose de la transmettre. Une unité qui appartient à quelqu'un d'autre ne propose rien, et la page le dit plutôt que de laisser un bouton qui ne peut que refuser.

Sur votre propre domaine, la revendication se termine chez SealTrust, et le bouton le dit avant le clic. Vos pages de vérification, de passeport et de certificat restent entièrement chez vous : elles n'ont besoin d'aucun compte. Revendiquer ou transmettre en demande un, et un compte vit chez SealTrust. Le faire ailleurs obligerait vos clients à se reconnecter sur chaque domaine, empêcherait leur gestionnaire de mots de passe de fonctionner, et surtout leur apprendrait à saisir un mot de passe SealTrust sur un domaine qui n'est pas le nôtre, ce qui est exactement le réflexe qu'exploite l'hameçonnage. Le numéro de série suit votre client jusqu'au bout : s'il doit se connecter, ou créer son compte puis confirmer son adresse, il revient sur l'écran de revendication de ce produit, puis un bouton « Retour vers » le ramène sur la page de votre domaine qu'il a quittée.

Le détenteur est lu sur la copie de la chaîne que tient notre observateur, pas sur une adresse de courriel enregistrée : une unité qui vient d'être frappée porte l'adresse de la personne qui l'a frappée, et la lire ferait passer pour « déjà revendiqué » tout produit qui sort d'atelier.

Une unité ne se revendique qu'une fois à la fois. Quand quelqu'un a commencé à la revendiquer par son numéro de série, elle reste réservée pendant dix minutes au plus, le temps qu'il termine. Une autre personne qui essaie pendant ce temps lit « une revendication de ce produit est déjà en cours, réessayez dans quelques minutes », et l'API répond 409 avec le code CLAIM_IN_PROGRESS et un en-tête Retry-After qui donne l'attente en secondes. Le ticket de la première personne n'est jamais remis à la seconde : un numéro de série est imprimé sur l'objet, il ne prouve pas qu'on le tient en main.

#Demander le passeport avec le paramètre linkType

Un lecteur machine qui veut le document lui-même ajoute un paramètre linkType.

curl
curl -sS -i "https://sealtrust.io/p/0ABCDEFGHJKM?linkType=dpp"
HTTP
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/passport/<identifiant de l'unité>

Le dernier segment est l'empreinte de l'unité, ou à défaut son identifiant de jeton, ou à défaut son numéro de série.

Cinq valeurs sont reconnues : dpp, passport, gs1:dpp, gs1:digitalproductpassport et digitalproductpassport. Toute autre valeur est traitée comme si le paramètre était absent, et le lecteur arrive sur la page produit.

Une unité retirée de la circulation part toujours vers son passeport, même sans ce paramètre. Son identifiant continue de répondre, ce que la norme exige.

#La forme exacte

Le même produit est adressable par un lien GS1 Digital Link. Sa forme est fixée par la structure du chemin.

Texte
https://sealtrust.io/01/03701234567891/21/0ABCDEFGHJKM
  • 01 est l'identifiant d'application du GTIN, le code article international.
  • 03701234567891 est le GTIN ramené à quatorze chiffres.
  • 21 est l'identifiant d'application du numéro de série.
  • 0ABCDEFGHJKM est le même numéro de série public que dans la forme courte.

Les deux formes désignent la même unité et mènent à la même page. Le domaine ne fait pas le lien GS1 Digital Link, c'est la structure du chemin qui le fait. Un résolveur hébergé sur votre propre domaine reste conforme.

Servir ces résolveurs sur votre propre nom de domaine fait partie de l'offre SealTrust Inside. Sans elle, vos liens restent sur sealtrust.io.

#Ce que le serveur vérifie

curl
curl -sS -i "https://sealtrust.io/01/03701234567891/21/0ABCDEFGHJKM"
HTTP
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/product/0ABCDEFGHJKM

Le GTIN du chemin doit correspondre au GTIN du modèle auquel l'unité appartient. Sinon le serveur répond un 404. Une unité dont le modèle ne porte aucun GTIN n'est donc pas adressable par cette forme, et reste adressable par la forme courte /p/{serial}.

Un GTIN qui ne peut pas être normalisé reçoit un 400 avec le message Invalid GTIN. Le serveur retient les chiffres du segment, refuse au delà de quatorze, et complète à gauche par des zéros jusqu'à quatorze. Les formes GTIN-8, GTIN-12, GTIN-13 et GTIN-14 passent donc, avec ou sans séparateurs.

Il vérifie ensuite la clé de contrôle GS1, et répond 400 avec le message Invalid GTIN: the check digit does not match. quand le dernier chiffre ne correspond pas aux précédents. Cette vérification a lieu à la résolution, et plus seulement à l'enregistrement du modèle : un code mal recopié est donc nommé comme tel, au lieu de répondre « produit inconnu » et d'envoyer le lecteur chercher au mauvais endroit.

Toutes les autres impasses reçoivent le même 404 avec le même message. Un numéro inconnu et un numéro connu sous un autre GTIN sont indiscernables de l'extérieur.

#La forme sans numéro de série

Un lien sans le segment 21 désigne un modèle commercial. Il ne désigne aucune unité en particulier.

curl
curl -sS -i "https://sealtrust.io/01/03701234567891"
HTTP
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/passport/01/03701234567891

Il résout vers le passeport de niveau modèle, celui qui est rattaché à un modèle et à aucune unité. Le serveur ne sert jamais ici un passeport rattaché à une unité : les données d'un exemplaire ne doivent pas être montrées pour un autre exemplaire du même modèle.

Le serveur répond un 404 dans quatre cas, sans les distinguer : le GTIN est inconnu, aucun passeport de modèle public n'est publié pour ce GTIN, plusieurs marques publient un passeport de modèle sous le même GTIN, ou le GTIN appartient à une autre marque que celle du domaine sur lequel le scan arrive.

SealTrust ne génère plus de QR code sur ce lien : chaque pièce porte le QR code de son exemplaire, dont la page affiche ce même passeport. Un code déjà imprimé sur ce lien continue de résoudre.

#Le lien d'un lot : /01/{gtin}/10/{lot}

Le niveau lot a sa forme d'adresse : le GTIN du modèle, puis l'identifiant d'application GS1 10, puis le numéro de lot tel qu'il est enregistré sur le lot, en respectant la casse.

HTTP
GET https://sealtrust.io/01/03701234567891/10/LOT-26A
HTTP
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/passport/01/03701234567891/10/LOT-26A

Il résout vers le passeport du lot quand ce lot en a un publié. Sinon, il résout vers le passeport du modèle, comme /01/{gtin} : une étiquette imprimée avant la publication du passeport du lot continue de répondre. Le numéro de lot compte au plus vingt caractères, pris dans le jeu de caractères GS1, sans barre oblique ni signe %. La console refuse de créer le passeport d'un lot dont le numéro ne tiendrait pas dans ce lien. Voir GET /01/{gtin}/10/{lot}.

SealTrust ne génère plus de QR code sur ce lien : chaque article du lot porte le QR code de son exemplaire, dont la page affiche le passeport du lot. Un code déjà imprimé sur ce lien continue de résoudre.

#La longueur de l'identifiant, et la voie d'envoi qui la fixe

Le registre européen n'applique pas une limite, il en applique deux, selon la voie par laquelle l'enregistrement arrive.

Voie d'envoiLongueur acceptée
Formulaire du registre50 caractères au plus, plafond appelé à augmenter
Dépôt de fichier, XML ou JSONde 8 à 2 000 caractères

Le service d'assistance de la Commission l'a indiqué par écrit le 31 août 2026. La même réponse confirme qu'un lien GS1 Digital Link compressé est une forme acceptable d'identifiant. Cette réponse n'est pas un texte officiel : si le guide du registre dit autre chose un jour, c'est le guide qui fait foi.

C'est votre marque qui dépose au registre, en tant qu'opérateur économique vérifié : le registre n'accepte pas aujourd'hui qu'un tiers enregistre à votre place. SealTrust prépare le fichier, en JSON ou en XML, et vous le déposez. Ce sont donc les bornes du fichier qui s'appliquent, et un lien GS1 complet y tient sans difficulté.

Pour vérifier qu'un identifiant répond, le registre suit au plus trois redirections, et refuse une adresse locale ou non sécurisée. Nos identifiants arrivent sur leur page en une seule redirection.

Le calcul qui suit garde son intérêt pour la voie du formulaire, et pour la lisibilité du code imprimé. La structure GS1 consomme vingt-deux caractères à elle seule, en plus du domaine : /01/, quatorze chiffres de GTIN, /21/. Le domaine que vous choisissez décide donc du nombre de caractères qu'il reste pour le numéro de série.

Domaine du résolveurCaractères restants pour le numéro
https://id.gs1.org10
https://sealtrust.io8
https://api.sealtrust.io4

Prenez le domaine le plus court dont vous disposez. Un sous-domaine api. est un piège. L'identifiant destiné au registre est la forme courte /p/{serial}, qui ne dépense pas ces vingt-deux caractères.

Le passeport publié porte les deux valeurs : le GTIN normalisé dans le champ gtin, et le lien complet dans le champ gs1_digital_link.

#Ce que le QR seul apporte

  • Il porte l'identifiant destiné au registre. La forme /p/{serial} est l'identifiant unique de produit qu'attend le registre européen. Le champ qui doit servir le document porte la même adresse suivie de ?linkType=dpp.
  • Il montre le passeport du modèle ou du lot. Chaque pièce porte son propre code, et sa page affiche le passeport de son lot, sinon celui de son modèle. Les liens partagés /01/{gtin} et /01/{gtin}/10/{lot} déjà imprimés continuent de résoudre.
  • Il ne demande aucun matériel. Le code est une image que vous téléchargez et envoyez à l'impression.
  • Il mène à une page web ordinaire. Aucune application n'est nécessaire pour la lire.

Ce qu'il ne fait pas : un QR imprimé encode une adresse fixe. Une photographie de l'étiquette encode la même adresse. Le résolveur cherche le numéro de série et redirige ; il n'a rien d'autre à examiner. Le QR identifie donc un objet, et ne prouve pas à lui seul que l'étiquette n'a pas été recopiée.

#Ce que le sceau NFC ajoute

Le sceau NFC est une puce NTAG 424 DNA. À chaque lecture, elle écrit elle-même deux paramètres dans l'adresse : une donnée chiffrée et un sceau de vérification. L'adresse change donc à chaque lecture.

Texte
https://sealtrust.io/verify?e=<donnée chiffrée>&c=<sceau>

Le paramètre e fait trente-deux caractères hexadécimaux. Le paramètre c en fait seize. Un téléphone qui approche la puce ouvre cette adresse déjà complétée. La page /verify interroge ensuite le point d'entrée de vérification de l'API, sur api.sealtrust.io.

Sur l'offre SealTrust Inside, nous gravons votre propre nom de domaine dans la puce, à la place de sealtrust.io. Ce choix se fige au premier encodage : une fois une puce gravée, le serveur refuse en 409 tout changement de domaine, parce que les puces déjà posées pointeraient dans le vide.

Trois choses en découlent.

Une adresse déjà utilisée est refusée. La puce incrémente un compteur à chaque lecture. Le serveur exige que ce compteur avance strictement. Une adresse capturée puis rejouée reçoit un 409. Une signature qui ne correspond pas reçoit un 403 avec le code SDM_MAC_MISMATCH. Des paramètres mal formés reçoivent un 422.

Le sceau d'ouverture, sur les puces qui en portent un. Certaines puces embarquent un fil qui se rompt à l'ouverture. Elles ajoutent alors un paramètre t de deux caractères, placé entre e et c. La réponse expose trois champs :

ChampContenu
tamper_statusLes deux caractères bruts : CC jamais ouvert, OO ouvert, OC ouvert puis refixé, II fonction jamais activée.
seal_intacttrue jamais ouvert, false ouvert, null rien à dire.
tamper_policyCe que votre marque veut qu'on en fasse.

Le champ seal_intact a trois états. La valeur null ne veut pas dire rompu : une puce ordinaire et une puce dont la fonction n'a jamais été activée donnent toutes deux null. L'afficher en alerte poserait un avertissement de contrefaçon sur des produits authentiques.

Une réponse plus riche que la redirection du QR. La lecture d'une puce renvoie directement un document, avec le nom du produit, la marque, l'identifiant de jeton, l'adresse du contrat, l'historique, la valeur du compteur, un indicateur declared_stolen si une déclaration de vol est ouverte sur l'unité, et une zone de scan au grain de la ville quand la position est fournie.

#Ce que chacun coûte en préparation

#Le QR

Vous demandez l'image au moment où vous en avez besoin, et le serveur la renvoie en PNG. Vous choisissez une taille entre 100 et 1000 pixels. La correction d'erreur est de niveau M et la marge blanche fait deux modules. Gardez cette marge à l'impression, sinon la lecture devient incertaine.

Vous pouvez télécharger le code d'un produit, celui d'un certificat, ou l'archive ZIP de tous les codes d'un lot en une fois.

Une marque en offre Conformité + Identité imprime le code de chaque exemplaire. Demander le code d'un modèle ou d'un lot lui répond 410 avec le code ITEM_QR_ONLY : elle imprime le code de chaque pièce, dont la page affiche le passeport de son lot ou de son modèle.

Une marque en offre Conformité n'a pas d'exemplaire : elle imprime le code de son modèle, GET /qr/01/{gtin}, ou de son lot, GET /qr/01/{gtin}/10/{lot}, une fois ce passeport publié. Voir Conformité, ou Conformité + Identité.

En résumé : aucun matériel, aucune manipulation par exemplaire, aucun délai d'approvisionnement.

#Le sceau NFC

La préparation est d'une autre nature.

  1. Votre offre doit comprendre l'authentification NFC. Sinon le serveur refuse la création des produits en 403.
  2. Vous approvisionnez les puces. Ce sont des composants physiques, avec un délai et un coût par exemplaire.
  3. Chaque puce passe devant un lecteur avant la création du produit. Nous lisons son identifiant matériel, vous l'associez à une ligne de votre lot, vous créez les produits, nous encodons les puces. C'est un parcours en quatre étapes, et il se fait puce par puce.
  4. Nous écrivons l'adresse dans la puce au moment de l'encodage. Vous ne pouvez pas la modifier à distance ensuite. Une puce mal encodée est une puce à remplacer physiquement.

Sur un lot NFC, vous pouvez produire en parallèle un QR imprimé pour les mêmes unités. L'inverse ne marche pas : une adresse de puce imprimée dans un QR ne fonctionne pas, parce que c'est la puce qui remplit les paramètres e et c, et qu'une image imprimée ne remplit rien.

#Choisir

QuestionQR seulSceau NFC
Identifiant /p/{serial} destiné au registre européenOuiOui
Page de la pièce qui affiche le passeport de son lot ou de son modèleOuiOui
Matériel à approvisionnerNonOui
Manipulation par exemplaireNonOui
Lecture sans applicationOuiOui
Adresse différente à chaque lectureNonOui
Rejeu d'une adresse capturée refuséNonOui
Détection d'ouverture de l'emballageNonSur les puces qui en portent un
Correction possible après fabricationRéimprimer l'étiquetteRemplacer la puce

Un dernier point sur les domaines. Si vous servez ces résolveurs sur votre propre nom de domaine, un lien reste sur ce domaine du début à la fin, et vos clients ne voient jamais le nôtre. Un domaine de marque ne résout que les produits de cette marque : le code d'une autre marque scanné sur votre domaine reçoit un 404. La même règle vaut pour la lecture d'une puce NFC, par la page de scan comme par nos applications : la puce d'une autre marque lue sur votre domaine reçoit un 404. Le refus arrive avant que le compteur de la puce n'avance et avant qu'aucune lecture ne soit enregistrée. Une puce qui ne correspond à aucun produit reçoit le même 404 sur votre domaine.

Votre réponse ouvre un courriel pré-rempli dans votre messagerie, à destination de contact@sealtrust.io. Vous le relisez avant de l'envoyer.

Proposer une correctionSignaler un problème