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

Contrôler l'intégrité du passeport publié d'un article : empreinte enregistrée, copie publique immuable et sceau de version. Point d'entrée public.

Sur cette page

Vous contrôlez qu'un passeport publié n'a pas été modifié depuis sa publication. En quittant cette page, vous saurez demander ce contrôle à partir de n'importe quel identifiant d'article, lire les trois verdicts que la réponse rend, et distinguer un passeport altéré d'un contrôle qui n'a pas pu aboutir.

Adresse complète :

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

Le même point d'entrée répond aussi sans le préfixe /v1, à https://api.sealtrust.io/passport/{identifier}/verify. 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/0ABCDEFGHJKM/verify et /passport/0ABCDEFGHJKM/verify remplissent le même compteur.

Prévoyez un délai d'attente d'au moins 30 secondes côté client. Pendant votre appel, ce point d'entrée va chercher la copie publique immuable sur des passerelles publiques. Il en interroge plusieurs l'une après l'autre, chacune avec sa propre limite de temps, donc un premier appel sur une copie que le serveur n'a encore jamais lue peut durer une vingtaine de secondes. Les appels suivants sur la même copie répondent sans aller la rechercher. Quand aucune passerelle ne répond, la réponse reste 200 et ipfs_match vaut null.

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 contrôler le passeport. 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'article0x suivi de 64 caractères hexadécimauxPour un article NFC, l'empreinte de l'identifiant lu sur la puce. Pour un article QR, une empreinte que le serveur tire au hasard au moment de la frappe. Les deux ont la même forme et vous les utilisez de la même façon.
Identifiant de jetonun entier de 256 bits écrit en décimal, 77 ou 78 chiffresL'identifiant de l'article sur la chaîne. Traitez-le comme une chaîne de caractères : il dépasse un entier 64 bits.
Numéro de série imprimé12 caractèresCe que porte le QR code sur le produit, dans l'adresse /p/{serial}.

Le serveur reconnaît l'empreinte d'article sans distinction de casse. Il reconnaît le numéro de série de la même façon, et il ramène les caractères qui se ressemblent à une forme unique avant de chercher : un I ou un L que vous saisissez à la main retrouve le 1, un O retrouve le 0.

Ce point d'entrée n'accepte pas le numéro de certificat d'authenticité. Vous l'employez sur GET /certificate/{identifier}.

#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

Contrôle d'intégrité du passeport de l'article dont le numéro de série imprimé est 0ABCDEFGHJKM. Les exemples utilisent cette forme parce qu'elle tient sur 12 caractères. Un identifiant de jeton s'écrit au même endroit dans l'adresse, sur 77 ou 78 chiffres. Les trois exemples posent le même délai d'attente de 30 secondes, pour la raison donnée plus haut.

curl -i --max-time 30 https://api.sealtrust.io/v1/passport/0ABCDEFGHJKM/verify

#Réponse d'exemple

Code HTTP 200OK

Code HTTP 200.

JSON
{
  "db_hash_match": true,
  "ipfs_match": true,
  "ipfs_uri": "ipfs://bafybeiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "ipfs_gateway_url": "https://passerelle.exemple.invalid/ipfs/bafybeiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "data_hash": "1111111111111111111111111111111111111111111111111111111111111111",
  "computed_hash": "1111111111111111111111111111111111111111111111111111111111111111",
  "passport_version": 3,
  "seal": {
    "sealed": true,
    "sealed_at": "2026-05-14T09:12:44+00:00",
    "algorithm": "st-dpp-chain-v1",
    "version_hash": "2222222222222222222222222222222222222222222222222222222222222222",
    "prev_version_hash": "3333333333333333333333333333333333333333333333333333333333333333",
    "linked": true,
    "chain_link_match": true
  }
}

La réponse compte huit champs et rien d'autre.

ChampTypeDescription
db_hash_matchboolean ou nulltrue quand les données enregistrées du passeport correspondent encore à l'empreinte enregistrée avec elles. null quand aucune empreinte n'a été enregistrée pour cette version.
ipfs_matchboolean ou nulltrue quand la copie publique immuable correspond à la version publique du passeport. false quand elle en diffère. null quand aucune copie n'existe, ou quand aucune passerelle n'a répondu.
ipfs_uristring ou nullL'adresse ipfs:// de la copie publique immuable. Renseignée uniquement quand cette copie est le passeport public que la marque publie aujourd'hui, voir ci-dessous.
ipfs_gateway_urlstring ou nullLa même copie, sous forme d'adresse HTTP ouvrable dans un navigateur. Renseignée aux mêmes conditions que ipfs_uri.
data_hashstring ou nullL'empreinte enregistrée avec cette version du passeport, 64 caractères hexadécimaux. null quand aucune empreinte n'a été enregistrée.
computed_hashstringL'empreinte recalculée au moment de votre appel à partir des données enregistrées, 64 caractères hexadécimaux. Elle porte sur les données complètes du passeport, y compris les champs que ce point d'entrée ne rend pas et que la version publique du passeport ne rend pas non plus. Vous ne pouvez donc pas la reproduire vous-même à partir de données publiques.
passport_versionintegerLe numéro de version du passeport contrôlé. Il démarre à 1 et augmente d'une unité à chaque nouvelle version du passeport.
sealobjectLe sceau de cette version et sa place dans la chaîne des versions, voir ci-dessous.

#Quel passeport le serveur contrôle

Le contrôle porte sur la dernière version publiée dont la visibilité est publique. Le serveur cherche d'abord le passeport propre à l'article. À défaut, il contrôle le passeport du modèle, partagé par tous les articles du modèle.

La réponse ne dit pas laquelle des deux portées a répondu. Les deux numérotent leurs versions séparément, donc passport_version peut valoir 1 dans les deux cas.

Le serveur ne contrôle jamais ici un passeport réservé au propriétaire ni un passeport réservé à la marque. La réponse est alors 404, comme si aucun passeport n'était publié.

#Quand le serveur vous rend l'adresse ipfs_uri

Vous recevez l'adresse de la copie publique lorsque son contenu est exactement le passeport public que la marque publie aujourd'hui. Sinon, ipfs_uri et ipfs_gateway_url valent null.

Une marque qui change ses règles d'accès change ce que montre son passeport public. Une copie déposée avant ce changement n'est donc plus annoncée tant que la marque n'en a pas déposé une nouvelle. Ne lisez jamais ces deux null comme un verdict sur la copie.

ipfs_match à null ne dit rien sur l'intégrité de la copie. Réessayez plus tard avant de conclure.

#Le bloc seal

ChampTypeDescription
sealedbooleanfalse quand la version n'est pas scellée. Le bloc s'arrête alors là et ne porte aucun autre champ.
sealed_atstringLa date et l'heure du scellement, au format ISO 8601.
algorithmstringLa version de l'algorithme de chaînage. Vaut aujourd'hui st-dpp-chain-v1.
version_hashstring ou nullL'empreinte scellée de cette version, 64 caractères hexadécimaux.
prev_version_hashstring ou nullL'empreinte scellée de la version précédente du même passeport. null pour la toute première version.
linkedbooleantrue quand cette version porte une empreinte scellée et prend donc sa place dans la chaîne.
reasonstringPrésent uniquement quand linked vaut false. Vaut alors sealed_before_chain : vous avez publié cette version avant l'existence du chaînage, et le serveur n'en fabrique aucun après coup.
chain_link_matchbooleanPrésent uniquement quand linked vaut true. false veut dire que les données enregistrées ne correspondent plus à ce qui a été scellé.

Le bloc seal prend donc trois formes, et vous devez pouvoir les distinguer sans rien déduire d'un champ absent.

JSON
{ "sealed": false }
JSON
{
  "sealed": true,
  "sealed_at": "2025-11-02T08:30:00+00:00",
  "algorithm": "st-dpp-chain-v1",
  "version_hash": null,
  "prev_version_hash": null,
  "linked": false,
  "reason": "sealed_before_chain"
}
JSON
{
  "sealed": true,
  "sealed_at": "2026-05-14T09:12:44+00:00",
  "algorithm": "st-dpp-chain-v1",
  "version_hash": "2222222222222222222222222222222222222222222222222222222222222222",
  "prev_version_hash": "3333333333333333333333333333333333333333333333333333333333333333",
  "linked": true,
  "chain_link_match": true
}

#Quel verdict lire en premier

chain_link_match à false est le signal qu'une version scellée a été modifiée après sa publication. C'est le verdict le plus fort de cette réponse. Il vient d'un recalcul fait au moment de votre appel.

ipfs_match à false porte le même genre de signal sur la copie publique.

#Erreurs

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

CodeConditionQue faire
404Aucun article 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 public n'est publié pour lui ni pour son modèle. detail vaut No published passport found for this product.Ne traitez pas cette réponse comme un échec du contrôle. Il n'y a rien à contrôler. Un passeport réservé au propriétaire ou à la marque donne aussi cette réponse.
429Le plafond de 60 appels par 60 secondes est atteint pour votre adresse réseau, tous chemins commençant par /passport confondus. detail vaut Rate limit exceeded: 60 requests per 60s.Attendez le nombre de secondes indiqué par Retry-After, puis réessayez.
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 passerelle injoignable ne produit pas d'erreur HTTP. La réponse reste 200 et ipfs_match vaut null.

#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