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

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 les niveaux public et end_user. Ce point d'entrée est alors ouvert, sans clef d'API ni session.

Les quatre 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 et de end_user.

Niveau demandéCe qu'il faut présenter
publicrien
end_userrien
repairerune 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é
recyclerune 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é
upstreamune session de la marque du produit, ou une session portant le rôle d'autorité de surveillance du marché
authorityune 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 cookie access_token est refusé avec 403 Origin 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

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/vc/preview et /passport/1042/vc/preview 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 l'aperçu. 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.

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

ValeurSections du passeport retenues avant rendu
publicidentité du produit, conformité ESPR, conformité REACH, marquage CE, taux de recyclabilité, taux de matière recyclée, étiquettes, spécification de batterie
end_usertout le niveau public, plus impact environnemental, circularité complète, matière principale, mention de coton biologique certifié, durabilité, efficacité énergétique, empreinte carbone
repairertout le niveau end_user, plus nomenclature, lien vers les instructions de démontage, indice de réparabilité, état de santé de la batterie
recyclertout 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
upstreamtout le niveau end_user, plus composition matière complète, substances préoccupantes, fabrication, chaîne d'approvisionnement
authorityl'intégralité des données, sans filtrage

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

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

Le 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"

#Réponse d'exemple

Code HTTP 200OK

Code HTTP 200.

JSON
{
  "@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": "03701234567890",
    "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."
}
ChampTypeDescription
@contextstring[]Les deux vocabulaires du document, dans cet ordre : le modèle de justificatif vérifiable du W3C, puis le nôtre.
typestring[]Toujours ["VerifiableCredential", "DigitalProductPassport"].
issuerstringL'identifiant did:web de la marque qui émettrait ce justificatif. Voir ci-dessous.
vctstringL'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.
credentialSubjectobjectLe passeport rendu en JSON-LD, filtré au niveau demandé. Voir ci-dessous.
access_tierstringLe niveau que vous avez demandé.
signedbooleanToujours false sur ce point d'entrée.
notestringUn 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: no-store, max-age=0. Aucun cache partagé ne doit donc conserver 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.

FormeOù 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.

ChampTypePrésenceDescription
@contextobjecttoujoursLes trois vocabulaires employés dans ce document.
@typestringtoujoursToujours Product.
identifierstringtoujours 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.
gtinstringsi renseignéLe code article GS1 du produit.
namestringsi renseignéLe modèle déclaré dans le passeport. À défaut, le nom du produit.
brandobjecttoujoursLa marque : name, et selon ce qu'elle a renseigné identifier (son code LEI), url, address, email.
countryOfOriginstringsi renseignéLe pays de fabrication déclaré.
gs1:productionFacilitystringsi renseignéLe site de production déclaré.
espr:operatorIdentifierstringsi renseignéL'identifiant de l'opérateur économique au sens de l'ESPR.
espr:batteryPassportIdentifierstringsi renseignéL'identifiant de passeport de batterie.
espr:uniqueBatteryIdentifierstringsi renseignéL'identifiant unique de la batterie.
espr:eprelRegistrationstringsi renseigné et visibleLe numéro d'enregistrement EPREL de l'étiquette énergie.
materialobject[]toujoursLa composition matière. Liste vide quand aucune matière n'est visible au niveau demandé.
additionalPropertyobject[]toujoursLes 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.
maintenanceTechnicalDataUrlstringsi renseigné et visibleLe lien vers les instructions de démontage.
espr:complianceobjectsi la section conformité est visibleLes 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.

#Erreurs

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

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. Un jeton expiré est traité comme une absence de session. Sinon, demandez le niveau public ou end_user.
403L'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>.
403L'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.
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.
403access_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.
404Aucun 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é.
404Le 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.
422La 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.
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. Espacez vos appels.
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.

Le code porte encore un dernier cas, 422 avec detail valant Brand has no website_url; 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

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