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

Récupérer le justificatif signé d'un passeport, au format SD-JWT-VC, filtré au niveau d'accès demandé. Point d'entrée public aux niveaux public et end_user.

Sur cette page

Vous récupérez le passeport d'un produit sous la forme d'un justificatif numérique signé par la marque. En quittant cette page, vous saurez demander ce justificatif au niveau d'accès qui vous concerne, lire les six champs de la réponse, et savoir où trouver la clef publique qui permet d'en vérifier la signature sans nous faire confiance.

Adresse complète :

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

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

La réponse est un objet JSON de six champs. Le passeport lui-même y tient dans un seul champ, sous la forme d'une chaîne de caractères signée au format SD-JWT-VC. Pour lire les données du passeport sous forme de JSON directement exploitable, appelez GET /v1/passport/{identifier}.

#Autorisation

Aucune pour les niveaux public et end_user. Ce point d'entrée est public à ces deux niveaux.

Une clef d'API partenaire n'ouvre rien ici. Les niveaux qui demandent une identité s'ouvrent avec un jeton de session de compte utilisateur, jamais avec une clef d'API.

Quatre valeurs du paramètre access_tier exigent une session de compte, que vous présentez 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 active de réparateur sur la marque du produit, ou un accès à cette marque, ou le rôle d'autorité
recyclerune session, et une accréditation active de recycleur sur la marque du produit, ou un accès à cette marque, ou le rôle d'autorité
upstreamune session ayant accès à la marque du produit, ou le rôle d'autorité. Aucune accréditation n'ouvre ce niveau.
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 les produits de cette marque.

Les règles de niveau d'accès sont les mêmes que celles du point d'entrée GET /v1/passport/{identifier}. Ce chemin ne donne donc jamais accès à plus de champs que la lecture en JSON.

Une différence sépare les deux chemins. Ce point d'entrée ne sert que les passeports dont la visibilité est publique. Un passeport réservé au propriétaire ou réservé à la marque n'y est jamais rendu, même à son propriétaire.

#Le contrôle d'origine

Vos appels de serveur à serveur passent tels quels. Deux situations donnent un 403.

Un appel émis par une page web ouverte sur un domaine qui n'est pas le nôtre porte un en-tête Origin ou Referer que nous refusons. N'appelez donc pas ce point d'entrée depuis le navigateur d'un visiteur, appelez-le depuis votre serveur.

Un appel qui porte le cookie de session sans en-tête Origin ni Referer est refusé lui aussi. Le cookie de session ne vaut que depuis une page servie par un de nos domaines. Depuis un serveur ou depuis la ligne de commande, présentez le jeton dans Authorization: Bearer.

#Plafond d'appels

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

Ce compteur est commun à tous les chemins qui commencent par /passport. Les appels que vous adressez à l'un d'eux entament le budget des autres. Le préfixe /v1 ne crée pas un second budget : /v1/passport/EXEMP1E00001/vc et /passport/EXEMP1E00001/vc 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 depuis le 1er janvier 1970

Un dépassement 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
identifierstringouiLe produit dont vous voulez le justificatif. 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.

Aucun en-tête n'est obligatoire dans la requête.

#Les trois formes d'identifiant acceptées

FormeÀ quoi elle ressembleOù vous la trouvez
Numéro de série12 caractères, chiffres et lettres majuscules. Les lettres I, L, O et U n'y figurent jamais.Imprimé 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, il la dérive de l'identifiant de la puce pour un produit NFC.

Le serveur reconnaît la forme à l'écriture. Il cherche une valeur qui commence par 0x et fait exactement 66 caractères comme une empreinte d'identifiant. Il cherche toute autre valeur d'abord comme un identifiant de jeton. Il essaie le numéro de série en dernier, quand les deux premières recherches n'ont rien donné.

Le serveur reconnaît l'empreinte d'identifiant quelle que soit la casse. Il reconnaît aussi le numéro de série quelle que soit la casse, et il le canonicalise comme le fait le résolveur du QR : il lit les lettres I et L comme un 1, la lettre O comme un 0. Vous pouvez donc lui envoyer un numéro recopié à la main depuis une étiquette.

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

#Les six valeurs de access_tier

Ces niveaux sont des publics différents, sans hiérarchie entre eux. Un recycleur n'est pas au-dessus d'un réparateur. 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 que le justificatif révèle
publicidentification du produit, conformité ESPR, REACH et marquage CE, pourcentage de recyclabilité, pourcentage de contenu recyclé, étiquettes, spécification générale de batterie. Ces champs figurent en clair dans le jeton signé, aucune divulgation n'est jointe.
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 champs du document

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. Les mêmes règles s'appliquent ici et sur la lecture en JSON.

Le serveur refuse toute autre valeur en 422. Il renvoie le niveau réellement servi dans le champ access_tier de la réponse et dans l'en-tête X-DPP-Access-Tier. Lisez l'un des deux plutôt que de le supposer.

#Corps de la requête

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

#Requête d'exemple

Justificatif public du produit dont le numéro imprimé est EXEMP1E00001.

curl -s "https://api.sealtrust.io/v1/passport/EXEMP1E00001/vc?access_tier=public"

Les trois onglets appellent la même adresse avec les mêmes valeurs. L'onglet curl écrit la réponse brute sur la sortie standard. Les onglets TypeScript et Python en extraient les mêmes champs, dans le même ordre.

#Réponse d'exemple

Code HTTP 200OK

Code HTTP 200.

Les valeurs ci-dessous sont fictives. Le jeton signé et les segments de divulgation sont raccourcis, un jeton réel fait plusieurs milliers de caractères.

JSON
{
  "passport_id": 1,
  "issuer": "did:web:api.sealtrust.io:brand:4242",
  "vct": "https://schema.sealtrust.io/vct/digital-product-passport",
  "access_tier": "public",
  "format": "dc+sd-jwt",
  "sd_jwt_vc": "eyJhbGciOiJFUzI1NiIsInR5cCI6ImRjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6YXBpLnNlYWx0cnVzdC5pbzpicmFuZDo0MjQyI2tleS0xIn0.RVhFTVBMRV9DSEFSR0VfVVRJTEU.RVhFTVBMRV9TSUdOQVRVUkU~"
}
ChampTypePrésenceDescription
passport_idintegertoujoursL'identifiant de la version du passeport à laquelle se rapporte ce justificatif.
issuerstringtoujoursL'identifiant décentralisé did:web de la marque qui a signé. C'est lui qui mène à la clef publique de vérification. Toujours renseigné sur ce point d'entrée.
vctstringtoujoursL'identifiant du modèle de justificatif. Vaut https://schema.sealtrust.io/vct/digital-product-passport à défaut de valeur enregistrée sur le passeport.
access_tierstringtoujoursLe niveau réellement servi.
formatstringtoujoursToujours dc+sd-jwt. C'est le type de média du justificatif à divulgation sélective.
sd_jwt_vcstringtoujoursLe justificatif lui-même. Voir ci-dessous.

#En-têtes de réponse à connaître

En-têteContenu
X-DPP-Access-Tierle niveau réellement servi
Cache-Controlno-store, max-age=0, quel que soit le niveau servi. Ne placez cette réponse derrière aucun cache partagé.

#Lire le champ sd_jwt_vc

Le contenu de sd_jwt_vc est une suite de segments séparés par le caractère ~. Le dernier segment est toujours vide, donc la chaîne se termine par un ~.

Texte
<jeton signé>~<divulgation>~<divulgation>~

Le premier segment est un jeton signé en trois parties, séparées par des points. L'en-tête et la charge utile sont encodés en base64url, sans remplissage. Vous les décodez sans clef.

L'en-tête porte trois valeurs.

ValeurContenu
algES256. La signature est une signature ECDSA sur la courbe P-256.
typdc+sd-jwt
kidL'identifiant de la clef qui a signé, sous la forme <did de la marque>#key-<numéro de version>.

La charge utile porte les champs suivants.

ChampContenu
issL'identifiant did:web de la marque émettrice. Il vaut la même valeur que le champ issuer de la réponse.
vctL'identifiant du modèle de justificatif.
iatLa date d'émission, en secondes depuis le 1er janvier 1970.
@context["https://www.w3.org/ns/credentials/v2", "https://schema.sealtrust.io/dpp/v1"]
type["VerifiableCredential", "DigitalProductPassport"]
issuerRépétition de iss, attendue par le modèle de données des justificatifs vérifiables.
validFromLa date d'émission au format ISO 8601, à la seconde, en temps universel.
credentialSubjectLes données du passeport. Les champs publics y figurent en clair. Les autres sont remplacés par des empreintes, sous la clef _sd.
credentialSchemaUn objet à deux clefs, id qui reprend vct, et type qui vaut JsonSchema.
productL'identité du produit : uid_hash, token_id et name. Jamais masquée.
brandL'identité de la marque : name, lei_code, eori_number, website_url, postal_address, contact_email. Jamais masquée. Les valeurs non renseignées sont absentes.

Un passeport peut porter sur un modèle de produit ou sur un exemplaire précis. Quand la marque publie un passeport de modèle, il vaut pour tous les exemplaires qui partagent le même code produit, et le justificatif émis à cette publication porte uid_hash et token_id à null dans le bloc product : il ne désigne aucun exemplaire en particulier.

Les segments suivants sont les divulgations. Chacun est un tableau de trois éléments encodé en base64url : un sel, le nom du champ, sa valeur. Vous les décodez sans clef. Leur nombre dépend du niveau demandé.

Texte
WyJFWEVNUExFMDAwMDAwMDAwMDAwMDAwMCIsInJlcGFpcmFiaWxpdHlfaW5kZXgiLDguMl0

Ce segment d'exemple se décode en ["EXEMPLE0000000000000000", "repairability_index", 8.2].

Au niveau public, la réponse ne révèle rien de plus que les champs toujours présents dans le document signé. La chaîne se réduit alors au jeton signé suivi d'un ~. Chaque autre niveau ajoute les divulgations qui le concernent.

#Vérifier la signature vous-même

Le champ issuer porte un identifiant did:web. Il désigne un document public qui contient les clefs publiques de la marque, exprimées en JsonWebKey2020. La clef à utiliser est celle dont l'identifiant correspond au kid de l'en-tête du jeton. Ce document ne contient que les clefs non révoquées, donc une clef révoquée n'y figure plus.

Un identifiant de la forme did:web:api.sealtrust.io:brand:4242 se résout à https://api.sealtrust.io/brand/4242/did.json. Un identifiant de la forme did:web:id.exemple-sas.example se résout à https://id.exemple-sas.example/.well-known/did.json. Une marque peut héberger elle-même ce document sur son propre domaine, auquel cas la vérification de ses passeports ne dépend d'aucun de nos serveurs.

Si vous préférez que la vérification soit faite pour vous, appelez GET /v1/passport/{identifier}/vc/verify.

#Erreurs

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

CodeConditionQue faire
401Vous demandez authority sans session. detail vaut Authority-tier access requires authentication.Connectez-vous, puis présentez le jeton de session dans Authorization: Bearer.
401Vous demandez repairer, recycler ou upstream sans session. detail vaut Professional-tier access requires authentication.Connectez-vous, puis présentez le jeton de session dans Authorization: Bearer. Une clef d'API ne convient pas.
403Vous demandez authority avec une session qui ne porte pas ce rôle. detail vaut Authority-tier access is restricted to market surveillance authorities.Demandez un niveau qui correspond à votre situation.
403Vous demandez un niveau professionnel sans accréditation active sur la marque du produit, sans accès à cette marque et sans le rôle d'autorité. detail commence par This tier is restricted to the product's brand.Demandez à la marque de vous accréditer, puis redemandez le niveau qui correspond à votre métier.
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, jamais depuis le navigateur d'un visiteur.
403L'appel porte un cookie de session sans en-tête Origin ni Referer. detail vaut Origin or Referer header required.Présentez le jeton dans Authorization: Bearer au lieu du cookie de session.
404Aucun produit au catalogue ne correspond à cet identifiant, sous aucune des trois formes acceptées. detail vaut Product not found.Vérifiez l'identifiant. Un exemplaire détruit sur la chaîne, remplacé par une version ultérieure ou retiré donne cette même réponse.
404Le produit 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. Ce produit n'a pas de passeport public. Un passeport réservé au propriétaire ou à la marque donne la même réponse.
404Le passeport existe et il est public, mais aucun justificatif signé n'a encore été émis pour lui. detail commence par No VC issued for this passport yet.Lisez le passeport en JSON avec GET /v1/passport/{identifier}. Publier une version d'un passeport émet son justificatif : demandez à la marque de republier la version en cours.
404La marque du passeport n'est pas résolvable. detail vaut Brand not found.Signalez-le au support. Aucune action de votre côté ne change cette réponse.
422La valeur de access_tier ne fait pas partie des six acceptées. detail est une liste d'objets qui nomment le paramètre en cause.Corrigez la valeur. Les six valeurs acceptées sont listées plus haut.
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.

#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