Méthode GET/passport /01 /{gtin} /proof
Récupérer les preuves publiques du passeport de référence annoncé par un GTIN : empreinte du contenu, copie IPFS vérifiée, ancrage du document sur Base et état de l'attestation signée. Point d'entrée public.
Sur cette page
Vous récupérez les preuves publiques du passeport que ce GTIN annonce pour un modèle. En quittant cette page, vous saurez demander ces preuves à partir d'un GTIN seul, lire ce que chaque bloc établit, et interpréter correctement l'absence d'un bloc.
Adresse complète :
GET https://api.sealtrust.io/v1/passport/01/{gtin}/proofLe même point d'entrée répond aussi sans le préfixe /v1, à
https://api.sealtrust.io/passport/01/{gtin}/proof. Les deux adresses appellent
le même code. Utilisez la forme /v1 pour une nouvelle intégration.
#Autorisation
Aucune, point d'entrée public. Vous n'envoyez ni clef d'API, ni session, ni en-tête d'origine. La réponse est la même pour tout le monde.
#Plafond d'appels
60 appels par tranche de 60 secondes, comptés par adresse réseau appelante.
Ce compteur est commun à tous les chemins qui commencent par /passport. Les
appels que vous adressez à l'un d'eux entament donc le budget des autres. Le
préfixe /v1 ne crée pas un second budget : /v1/passport/01/03701234567890/proof
et /passport/01/03701234567890/proof remplissent le même compteur.
Chaque réponse acceptée porte trois en-têtes.
| En-tête | Contenu |
|---|---|
X-RateLimit-Limit | le plafond appliqué sur la fenêtre, ici 60 |
X-RateLimit-Remaining | ce qu'il vous reste dans la fenêtre en cours |
X-RateLimit-Reset | l'horodatage de fin de la fenêtre, en secondes |
Un refus renvoie 429, avec ces trois en-têtes et Retry-After. Sur ce point
d'entrée, Retry-After vaut la durée de la fenêtre, soit 60 secondes.
#Paramètres de chemin et de requête
| Nom | Type | Obligatoire | Description |
|---|---|---|---|
gtin | string | oui | Le numéro d'article commercial, l'identifiant GS1 que porte le code produit. |
Ce point d'entrée n'a aucun paramètre de requête.
Nous ramenons le GTIN à sa forme canonique de 14 chiffres avant la recherche. Nous retirons tout caractère qui n'est pas un chiffre, puis nous complétons par des zéros à gauche. Un GTIN à 8, 12 ou 13 chiffres retrouve donc le même modèle qu'un GTIN à 14 chiffres. Nous refusons en 404 une valeur vide, une valeur sans aucun chiffre, ou une valeur de plus de 14 chiffres.
Un GTIN se termine par une clef de contrôle, le chiffre calculé à partir de ceux qui le précèdent. Nous la vérifions, et nous refusons en 400 un GTIN dont le dernier chiffre ne correspond pas. Recopiez le code tel qu'il est imprimé sur le produit, chiffre pour chiffre.
Le champ gtin de la réponse vous rend la forme à 14 chiffres retenue.
#En-têtes
Aucun en-tête n'est requis.
#Corps de la requête
Aucun. Cette requête n'a pas de corps.
#Requête d'exemple
Preuves du passeport de référence annoncé par le GTIN 03701234567890.
curl -i https://api.sealtrust.io/v1/passport/01/03701234567890/proofconst reponse = await fetch(
"https://api.sealtrust.io/v1/passport/01/03701234567890/proof",
);
if (reponse.status === 404) {
console.log("Aucun passeport de référence publié pour ce GTIN.");
} else if (reponse.ok) {
const preuves = await reponse.json();
console.log(preuves.gtin, preuves.level, preuves.passport_version);
console.log(preuves.data_hash);
console.log(preuves.ipfs_gateway_url);
console.log(preuves.passport_anchor);
console.log(preuves.seal);
console.log(preuves.vc);
} else {
console.log(reponse.status, await reponse.json());
}import requests
response = requests.get(
"https://api.sealtrust.io/v1/passport/01/03701234567890/proof",
timeout=30,
)
if response.status_code == 404:
print("Aucun passeport de référence publié pour ce GTIN.")
elif response.ok:
preuves = response.json()
print(preuves["gtin"], preuves["level"], preuves["passport_version"])
print(preuves.get("data_hash"))
print(preuves.get("ipfs_gateway_url"))
print(preuves.get("passport_anchor"))
print(preuves["seal"])
print(preuves["vc"])
else:
print(response.status_code, response.json())#Réponse d'exemple
Code HTTP 200OK
Code HTTP 200.
{
"passport_version": 3,
"data_hash": "1111111111111111111111111111111111111111111111111111111111111111",
"ipfs_uri": "ipfs://bafybeiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"ipfs_gateway_url": "https://ipfs.io/ipfs/bafybeiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"passport_anchor": {
"chain": "base",
"chain_id": 8453,
"tx_hash": "0x2222222222222222222222222222222222222222222222222222222222222222",
"basescan_url": "https://basescan.org/tx/0x2222222222222222222222222222222222222222222222222222222222222222",
"merkle_root": "0x3333333333333333333333333333333333333333333333333333333333333333",
"leaf": "0x4444444444444444444444444444444444444444444444444444444444444444",
"leaf_index": 7,
"proof": [
"0x5555555555555555555555555555555555555555555555555555555555555555",
"0x6666666666666666666666666666666666666666666666666666666666666666"
],
"anchored_at": "2026-08-14T09:12:44.318000+00:00",
"data_hash_matches": true,
"proves": "content_existed_at_or_before_tx"
},
"seal": {
"sealed": true,
"sealed_at": "2026-08-12T10:04:11.882000+00:00",
"algorithm": "st-dpp-chain-v1",
"version_hash": "7777777777777777777777777777777777777777777777777777777777777777",
"prev_version_hash": "8888888888888888888888888888888888888888888888888888888888888888",
"linked": true,
"chain_link_match": true
},
"vc": {
"issued": true,
"vct": "https://schema.sealtrust.io/vct/digital-product-passport",
"issued_at": "2026-08-12T10:04:12.140000+00:00"
},
"level": "model",
"gtin": "03701234567890"
}La réponse porte aussi l'en-tête Cache-Control: no-store, max-age=0. Ne
mettez cette réponse dans aucun cache partagé. Pour réduire le nombre de vos
appels, gardez le résultat dans votre propre cache applicatif, avec la durée de
fraîcheur que votre usage tolère.
Cinq champs sont toujours présents : passport_version, seal, vc, et,
propres à ce point d'entrée, level et gtin. Les autres champs
n'apparaissent que lorsque la preuve correspondante est établie. Une absence
recouvre deux situations que la réponse ne distingue pas : la preuve n'existe
pas encore, ou nous n'avons pas pu l'établir au moment de votre appel. Ne lisez
jamais une absence comme une altération.
| Champ | Type | Description |
|---|---|---|
passport_version | integer | Le numéro de la version de passeport servie. Une correction publiée crée une nouvelle version. Quand plusieurs versions de référence sont publiées et visibles publiquement pour ce modèle, nous servons celle qui porte le numéro de version le plus élevé. |
data_hash | string | L'empreinte SHA-256 du contenu de cette version, 64 caractères hexadécimaux sans préfixe 0x. Absent quand la version n'en porte pas. |
ipfs_uri | string | L'adresse IPFS de la copie publique figée de ce passeport. Voir ci-dessous la condition qui commande sa présence. |
ipfs_gateway_url | string | La même copie, servie par une passerelle HTTP publique, pour l'ouvrir dans un navigateur. Présent chaque fois que ipfs_uri est présent. Les deux champs vont ensemble. |
passport_anchor | object | L'ancrage qui date le contenu de cette version sur la chaîne Base. Absent tant que la version n'a pas été inscrite sur la chaîne, et aussi lorsque nous ne pouvons pas reconstruire la preuve d'inclusion au moment de votre appel. Voir ci-dessous. |
seal | object | Le sceau de la version et sa place dans la suite des versions. Toujours présent. Voir ci-dessous. |
vc | object | L'état de l'attestation signée du passeport. Toujours présent. Voir ci-dessous. |
level | string | Toujours model. Rappelle que ces preuves portent sur un modèle. |
gtin | string | Le GTIN à 14 chiffres retenu après normalisation de la valeur que vous avez envoyée. |
#Le bloc passport_anchor
Ce bloc établit une seule chose : le contenu de cette version existait au plus
tard au moment de la transaction. C'est ce que dit son champ proves, dont la
valeur est content_existed_at_or_before_tx. Il ne rend pas le contenu vrai, et
il n'empêche pas la marque de publier une correction plus tard.
| Champ | Type | Description |
|---|---|---|
chain | string | Le réseau, base en production. |
chain_id | integer ou null | L'identifiant de chaîne, 8453 pour Base en production. null sur les inscriptions les plus anciennes, où nous n'avions pas enregistré la chaîne ; lisez alors chain. |
tx_hash | string | La transaction qui porte l'inscription de la racine. |
basescan_url | string | Le lien direct vers cette transaction sur l'explorateur public du réseau. |
merkle_root | string | La racine inscrite sur la chaîne, 0x suivi de 64 caractères hexadécimaux. |
leaf | string | L'empreinte de cette version dans l'arbre, 0x suivi de 64 caractères hexadécimaux. |
leaf_index | integer | La position de cette empreinte dans la liste des empreintes inscrites ensemble. Le comptage démarre à 0. |
proof | string[] | Les empreintes voisines à combiner avec leaf pour retrouver merkle_root. La liste est vide quand l'inscription ne couvrait qu'une version. |
anchored_at | string ou null | L'instant de l'inscription, au format ISO 8601. null quand cet instant n'a pas été enregistré. |
data_hash_matches | boolean | true quand l'empreinte inscrite alors est encore l'empreinte du contenu servi aujourd'hui. false est le signal d'altération, et il est publié. |
proves | string | Toujours content_existed_at_or_before_tx. |
Vous pouvez recalculer la racine vous-même. Vous partez de leaf. Pour chaque
élément de proof, dans l'ordre, vous mettez les deux valeurs de 32 octets côte
à côte, la plus petite des deux d'abord, puis vous appliquez keccak256 à la
concaténation. Le résultat devient la nouvelle valeur de travail. Après le
dernier élément de proof, vous devez obtenir exactement merkle_root. C'est
la convention de vérification d'OpenZeppelin. Nous trions les voisins à chaque
étage, donc la preuve n'a pas besoin d'indiquer un sens.
Il vous reste à vérifier que merkle_root est bien la valeur inscrite sur la
chaîne. Ouvrez basescan_url pour lire la transaction d'inscription.
Un passport_anchor absent ne veut pas dire que le passeport n'est pas
fiable. L'inscription sur la chaîne est une opération que SealTrust déclenche.
Une marque ne la commande pas depuis sa console, et beaucoup de versions
publiées ne sont jamais inscrites. Publier une version reste une écriture en
base de données, sans transaction sur la chaîne. Le bloc seal, lui, est
présent sur toute version scellée, et c'est lui qui rend visible une réécriture
tant qu'aucune inscription ne couvre la version.
#Le bloc seal
Nous fixons le sceau à la première publication d'une version. Il chaîne cette version à la précédente du même passeport, ce qui rend visible une réécriture survenue après coup.
| Champ | Type | Description |
|---|---|---|
sealed | boolean | false pour une version non scellée. Le bloc ne contient alors rien d'autre. |
sealed_at | string | L'instant du scellement, au format ISO 8601. |
algorithm | string | La version du calcul du sceau, st-dpp-chain-v1 aujourd'hui. |
version_hash | string ou null | Le maillon de cette version, 64 caractères hexadécimaux. |
prev_version_hash | string ou null | Le maillon de la version précédente. null pour la première version d'un passeport. |
linked | boolean | true quand la version porte un maillon. |
reason | string | Présent uniquement quand linked vaut false, avec la valeur sealed_before_chain. La version a été publiée avant l'existence du chaînage, et aucun maillon n'est fabriqué après coup pour une publication que nous ne pouvons pas dater. |
chain_link_match | boolean | Présent uniquement quand linked vaut true. Nous recalculons le maillon à partir du contenu servi et nous le comparons à celui qui est stocké. false veut dire que la version a été modifiée après sa publication. |
#Le bloc vc
L'attestation est le passeport rendu sous forme d'un document signé, au format SD-JWT-VC. La clef privée de signature ne quitte pas un module matériel de sécurité.
| Champ | Type | Description |
|---|---|---|
issued | boolean | true quand une attestation signée existe pour cette version. Toujours présent. |
vct | string | L'identifiant du schéma de l'attestation, https://schema.sealtrust.io/vct/digital-product-passport par défaut. Absent quand la version n'en porte pas. |
issued_at | string | L'instant d'émission, au format ISO 8601. Absent quand cet instant n'a pas été enregistré. |
#Pourquoi ipfs_uri peut manquer
Nous n'annonçons la copie IPFS que lorsque nous avons vérifié, au moment de votre appel, que son contenu est exactement le passeport public que la marque publie aujourd'hui. Nous allons chercher la copie, nous la hachons, et nous ne publions le lien qu'en cas de correspondance.
Trois situations produisent donc une réponse sans ipfs_uri : aucune copie n'a
été épinglée, la copie n'a pas pu être récupérée au moment de votre appel, ou
son contenu ne correspond plus à ce que la marque publie. Une marque qui change
ses règles d'accès change ce que montre son passeport public, donc une copie
épinglée avant ce changement cesse d'être annoncée tant qu'elle n'a pas été
épinglée de nouveau. Le champ ne distingue pas ces trois cas. Ne lisez jamais
son absence comme une preuve que la copie a été altérée.
#Erreurs
Le corps d'une réponse d'erreur porte un champ detail.
| Code | Condition | Que faire |
|---|---|---|
| 400 | Le dernier chiffre du GTIN envoyé n'est pas la clef de contrôle des chiffres qui le précèdent. C'est la seule cause de ce code sur ce point d'entrée : une valeur sans aucun chiffre, ou de plus de quatorze chiffres, renvoie 404 et non 400. detail vaut Invalid GTIN: the check digit does not match. | Recopiez le code imprimé sur le produit, chiffre pour chiffre, sans en ajouter ni en omettre. |
| 404 | La valeur envoyée n'est pas un GTIN exploitable : elle est vide, elle ne contient aucun chiffre, ou elle en contient plus de 14. detail vaut Unknown GS1 Digital Link. | Envoyez le GTIN tel qu'il est imprimé sur le produit, à 8, 12, 13 ou 14 chiffres. |
| 404 | Aucun modèle enregistré ne porte ce GTIN. detail vaut Unknown GS1 Digital Link. | Vérifiez le GTIN auprès de la marque. |
| 404 | Un modèle porte ce GTIN, mais aucun passeport de niveau référence n'est publié et visible publiquement pour lui. detail vaut Unknown GS1 Digital Link. | Ce n'est pas un échec de vérification. La marque n'a pas publié de passeport de référence pour cette référence commerciale, ou l'a réservé à un public restreint. Un passeport rattaché à un exemplaire n'est jamais servi ici. |
| 429 | Le plafond de 60 appels par 60 secondes est atteint pour votre adresse réseau, tous chemins /passport confondus. detail vaut Rate limit exceeded: 60 requests per 60s. | Attendez le nombre de secondes indiqué par Retry-After, puis réessayez. Mettez la réponse en cache de votre côté. |
| 500 | Une erreur inattendue s'est produite pendant le traitement de votre appel. detail vaut Internal Server Error. La réponse porte un en-tête X-Request-Id. | Réessayez. Si l'erreur persiste, contactez le support en indiquant la valeur de X-Request-Id. |
#Voir aussi
GET /passport/01/{gtin}, lire le passeport publié d'un modèle, à partir de son GTIN.GET /passport/{identifier}/proof, rassembler les preuves publiques du passeport d'un article.GET /01/{gtin}, résoudre un lien GS1 qui ne porte qu'un GTIN.- Confiance et preuves, ce que chaque preuve établit et comment un tiers refait la vérification.
Cette page vous a-t-elle été utile ?
Votre réponse ouvre un courriel pré-rempli dans votre messagerie, à destination de contact@sealtrust.io. Vous le relisez avant de l'envoyer.