Méthode GET/passport /{identifier} /vc /preview
Voir, sans signature et sans rien enregistrer, l'enveloppe de justificatif vérifiable et le document JSON-LD qu'un niveau d'accès donné exposerait pour un passeport.
Sur cette page
- Autorisation
- Contrôle de l'origine
- Plafond d'appels
- Paramètres de chemin et de requête
- Les six valeurs de access_tier
- L'adresse complète et l'alias sans /v1
- Ce que cet aperçu ne prouve pas
- Corps de la requête
- Requête d'exemple
- Réponse d'exemple
- Le champ issuer
- Le champ credentialSubject
- Passeport d'un modèle ou d'un lot
- Erreurs
- Voir aussi
Ce point d'entrée rend, sans signature et sans rien enregistrer, l'enveloppe de justificatif vérifiable et le document JSON-LD qu'un niveau d'accès donné exposerait pour le passeport d'un produit.
#Autorisation
Aucune pour le niveau public. Ce point d'entrée est alors ouvert, sans clef
d'API ni session.
Les cinq autres valeurs du paramètre access_tier exigent une session de
compte. Depuis votre serveur, présentez-la dans l'en-tête
Authorization: Bearer <jeton de session>. Le cookie access_token ouvre les
mêmes niveaux, uniquement dans un appel qui porte aussi un en-tête Origin ou
Referer que nous acceptons, donc depuis nos propres pages. Une clef d'API
partenaire ne convient pas : ce point d'entrée ne lit qu'un jeton de session,
dans l'en-tête Authorization ou dans le cookie. Une clef d'API n'ouvre donc
aucun niveau au-delà de public.
| Niveau demandé | Ce qu'il faut présenter |
|---|---|
public | rien Pour un passeport batterie, s'y ajoutent les champs que le point 1 de l'annexe XIII rend publics : substances dangereuses, matières premières critiques, empreinte carbone et sa classe, rapport de diligence raisonnable, contenu recyclé après consommation par métal et part de contenu renouvelable. À l'inverse, les références de pièces, l'état de la batterie et la durée de vie en cycles en sont retirés : les points 2 et 4 les réservent aux personnes ayant un intérêt légitime. Pour un passeport textile, s'y ajoutent le nom et le pourcentage de chaque matière, la composition en fibres que le règlement (UE) n° 1007/2011 impose sur l'étiquette. Pour un passeport chaussure, la matière de la tige, de la doublure, de la première de propreté et de la semelle, que la directive 94/11/CE fait figurer sur la chaussure. |
end_user | une session, quel que soit le compte |
repairer | une session dont le compte porte une accréditation de réparateur active sur la marque du produit, une session de la marque elle-même, ou une session portant le rôle d'autorité de surveillance du marché |
recycler | une session dont le compte porte une accréditation de recycleur active sur la marque du produit, une session de la marque elle-même, ou une session portant le rôle d'autorité de surveillance du marché |
upstream | une session de la marque du produit, ou une session portant le rôle d'autorité de surveillance du marché |
authority | une session portant le rôle d'autorité de surveillance du marché |
Nous ne servons ici que les passeports en visibilité publique. Un passeport
réservé au propriétaire du produit répond 404 sur ce point d'entrée, y compris
pour ce propriétaire, alors que GET /v1/passport/{identifier} le lui sert. Un
passeport réservé à la marque n'est jamais rendu ici.
#Contrôle de l'origine
Ce point d'entrée refuse tout appel dont l'en-tête Origin ou Referer
désigne un domaine qui n'est pas le nôtre, avec 403 Forbidden origin. Le
refus ne regarde pas la nature du client : un programme lancé sur votre serveur
qui envoie un Referer reçoit le même 403 qu'une page web.
Deux règles pour appeler depuis votre serveur.
- N'envoyez pas d'en-tête
Referer. La plupart des bibliothèques HTTP n'en envoient aucun tant que vous ne le demandez pas. - Présentez votre session dans
Authorization: Bearer <jeton de session>. Un appel de serveur qui s'appuie sur le cookieaccess_tokenest refusé avec 403Origin or Referer header required.
N'appelez pas cette adresse depuis le navigateur de votre visiteur : un appel JavaScript lancé depuis une page hébergée ailleurs que chez nous est refusé.
#Plafond d'appels
600 appels par tranche de 60 secondes, comptés par adresse réseau appelante.
Ce compteur est commun à toutes les lectures (GET) dont l'adresse commence 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/vc/preview et
/passport/1042/vc/preview 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 600 |
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 |
|---|---|---|---|
identifier | string | oui | L'article dont vous voulez l'aperçu. Trois formes sont acceptées, voir ci-dessous. |
access_tier | string | non | Le niveau d'accès demandé. Vaut public par défaut. Six valeurs acceptées, listées plus bas. |
identifier accepte trois formes, essayées dans cet ordre.
| Forme | Aspect | Provenance |
|---|---|---|
| Empreinte d'identifiant | 0x suivi de 64 caractères hexadécimaux | l'empreinte de l'identifiant unique de l'article. Nous la lisons sur la puce pour un article NFC, et nous la tirons au hasard à la frappe pour un article QR |
| Identifiant de jeton | un nombre écrit en décimal | l'identifiant de l'article sur la chaîne |
| Numéro de série imprimé | 12 caractères | ce que porte le QR code sur le produit, dans l'adresse /p/{serial} |
Vous pouvez écrire le numéro de série en minuscules ou en majuscules. 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. GET /v1/passport/{identifier} se comporte autrement : il
continue de servir le dernier passeport publié pour ces articles.
#Les six valeurs de access_tier
Ces niveaux ne forment pas une échelle. Ils décrivent six publics dont les besoins diffèrent. Un recycleur et un réparateur voient des données différentes.
| Valeur | Sections du passeport retenues avant rendu |
|---|---|
public | identité du produit, conformité ESPR, conformité REACH, marquage CE, taux de recyclabilité, taux de matière recyclée, étiquettes, spécification de batterie, marquages des articles 13(4) et 13(5), agent extincteur, déclaration UE de conformité, information sur la gestion des déchets, et pour un textile ou une chaussure les mentions d'étiquette décrites plus haut |
end_user | tout le niveau public, plus impact environnemental, circularité complète, matière principale, mention de matière certifiée biologique, durabilité, efficacité énergétique, empreinte carbone |
repairer | tout le niveau end_user, plus nomenclature, lien vers les instructions de démontage, indice de réparabilité, état de santé de la batterie |
recycler | tout le niveau end_user, plus composition matière complète, substances préoccupantes, lien vers les instructions de démontage, état de santé de la batterie |
upstream | tout le niveau end_user, plus composition matière complète, substances préoccupantes, fabrication, chaîne d'approvisionnement |
authority | l'intégralité des données, sans filtrage |
Les champs que la console écrit à la racine du passeport ont chacun leur propre niveau, nommé un par un : voir Les règles d'accès au passeport.
Ce tableau décrit le filtre appliqué avant la conversion en JSON-LD. Plusieurs de ces sections restent absentes du document rendu, parce que ce point d'entrée ne les convertit pas. L'encadré plus bas les liste toutes.
Une marque peut resserrer ou élargir ces listes pour ses propres produits. Les valeurs ci-dessus sont celles qui s'appliquent quand elle n'a rien changé.
#L'adresse complète et l'alias sans /v1
GET https://api.sealtrust.io/v1/passport/{identifier}/vc/previewLe même point d'entrée répond aussi sans le préfixe /v1, à
https://api.sealtrust.io/passport/{identifier}/vc/preview. Les deux adresses
appellent le même code. Utilisez la forme /v1 pour une nouvelle intégration.
#Ce que cet aperçu ne prouve pas
Un justificatif vérifiable est un document que son émetteur signe, et que n'importe qui peut contrôler ensuite sans nous redemander quoi que ce soit. Ce point d'entrée en montre la forme avant signature.
#Corps de la requête
Aucun. Cette requête n'a pas de corps.
#Requête d'exemple
Aperçu public du justificatif de l'article dont le numéro de série imprimé est
EXEMPLE00001.
curl -i "https://api.sealtrust.io/v1/passport/EXEMPLE00001/vc/preview?access_tier=public"const url = new URL(
"https://api.sealtrust.io/v1/passport/EXEMPLE00001/vc/preview",
);
url.searchParams.set("access_tier", "public");
const reponse = await fetch(url);
if (reponse.status === 404) {
console.log("Aucun passeport public pour cet identifiant.");
} else if (reponse.ok) {
const apercu = await reponse.json();
console.log("Émetteur :", apercu.issuer);
console.log("Modèle de justificatif :", apercu.vct);
console.log("Niveau demandé :", apercu.access_tier);
console.log("Signé :", apercu.signed);
const sujet = apercu.credentialSubject;
console.log(sujet.name, sujet.gtin, sujet.brand.name);
for (const propriete of sujet.additionalProperty ?? []) {
console.log(propriete.name, propriete.value, propriete.unitText ?? "");
}
} else {
console.log(reponse.status, await reponse.json());
}import requests
response = requests.get(
"https://api.sealtrust.io/v1/passport/EXEMPLE00001/vc/preview",
params={"access_tier": "public"},
timeout=30,
)
if response.status_code == 404:
print("Aucun passeport public pour cet identifiant.")
elif response.ok:
apercu = response.json()
print("Émetteur :", apercu["issuer"])
print("Modèle de justificatif :", apercu["vct"])
print("Niveau demandé :", apercu["access_tier"])
print("Signé :", apercu["signed"])
sujet = apercu["credentialSubject"]
print(sujet.get("name"), sujet.get("gtin"), sujet["brand"]["name"])
for propriete in sujet.get("additionalProperty", []):
print(propriete["name"], propriete["value"], propriete.get("unitText", ""))
else:
print(response.status_code, response.json())#Réponse d'exemple
Code HTTP 200OK
Code HTTP 200.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://schema.sealtrust.io/dpp/v1"
],
"type": ["VerifiableCredential", "DigitalProductPassport"],
"issuer": "did:web:api.sealtrust.io:brand:4242",
"vct": "https://schema.sealtrust.io/vct/digital-product-passport",
"credentialSubject": {
"@context": {
"@vocab": "https://schema.org/",
"gs1": "https://gs1.org/voc/",
"espr": "https://data.europa.eu/espr/"
},
"@type": "Product",
"identifier": "0x1111111111111111111111111111111111111111111111111111111111111111",
"gtin": "03701234567891",
"name": "Modèle Exemple 001",
"brand": {
"@type": "Brand",
"name": "Exemple SAS",
"identifier": "00000000000000000000",
"url": "https://exemple.example"
},
"countryOfOrigin": "FR",
"material": [],
"additionalProperty": [
{
"@type": "PropertyValue",
"name": "Recyclability (EN 45555)",
"value": 82,
"unitText": "percent"
},
{
"@type": "PropertyValue",
"name": "gs1:recycledContentPercentage",
"value": 35,
"unitText": "percent"
}
],
"espr:compliance": {
"@type": "espr:ComplianceDeclaration",
"espr:euEsprCompliant": true,
"espr:reachCompliant": true,
"espr:ceMarking": true
}
},
"access_tier": "public",
"signed": false,
"note": "Unsigned preview — POST /vc/issue to mint the signed SD-JWT-VC."
}| Champ | Type | Description |
|---|---|---|
@context | string[] | Les deux vocabulaires du document, dans cet ordre : le modèle de justificatif vérifiable du W3C, puis le nôtre. |
type | string[] | Toujours ["VerifiableCredential", "DigitalProductPassport"]. |
issuer | string | L'identifiant did:web de la marque qui émettrait ce justificatif. Voir ci-dessous. |
vct | string | L'identifiant du modèle de justificatif. Vaut https://schema.sealtrust.io/vct/digital-product-passport quand la marque n'en a pas défini un autre. |
credentialSubject | object | Le passeport rendu en JSON-LD, filtré au niveau demandé. Voir ci-dessous. |
access_tier | string | Le niveau que vous avez demandé. |
signed | boolean | Toujours false sur ce point d'entrée. |
note | string | Un texte fixe, en anglais, qui rappelle que l'aperçu n'est pas signé. Ne branchez aucun code dessus. |
Le champ access_tier de la réponse et l'en-tête X-DPP-Access-Tier
reprennent le niveau que vous avez demandé. L'appel réussit au niveau demandé
ou échoue en 401 ou en 403. Il n'y a pas de repli silencieux vers un niveau
plus bas.
La réponse porte Cache-Control: private, no-store à un niveau professionnel,
et public, max-age=60, s-maxage=300 au seul niveau public. Aucun cache
partagé ne conserve donc une réponse obtenue à un niveau professionnel.
#Le champ issuer
C'est l'identité de l'émetteur, sous la forme did:web. Elle prend deux
formes selon ce que la marque a choisi.
| Forme | Où se lit le document d'identité |
|---|---|
did:web:<hôte>:brand:<numéro> | https://<hôte>/brand/<numéro>/did.json |
did:web:<domaine de la marque> | https://<domaine de la marque>/.well-known/did.json |
La première forme s'applique par défaut, et la marque n'a rien à faire pour l'obtenir. La seconde demande que la marque déclare son propre domaine et y publie son document d'identité.
Lisez la valeur rendue telle quelle. Ne la reconstruisez pas de votre côté : une marque peut passer d'une forme à l'autre.
#Le champ credentialSubject
C'est le passeport rendu en JSON-LD, avec le vocabulaire Schema.org, le
vocabulaire web de GS1 et nos extensions ESPR. Il porte son propre @context,
qui est un objet, alors que celui du premier niveau est une liste. Les deux
coexistent normalement.
| Champ | Type | Présence | Description |
|---|---|---|---|
@context | object | toujours | Les trois vocabulaires employés dans ce document. |
@type | string | toujours | Toujours Product. |
identifier | string | toujours pour un article frappé | L'empreinte de l'identifiant unique de l'article. Elle existe aussi bien pour un article QR seul que pour un article à puce. |
gtin | string | si renseigné | Le code article GS1 du produit. |
name | string | si renseigné | Le modèle déclaré dans le passeport. À défaut, le nom du produit. |
brand | object | toujours | La marque : name, et selon ce qu'elle a renseigné identifier (son code LEI), url, address, email. |
countryOfOrigin | string | si renseigné | Le pays de fabrication déclaré. |
gs1:productionFacility | string | si renseigné | Le site de production déclaré. |
espr:operatorIdentifier | string | si renseigné | L'identifiant de l'opérateur économique au sens de l'ESPR. |
espr:batteryPassportIdentifier | string | si renseigné | L'identifiant de passeport de batterie. |
espr:uniqueBatteryIdentifier | string | si renseigné | L'identifiant unique de la batterie. |
espr:eprelRegistration | string | si renseigné et visible | Le numéro d'enregistrement EPREL de l'étiquette énergie. |
material | object[] | toujours | La composition matière. Liste vide quand aucune matière n'est visible au niveau demandé. |
additionalProperty | object[] | toujours | Les mesures environnementales, de circularité, de batterie et d'efficacité énergétique, sous forme de couples nom et valeur. Liste vide quand aucune n'est visible. |
maintenanceTechnicalDataUrl | string | si renseigné et visible | Le lien vers les instructions de démontage. |
espr:compliance | object | si la section conformité est visible | Les déclarations de conformité retenues au niveau demandé. |
Une entrée de additionalProperty porte @type valant PropertyValue, un
name en anglais, une value, et un unitText quand la grandeur a une unité.
Les noms sont ceux du vocabulaire, par exemple Recyclability (EN 45555) ou
gs1:recycledContentPercentage. Branchez votre code sur name, sur la valeur
exacte, sans traduction.
#Passeport d'un modèle ou d'un lot
Un passeport de modèle, ou d'un lot de production, n'est rattaché à aucun
exemplaire. Il n'a donc aucun identifiant à passer dans {identifier}. Son
aperçu non signé se lit à l'adresse GS1 du passeport lui-même, à côté du passeport et de
sa preuve :
GET https://api.sealtrust.io/v1/passport/01/{gtin}/vc/preview
GET https://api.sealtrust.io/v1/passport/01/{gtin}/10/{lot}/vc/previewLa première adresse vise le passeport du modèle qui porte ce GTIN. La seconde
vise le passeport du lot {lot} de ce modèle. Comme les autres adresses de
cette page, chacune répond aussi sans le préfixe /v1.
| Nom | Type | Obligatoire | Description |
|---|---|---|---|
gtin | string | oui | Le GTIN du modèle, sur 8, 12, 13 ou 14 chiffres. Son chiffre de contrôle est vérifié. |
lot | string | sur la seconde adresse | Le numéro du lot (identifiant d'application GS1 10), tel qu'il est imprimé, majuscules et minuscules comprises. Un caractère réservé, comme /, s'encode en pourcentage. |
C'est la seule façon de prévisualiser le justificatif d'une marque à l'offre Conformité, qui n'enregistre aucun exemplaire.
Le niveau d'accès, les règles d'autorisation, le plafond d'appels et les champs de la réponse sont ceux de cette page. La réponse ajoute deux champs, et un troisième pour un lot.
| Champ | Type | Présence | Description |
|---|---|---|---|
level | string | sur ces deux adresses | model pour un passeport de modèle, batch pour un passeport de lot. |
gtin | string | sur ces deux adresses | Le GTIN, ramené à 14 chiffres. |
batch_code | string | sur l'adresse du lot | Le numéro du lot. |
L'aperçu d'un modèle ou d'un lot porte l'identité du modèle seule. Dans
credentialSubject, identifier vaut null.
L'adresse d'un lot ne vise que le passeport de ce lot. Un lot sans passeport publié répond 404, et jamais par l'aperçu du modèle.
#Erreurs
Le corps d'une réponse d'erreur porte un champ detail.
| Code | Condition | Que faire |
|---|---|---|
| 401 | access_tier=end_user est demandé sans session valide. detail vaut End-user-tier access requires authentication. | Connectez-vous avec n'importe quel compte, ou demandez le niveau public. |
| 401 | access_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. |
| 401 | access_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. Un jeton expiré est traité comme une absence de session. Sinon, demandez le niveau public. |
| 403 | L'appel porte un en-tête Origin ou Referer qui désigne un domaine qui n'est pas le nôtre. detail vaut Forbidden origin. | Depuis votre serveur, cessez d'envoyer un en-tête Referer, ou présentez votre session dans Authorization: Bearer <jeton>. |
| 403 | L'appel n'envoie ni Origin ni Referer, et porte un cookie access_token. detail vaut Origin or Referer header required. | Depuis votre serveur, présentez la session dans Authorization: Bearer <jeton> au lieu du cookie. |
| 403 | access_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. |
| 403 | access_tier vaut repairer, recycler ou upstream, et le compte connecté n'appartient ni à la marque du produit, ni aux autorités, et ne porte pas 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. | Faites-vous accréditer par la marque du produit, puis demandez le niveau de votre métier. |
| 404 | Aucun passeport public ne répond à cet identifiant. Soit aucun article au catalogue ne correspond à cet identifiant, soit l'article existe et ne porte aucun passeport publié en visibilité publique, ni directement, ni par son modèle. | Ne traitez pas cette réponse comme une panne. Vérifiez votre identifiant, et prévoyez le cas d'un article sans passeport public. Un passeport réservé au propriétaire ou à la marque donne la même réponse, comme un article détruit sur la chaîne, remplacé ou archivé. |
| 404 | Le passeport trouvé renvoie à une marque qui n'existe plus. detail vaut Brand not found. | Signalez le cas au support. Aucune action de votre côté ne corrige cet état. |
| 404 | L'appel arrive sur le nom de domaine vérifié d'une marque, et le produit appartient à une autre marque. detail vaut Product not found. | Appelez cette adresse sur le domaine de la marque concernée, ou sur api.sealtrust.io. Le message est le même que pour un identifiant inconnu, pour ne pas confirmer qu'il existe. |
| 400 | Sur l'adresse d'un modèle ou d'un lot, le chiffre de contrôle du GTIN est faux. detail vaut Invalid GTIN: the check digit does not match. | Recopiez le GTIN depuis l'étiquette. |
| 404 | Sur l'adresse d'un modèle ou d'un lot : aucun passeport publié en visibilité publique ne répond à ce GTIN ou à ce lot, plusieurs marques publient un passeport sous ce GTIN, ou l'appel arrive sur le domaine vérifié d'une autre marque. detail vaut Unknown GS1 Digital Link dans tous ces cas. | Vérifiez le GTIN et le numéro du lot. Le message est le même dans tous ces cas, pour ne pas confirmer qu'un GTIN existe. |
| 422 | La valeur de access_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. |
| 429 | Le plafond de 600 appels par 60 secondes est atteint pour votre adresse réseau, sur l'ensemble des lectures /passport. detail vaut Rate limit exceeded: 600 requests per 60s. | Attendez le nombre de secondes indiqué par Retry-After, puis réessayez. Espacez vos appels. |
| 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. |
Le code porte encore un dernier cas, 422 avec detail valant
Brand has no persisted id; cannot derive a did:web issuer. Vous ne le
rencontrerez pas : toute marque enregistrée reçoit une identité d'émetteur,
did:web:api.sealtrust.io:brand:<numéro> quand elle n'a pas déclaré son propre
domaine.
#Voir aussi
GET /passport/{identifier}/vc, récupérer le justificatif signé du passeport, au format SD-JWT-VC.GET /passport/{identifier}/vc/verify, contrôler la signature du justificatif et lire les données révélées.GET /brand/{brand_id}/did.json, récupérer les clefs publiques de signature d'une marque.- Publier un passeport numérique de produit, publier, choisir qui voit quels champs, exporter et faire vérifier.
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.