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

Contrôler la signature du passeport numérique délivré sous forme d'attestation vérifiable, et lire les données révélées au niveau d'accès demandé. Aucune session n'est demandée pour les niveaux public et end_user.

Sur cette page

Vous faites contrôler la signature du passeport numérique d'un produit, et vous récupérez les données que cette signature couvre. En quittant cette page, vous saurez demander ce contrôle depuis n'importe quel identifiant de produit, distinguer un contrôle qui échoue d'une requête qui échoue, et savoir quelles données la réponse vous montre selon le niveau d'accès que vous demandez.

Adresse complète :

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

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

Le passeport est délivré au format SD-JWT-VC, une attestation signée dont chaque champ peut être révélé ou retenu séparément. L'émetteur est la marque, identifiée par un identifiant décentralisé did:web. Ce point d'entrée recompose l'attestation au niveau d'accès que vous demandez, contrôle sa signature, et vous rend les données révélées.

#Autorisation

Aucun droit de clef d'API n'est vérifié sur ce point d'entrée. Deux contrôles s'appliquent malgré tout : l'origine de votre appel, puis le niveau d'accès que vous demandez.

#D'où vous appelez

Appelez ce point d'entrée depuis votre serveur.

Nous refusons en 403 tout appel qui porte un en-tête Origin ou Referer désignant un domaine autre que les nôtres. Le champ detail vaut alors Forbidden origin. Un navigateur pose toujours l'un de ces deux en-têtes, donc une page web hébergée ailleurs que chez nous ne peut pas appeler cette adresse depuis le navigateur de son visiteur.

Le cookie de session ne fonctionne que depuis une page servie par un de nos domaines. Nous refusons en 403 un appel qui porte ce cookie sans en-tête Origin ni Referer, avec detail à Origin or Referer header required. Depuis un serveur, présentez donc le jeton de session dans l'en-tête Authorization: Bearer.

#Le niveau que vous demandez

Les niveaux public et end_user ne demandent aucun compte. Les cinq autres valeurs du paramètre access_tier exigent une session de compte, présentée par l'en-tête Authorization: Bearer <jeton de session> ou par le cookie de session posé à la connexion.

Niveau demandéCe qu'il faut
publicrien
end_userrien
repairerune session, et une accréditation de réparateur active sur la marque du produit
recyclerune session, et une accréditation de recycleur active sur la marque du produit
upstreamune session ayant accès à la marque du produit, ou le rôle d'autorité
authorityune session portant le rôle d'autorité de surveillance du marché

Une session ayant accès à la marque du produit ouvre les trois niveaux de métier sur ses propres produits. Le rôle d'autorité de surveillance du marché les ouvre également, sur tous les produits.

Une clef d'API partenaire n'ouvre rien ici. Le jeton reçu dans l'en-tête Authorization est décodé comme un jeton de session de compte utilisateur, et une clef d'API n'en est pas un. La lecture échoue en silence et l'appel se poursuit comme un appel anonyme.

#Plafond d'appels

60 appels par tranche de 60 secondes, comptés par adresse IP appelante. La fenêtre est fixe.

Ce plafond est partagé par toutes les adresses qui commencent par /passport. Les formes /passport/… et /v1/passport/… alimentent le même compteur, le préfixe /v1 ne crée pas un second budget.

Chaque réponse acceptée porte trois en-têtes qui décrivent ce compteur.

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 dépassement renvoie 429, avec les mêmes trois en-têtes et un 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'identifiant du produit. Trois formes sont acceptées, voir ci-dessous.
access_tierstringnonLe niveau d'accès demandé. Vaut public par défaut. Six valeurs acceptées, listées plus bas. Nous refusons toute autre valeur en 422.

#Les trois formes d'identifiant acceptées

FormeÀ quoi elle ressembleOù vous la trouvez
Numéro de série12 caractères, chiffres et lettresImprimé sur le produit, c'est ce que porte son QR
Identifiant de jetonUne suite de chiffres, souvent très longueRendu par nos réponses dans le champ token_id
Empreinte d'identifiant0x suivi de 64 caractères hexadécimauxRendue par nos réponses dans le champ uid_hash

L'empreinte d'identifiant existe pour un produit en QR seul comme pour un produit à puce NFC. Le serveur la tire au hasard pour un produit en QR seul. Il la dérive de l'identifiant de la puce pour un produit à puce NFC. Les deux formes ont donc la même allure et se demandent de la même manière.

Nous reconnaissons la forme à l'écriture. Une valeur qui commence par 0x et fait exactement 66 caractères, nous la cherchons comme une empreinte d'identifiant. Toute autre valeur, nous la cherchons d'abord comme un identifiant de jeton, puis comme un numéro de série quand la première recherche n'a rien donné.

Vous écrivez l'empreinte d'identifiant dans la casse que vous voulez. Vous écrivez le numéro de série dans la casse que vous voulez également, et nous le canonicalisons comme le fait le résolveur du QR : nous y lisons les lettres I et L comme un 1, la lettre O comme un 0. Vous pouvez donc recopier à la main un numéro lu sur une étiquette.

Le numéro de certificat d'authenticité n'est pas accepté ici.

Un produit détruit sur la chaîne ou retiré du catalogue ne se résout plus par ce point d'entrée, et la réponse est alors 404.

#Les six valeurs de access_tier

Ces niveaux sont des publics différents, sans hiérarchie entre eux. Chacun des trois niveaux de métier hérite du niveau public et du niveau utilisateur final, puis ajoute ce que son métier demande.

ValeurCe qu'elle ajoute aux champs révélés
publicidentification du produit, conformité ESPR, REACH et marquage CE, pourcentage de recyclabilité, pourcentage de contenu recyclé, étiquettes, spécification générale de batterie
end_userimpact environnemental, circularité complète, matière principale, matière certifiée biologique, durabilité, efficacité énergétique, empreinte carbone
repairernomenclature, notice de démontage, indice de réparabilité, état de santé de batterie
recyclercomposition matière, substances préoccupantes, notice de démontage, état de santé de batterie
upstreamcomposition matière, substances préoccupantes, fabrication, chaîne d'approvisionnement
authorityl'intégralité des données, sans filtrage

Une marque peut remplacer ces règles par les siennes. Le tableau ci-dessus décrit ce qui s'applique à défaut de règles propres à la marque.

#En-têtes

Aucun en-tête n'est requis pour les niveaux public et end_user. Les cinq autres niveaux exigent l'en-tête Authorization ou le cookie de session. Dans tous les cas, respectez la règle d'origine décrite plus haut.

#Corps de la requête

Aucun. Cette requête n'a pas de corps.

#Requête d'exemple

Contrôle de l'attestation du produit dont le numéro imprimé est EXEMPLE00001, au niveau public.

Les trois exemples s'exécutent depuis un serveur. Aucun ne fonctionne dans le navigateur d'un visiteur : le navigateur pose un en-tête Origin que nous refusons, et vous recevez 403.

curl -i "https://api.sealtrust.io/v1/passport/EXEMPLE00001/vc/verify?access_tier=public"

#Réponse d'exemple

Code HTTP 200OK

Code HTTP 200. La signature est valide et le niveau demandé est public.

JSON
{
  "passport_id": 1,
  "issuer": "did:web:api.sealtrust.io:brand:4242",
  "vct": "https://schema.sealtrust.io/vct/digital-product-passport",
  "key_version": 1,
  "access_tier": "public",
  "verified": true,
  "error": null,
  "credential_subject": {
    "product_identity": {
      "gtin": "03701234567890",
      "model": "Cartable Exemple 32",
      "brand": "Exemple SAS",
      "made_in": "FR"
    },
    "compliance": {
      "eu_espr": true,
      "reach": true,
      "ce_marking": false
    },
    "circularity": {
      "recyclability_percentage": 62,
      "recycled_content_percentage": 0
    }
  }
}

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

ChampTypeDescription
passport_idintegerL'identifiant de la version de passeport sur laquelle le contrôle a porté.
issuerstringL'identifiant décentralisé did:web de la marque émettrice. Toujours renseigné sur ce point d'entrée.
vctstringLe type d'attestation. Vaut https://schema.sealtrust.io/vct/digital-product-passport quand la marque n'en a pas déclaré un autre.
key_versioninteger ou nullLe numéro de version de la clef de signature de la marque qui a signé l'attestation. null quand ce numéro n'a pas été enregistré à la délivrance.
access_tierstringLe niveau d'accès demandé, repris tel quel. Ce point d'entrée ne change jamais le niveau demandé.
verifiedbooleantrue quand la signature a été contrôlée avec succès.
errorstring ou nullnull quand verified vaut true. Vaut verification_failed sinon. C'est la seule valeur possible.
credential_subjectobject ou nullLes données révélées au niveau demandé, telles que la signature les couvre. Vaut null dès que verified vaut false.

#Un contrôle qui échoue reste une réponse 200

C'est le point à retenir de cette page. Un échec de contrôle n'est pas une erreur HTTP. La réponse reste 200 et porte le verdict.

JSON
{
  "passport_id": 1,
  "issuer": "did:web:api.sealtrust.io:brand:4242",
  "vct": "https://schema.sealtrust.io/vct/digital-product-passport",
  "key_version": 1,
  "access_tier": "public",
  "verified": false,
  "error": "verification_failed",
  "credential_subject": null
}

Lisez donc toujours verified. Un code 200 ne dit rien à lui seul.

#Ce qui fait basculer verified à false

CauseCe qu'elle signifie
La signature ne correspond pas au contenuL'attestation a été modifiée après sa délivrance.
L'émetteur inscrit dans l'attestation n'est pas celui attendu pour cette marqueL'attestation a été délivrée sous une autre identité que celle de la marque du produit.
L'attestation ne désigne aucune version de clef lisibleL'en-tête de l'attestation ne porte pas de numéro de version de clef exploitable.
La version de clef citée par l'attestation n'existe pas pour cette marqueLa clef qui a signé n'est pas connue.
Cette version de clef a été révoquéeLa marque a retiré cette clef. Les attestations qu'elle a signées ne sont plus reconnues.

La réponse ne dit pas laquelle de ces causes s'applique. Le champ error vaut verification_failed dans tous ces cas.

#Contrôler la signature vous-même

Vous n'êtes pas obligé de nous demander ce verdict. La marque publie ses clefs publiques de signature dans un document d'identité décentralisé, servi publiquement à l'adresse GET https://api.sealtrust.io/brand/{brand_id}/did.json. Une marque qui héberge son identité sur son propre domaine le sert à l'adresse https://<son domaine>/.well-known/did.json.

Avec ce document et n'importe quelle bibliothèque did:web et SD-JWT-VC du commerce, vous contrôlez la signature sans passer par nous. C'est ce qui rend le passeport opposable sans dépendre de notre disponibilité.

#Erreurs

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

Les contrôles s'enchaînent dans cet ordre : origine de l'appel, résolution du produit, recherche du passeport publié, contrôle du niveau demandé, présence d'une attestation délivrée, puis identification de la marque émettrice. La première étape qui échoue donne la réponse.

CodeConditionQue faire
401access_tier=authority est demandé sans session valide. detail vaut Authority-tier access requires authentication.Connectez-vous avec un compte portant le rôle d'autorité de surveillance du marché. Une clef d'API partenaire ne convient pas.
401access_tier vaut repairer, recycler ou upstream, et l'appel ne porte aucune session valide. detail vaut Professional-tier access requires authentication.Présentez un jeton de session de compte, ou demandez le niveau public ou end_user.
403L'appel porte un en-tête Origin ou Referer qui ne désigne pas un de nos domaines, ce qui arrive pour tout appel émis depuis une page web hébergée ailleurs. detail vaut Forbidden origin.Appelez ce point d'entrée depuis votre serveur. Un appel émis par le navigateur d'un visiteur ne peut aboutir.
403L'appel porte le cookie de session et n'a ni en-tête Origin ni en-tête Referer, ce qui arrive quand on rejoue un cookie de navigateur en ligne de commande. detail vaut Origin or Referer header required.Retirez le cookie et présentez le jeton de session dans l'en-tête Authorization: Bearer.
403access_tier=authority est demandé par un compte connecté qui ne porte pas ce rôle. detail vaut Authority-tier access is restricted to market surveillance authorities.Demandez le niveau qui correspond à votre habilitation.
403Un niveau professionnel est demandé par un compte connecté qui n'a ni accès à la marque du produit, ni l'accréditation correspondante sur cette marque. detail vaut This tier is restricted to the product's brand, partners holding the matching accreditation, and market-surveillance authorities.Demandez à la marque l'accréditation qui correspond à votre métier, puis demandez le niveau de ce métier.
404Aucun produit ne correspond à cet identifiant, sous aucune des trois formes acceptées. detail vaut Product not found.Vérifiez l'identifiant. Un produit détruit sur la chaîne ou retiré du catalogue donne cette même réponse.
404Le produit existe, mais aucun passeport public n'est publié pour lui ni pour son modèle. detail vaut No published passport found for this product.Il n'y a rien à contrôler. Un passeport réservé au propriétaire ou à la marque donne aussi cette réponse.
404Un passeport public existe, mais aucune attestation signée n'a été délivrée pour cette version. detail vaut No VC issued for this passport yet.Demandez à la marque de délivrer l'attestation de cette version du passeport. Le passeport reste lisible par les points d'entrée de lecture.
404La marque du passeport n'a pas pu être retrouvée. detail vaut Brand not found.Contactez le support en indiquant l'identifiant que vous avez appelé. Aucune action de votre côté ne corrige cette réponse.
422access_tier n'est pas une des six valeurs acceptées. detail est une liste, chaque entrée portant loc, type et msg.Lisez loc pour savoir quel paramètre est en cause, puis corrigez sa valeur.
429Le plafond de 60 appels par 60 secondes est atteint pour votre adresse IP, 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.

#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