Méthode GET/passport/{identifier}/proof

Rassembler en un appel toutes les preuves publiques d'un passeport : empreinte du contenu, copie IPFS, ancrage sur Base, sceau de version et état du justificatif signé. Point d'entrée public.

Sur cette page

Vous rassemblez en un seul appel les preuves publiques attachées au passeport d'un produit. En quittant cette page, vous saurez demander ces preuves à partir d'un identifiant d'article, lire ce que chaque bloc établit réellement, et distinguer une preuve absente d'une preuve en défaut.

Adresse complète :

HTTP
GET https://api.sealtrust.io/v1/passport/{identifier}/proof

Le même point d'entrée répond aussi sans le préfixe /v1, à https://api.sealtrust.io/passport/{identifier}/proof. Les deux adresses appellent le même code. Utilisez la forme /v1 pour une nouvelle intégration.

Ce point d'entrée ne renvoie aucun contenu du passeport. Il renvoie les éléments qui permettent de vérifier ce contenu. Pour lire le passeport lui-même, appelez GET /v1/passport/{identifier}.

#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.

Vous recevez ici uniquement les passeports dont la visibilité est publique. Un passeport réservé au propriétaire ou réservé à la marque ne vous est jamais rendu par ce point d'entrée.

#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/1042/proof et /passport/1042/proof remplissent le même compteur.

Chaque réponse acceptée porte trois en-têtes.

En-têteContenu
X-RateLimit-Limitle plafond appliqué sur la fenêtre, ici 60
X-RateLimit-Remainingce qu'il vous reste dans la fenêtre en cours
X-RateLimit-Resetl'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

NomTypeObligatoireDescription
identifierstringouiL'article dont vous voulez les preuves. Trois formes sont acceptées, voir ci-dessous.

Ce point d'entrée n'a aucun paramètre de requête.

identifier accepte trois formes, essayées dans cet ordre.

FormeAspectProvenance
Empreinte d'identifiant0x suivi de 64 caractères hexadécimauxl'empreinte de l'identifiant unique de l'exemplaire. Sur un article NFC elle vient de l'identifiant de la puce. Sur un article QR seul, le serveur la tire au hasard à la frappe.
Identifiant de jetonun nombre écrit en décimall'identifiant de l'article sur la chaîne
Numéro de série imprimé12 caractèresce que porte le QR code sur le produit, dans l'adresse /p/{serial}

Vous pouvez écrire le numéro de série en majuscules ou en minuscules. Nous ramenons les caractères qui se ressemblent à une forme unique avant la recherche, donc un I ou un L saisi à la main retrouve le 1, et un O retrouve le 0.

Ce point d'entrée ne résout que les articles encore au catalogue de la marque. Un article détruit sur la chaîne, remplacé par une version ultérieure ou archivé répond 404.

#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 l'article dont l'identifiant de jeton est 1042.

curl -i https://api.sealtrust.io/v1/passport/1042/proof

#Réponse d'exemple

Code HTTP 200OK

Code HTTP 200.

JSON
{
  "passport_version": 3,
  "data_hash": "1111111111111111111111111111111111111111111111111111111111111111",
  "ipfs_uri": "ipfs://bafybeiexemple00000000000000000000000000000000000000000000",
  "ipfs_gateway_url": "https://ipfs.io/ipfs/bafybeiexemple00000000000000000000000000000000000000000000",
  "anchor": {
    "chain": "base",
    "chain_id": 8453,
    "type": "merkle_batch",
    "tx_hash": "0x2222222222222222222222222222222222222222222222222222222222222222",
    "basescan_url": "https://basescan.org/tx/0x2222222222222222222222222222222222222222222222222222222222222222",
    "merkle_root": "0x3333333333333333333333333333333333333333333333333333333333333333",
    "anchored": true,
    "proves": "batch_inclusion"
  },
  "passport_anchor": {
    "chain": "base",
    "chain_id": 8453,
    "tx_hash": "0x4444444444444444444444444444444444444444444444444444444444444444",
    "basescan_url": "https://basescan.org/tx/0x4444444444444444444444444444444444444444444444444444444444444444",
    "merkle_root": "0x5555555555555555555555555555555555555555555555555555555555555555",
    "leaf": "0x6666666666666666666666666666666666666666666666666666666666666666",
    "leaf_index": 2,
    "proof": [
      "0x7777777777777777777777777777777777777777777777777777777777777777",
      "0x8888888888888888888888888888888888888888888888888888888888888888"
    ],
    "anchored_at": "2026-08-14T02:15:09+00:00",
    "data_hash_matches": true,
    "proves": "content_existed_at_or_before_tx"
  },
  "seal": {
    "sealed": true,
    "sealed_at": "2026-08-13T09:41:22+00:00",
    "algorithm": "st-dpp-chain-v1",
    "version_hash": "9999999999999999999999999999999999999999999999999999999999999999",
    "prev_version_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "linked": true,
    "chain_link_match": true
  },
  "vc": {
    "issued": true,
    "vct": "https://schema.sealtrust.io/vct/digital-product-passport",
    "issued_at": "2026-08-13T09:41:25+00:00"
  },
  "verifications": {
    "count": 47,
    "last_verified_at": "2026-08-19T18:03:44+00:00"
  }
}

passport_version, seal et vc sont toujours présents. Nous omettons les autres champs de premier niveau quand la preuve correspondante n'existe pas. Une absence signifie que cette preuve n'est pas disponible. Traitez-la comme une information, au même titre qu'une valeur.

ChampTypePrésenceDescription
passport_versionintegertoujoursLe numéro de version du passeport publié auquel se rapportent toutes les preuves ci-dessous.
data_hashstringsi enregistréeL'empreinte SHA-256 du contenu complet du passeport, 64 caractères hexadécimaux sans préfixe 0x.
ipfs_uristringsi copie vérifiéeL'adresse IPFS de la copie publique du passeport.
ipfs_gateway_urlstringsi copie vérifiéeLa même copie, sous forme d'adresse web ouvrable dans un navigateur.
anchorobjectsi l'article a une référence sur la chaîneLa référence sur la chaîne qui concerne l'ARTICLE. Voir ci-dessous.
passport_anchorobjectsi la version a été ancréeL'ancrage qui date le DOCUMENT. Voir ci-dessous.
sealobjecttoujoursLe sceau de la version et sa place dans la suite des versions. Voir ci-dessous.
vcobjecttoujoursL'état du justificatif signé attaché au passeport. Voir ci-dessous.
verificationsobjectsi le compte est supérieur à zéroLe nombre de vérifications réussies enregistrées pour cet exemplaire, par QR comme par NFC, et la date de la dernière. Absent aussi quand l'exemplaire ne porte pas d'empreinte d'identifiant.

Le passeport servi ici porte soit sur cet exemplaire précis, soit sur son modèle. Nous cherchons d'abord un passeport rattaché à l'exemplaire. À défaut, nous servons le passeport publié pour son modèle, partagé par tous les exemplaires qui portent le même code produit. Dans ce second cas, data_hash, ipfs_uri, ipfs_gateway_url, passport_anchor, seal et vc décrivent le document du modèle. anchor et verifications restent propres à l'exemplaire que vous avez demandé.

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.

#Le bloc anchor, la référence de l'article

Ce bloc est présent quand l'article porte une référence sur la chaîne. Il recouvre deux situations différentes, et c'est le champ anchored qui les sépare.

ChampTypeDescription
chainstringLe réseau, en forme lisible par une machine. base en production.
chain_idintegerL'identifiant du réseau. 8453 pour Base en production.
typestringmerkle_batch ou mint_transaction.
tx_hashstringLa transaction concernée.
basescan_urlstringLe lien direct vers cette transaction sur l'explorateur public du réseau.
merkle_rootstringLa racine du lot inscrite sur la chaîne. Présent uniquement quand type vaut merkle_batch et que la racine est enregistrée.
anchoredbooleantrue uniquement quand le lot de l'article a été inscrit sur la chaîne.
provesstringbatch_inclusion quand le lot est ancré, token_minted sinon.

anchored: true veut dire que le lot auquel appartient l'article a été inscrit sur la chaîne. Vous obtenez la preuve d'appartenance elle-même par GET /v1/verify/merkle/{identifier}, lorsque ce bloc porte aussi merkle_root. Sans merkle_root, cet appel répond 404 et detail vaut No Merkle anchor for this product.

anchored: false veut dire que le lot de l'article n'a jamais été inscrit. Le bloc porte alors la transaction de frappe de l'article. Elle démontre que le jeton existe sur la chaîne. Elle ne démontre rien sur un lot, et rien sur le contenu du passeport.

Dans les deux cas, cette référence ne porte aucun engagement sur le contenu du passeport. L'engagement sur le contenu se lit dans passport_anchor et dans seal.

#Le bloc passport_anchor, la date du document

Ce bloc est présent quand cette version précise du passeport a été inscrite sur la chaîne. Il établit une seule chose : le contenu existait au plus tard au moment de cette transaction.

ChampTypeDescription
typestringToujours passport_anchor. Il distingue cet ancrage de celui du bloc anchor, qui porte un lot d'articles.
anchoredbooleanToujours true. Le bloc n'existe que lorsque la version a été inscrite sur la chaîne.
chainstringLe réseau, en forme lisible par une machine.
chain_idinteger ou nullL'identifiant du réseau. null sur un ancrage antérieur à l'enregistrement du réseau. chain indique alors le réseau de production.
tx_hashstringLa transaction qui porte la racine.
basescan_urlstringLe lien direct vers cette transaction sur l'explorateur public du réseau.
merkle_rootstringLa racine inscrite sur la chaîne, 0x suivi de 64 caractères hexadécimaux.
leafstringL'empreinte de cette version dans l'arbre, 0x suivi de 64 caractères hexadécimaux.
leaf_indexintegerLa position de cette empreinte dans la liste des empreintes inscrites. Le comptage démarre à 0.
proofstring[]Les empreintes voisines à combiner avec leaf, de bas en haut, pour retrouver merkle_root. La liste est vide quand l'inscription ne couvrait qu'une version.
anchored_atstring ou nullLa date de l'inscription, au format ISO 8601.
data_hash_matchesbooleantrue quand le passeport enregistré aujourd'hui correspond encore à ce qui a été inscrit.
provesstringToujours content_existed_at_or_before_tx.

Vous pouvez refaire la vérification d'appartenance sans nous faire confiance. 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, avec des voisins triés à chaque étage. Ouvrez ensuite basescan_url pour lire la transaction qui a inscrit cette racine.

L'absence de passport_anchor est courante et normale. Publier une version ne l'inscrit pas sur la chaîne. L'inscription est une opération distincte, faite par passages groupés, et beaucoup de passeports publiés ne portent jamais ce bloc. Ne concluez donc rien de son absence sur la validité du passeport. Le bloc seal, lui, est toujours présent et couvre les versions non inscrites.

#Le bloc seal, le sceau de la version

Ce bloc est toujours présent. Il tient sur les versions que passport_anchor ne couvre pas.

ChampTypePrésenceDescription
sealedbooleantoujoursfalse quand la version n'a jamais été scellée. Le bloc s'arrête alors là.
sealed_atstringsi sealedLa date du scellement, au format ISO 8601.
algorithmstringsi sealedLa version de l'algorithme de chaînage. Vaut st-dpp-chain-v1.
version_hashstring ou nullsi sealedL'empreinte de ce maillon, 64 caractères hexadécimaux.
prev_version_hashstring ou nullsi sealedL'empreinte du maillon précédent. null pour la première version publiée.
linkedbooleansi sealedtrue quand cette version porte une empreinte de maillon.
reasonstringsi linked est falseVaut sealed_before_chain. La version a été publiée avant l'existence du chaînage, donc aucun maillon n'est fabriqué après coup. Le bloc s'arrête là.
chain_link_matchbooleansi linkedtrue quand le passeport enregistré aujourd'hui produit encore exactement le maillon stocké.

chain_link_match est recalculé à chaque appel à partir du contenu enregistré. false veut dire que la version a été modifiée après sa publication.

#Le bloc vc, le justificatif signé

Ce bloc est toujours présent.

ChampTypePrésenceDescription
issuedbooleantoujourstrue quand un justificatif signé a été émis pour ce passeport.
vctstringsi enregistréL'identifiant du modèle de justificatif. Vaut aujourd'hui https://schema.sealtrust.io/vct/digital-product-passport.
issued_atstringsi enregistréeLa date d'émission, au format ISO 8601.

#La copie IPFS

ipfs_uri et ipfs_gateway_url désignent la copie publique du passeport. Le contenu à cette adresse est la vue publique du passeport. Son empreinte diffère donc de data_hash, qui porte sur le contenu complet.

Vous ne recevez ces deux champs que lorsque nous avons récupéré la copie et vérifié qu'elle est exactement le passeport public que la marque publie aujourd'hui. Leur absence peut donc signifier trois choses : aucune copie n'a été déposée, la copie n'a pas pu être récupérée au moment de l'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 déposée avant ce changement cesse d'être annoncée tant qu'une nouvelle n'a pas été déposée. Ne concluez rien de leur seule absence.

L'hôte de ipfs_gateway_url est celui d'une passerelle publique et peut changer. Ne le codez pas en dur. Utilisez l'adresse rendue telle quelle, ou ipfs_uri avec la passerelle de votre choix.

#Erreurs

Le corps d'une réponse d'erreur porte un champ detail.

CodeConditionQue faire
404Aucun article au catalogue ne correspond à cet identifiant, sous aucune des trois formes acceptées. detail vaut Product not found.Vérifiez l'identifiant. Un article détruit sur la chaîne, remplacé par une version ultérieure ou archivé ne se résout plus et donne cette même réponse.
404L'article existe, mais aucun passeport publié en visibilité publique ne lui est rattaché, ni directement, ni par son modèle. detail vaut No published passport found for this product.Ne traitez pas cette réponse comme un échec. Cet article n'a pas de passeport public. Un passeport réservé au propriétaire ou à la marque donne la même réponse.
429Le plafond de 60 appels par 60 secondes est atteint pour votre adresse réseau, sur l'ensemble des chemins /passport. 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é.
500Une 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.

Une lecture d'ancrage ou de copie IPFS qui échoue ne produit pas d'erreur. Le bloc concerné est absent, et les autres preuves sont servies normalement.

#Voir aussi

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