Method GET/passport/{identifier}/vc/preview

See, without a signature and without recording anything, the verifiable credential envelope and the JSON-LD document that a given access tier would expose for a passport.

On this page

This endpoint returns, without a signature and without recording anything, the verifiable credential envelope and the JSON-LD document that a given access tier would expose for a product's passport.

#Authorization

None for the public and end_user tiers. This endpoint is then open, with no API key and no session.

The four other values of the access_tier parameter require an account session. From your server, present it in the header Authorization: Bearer <session token>. The access_token cookie opens the same tiers, only in a call that also carries an Origin or Referer header that we accept, that is, from our own pages. A partner API key does not work: this endpoint reads only a session token, in the Authorization header or in the cookie. An API key therefore opens no tier beyond public and end_user.

Tier requestedWhat you must present
publicnothing
end_usernothing
repairera session whose account holds an active repairer accreditation on the product's brand, a session of the brand itself, or a session carrying the market surveillance authority role
recyclera session whose account holds an active recycler accreditation on the product's brand, a session of the brand itself, or a session carrying the market surveillance authority role
upstreama session of the product's brand, or a session carrying the market surveillance authority role
authoritya session carrying the market surveillance authority role

We serve here only the passports with public visibility. A passport reserved for the product's owner answers 404 on this endpoint, including for that owner, whereas GET /v1/passport/{identifier} serves it to them. A passport reserved for the brand is never returned here.

#Origin check

This endpoint refuses any call whose Origin or Referer header designates a domain that is not ours, with 403 Forbidden origin. The refusal does not look at the nature of the client: a program launched on your server that sends a Referer receives the same 403 as a web page.

Two rules for calling from your server.

  • Do not send a Referer header. Most HTTP libraries send none until you ask for it.
  • Present your session in Authorization: Bearer <session token>. A server call that relies on the access_token cookie is refused with 403 Origin or Referer header required.

Do not call this address from your visitor's browser: a JavaScript call launched from a page hosted anywhere other than with us is refused.

#Rate limit

60 calls per 60 second window, counted per calling network address.

This counter is shared by every path that starts with /passport. The calls you address to one of them therefore eat into the budget of the others. The /v1 prefix does not create a second budget: /v1/passport/1042/vc/preview and /passport/1042/vc/preview fill the same counter.

Every accepted response carries three headers.

HeaderContents
X-RateLimit-Limitthe limit applied over the window, here 60
X-RateLimit-Remainingwhat is left to you in the current window
X-RateLimit-Resetthe timestamp of the end of the window, in seconds

A refusal returns 429, with those three headers and Retry-After. On this endpoint, Retry-After equals the duration of the window, that is 60 seconds.

#Path and query parameters

NameTypeRequiredDescription
identifierstringyesThe item you want the preview of. Three forms are accepted, see below.
access_tierstringnoThe access tier requested. Equals public by default. Six accepted values, listed below.

identifier accepts three forms, tried in this order.

FormAppearanceOrigin
Identifier hash0x followed by 64 hexadecimal charactersthe hash of the item's unique identifier. We read it on the chip for an NFC item, and we draw it at random at minting time for a QR item
Token identifiera number written in decimalthe item's identifier on the chain
Printed serial number12 characterswhat the QR code on the product carries, in the address /p/{serial}

You can write the serial number in lowercase or in uppercase. We reduce the characters that look alike to a single form before the lookup, so an I or an L entered by hand finds the 1, and an O finds the 0.

This endpoint resolves only the items still in the brand's catalog. An item destroyed on the chain, replaced by a later version or archived answers 404. GET /v1/passport/{identifier} behaves differently: it keeps serving the last published passport for those items.

#The six values of access_tier

These tiers do not form a scale. They describe six audiences whose needs differ. A recycler and a repairer see different data.

ValuePassport sections kept before rendering
publicproduct identity, ESPR compliance, REACH compliance, CE marking, recyclability rate, recycled material rate, labels, battery specification
end_userthe whole public tier, plus environmental impact, full circularity, primary material, certified organic cotton statement, durability, energy efficiency, carbon footprint
repairerthe whole end_user tier, plus bill of materials, link to the disassembly instructions, repairability index, battery state of health
recyclerthe whole end_user tier, plus full material composition, substances of concern, link to the disassembly instructions, battery state of health
upstreamthe whole end_user tier, plus full material composition, substances of concern, manufacturing, supply chain
authoritythe entirety of the data, with no filtering

This table describes the filter applied before the conversion to JSON-LD. Several of these sections stay absent from the document returned, because this endpoint does not convert them. The callout further down lists them all.

A brand can tighten or widen these lists for its own products. The values above are the ones that apply when it has changed nothing.

#The full address and the alias without /v1

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

The same endpoint also answers without the /v1 prefix, at https://api.sealtrust.io/passport/{identifier}/vc/preview. Both addresses call the same code. Use the /v1 form for a new integration.

#What this preview does not prove

A verifiable credential is a document that its issuer signs, and that anyone can check afterwards without asking us for anything again. This endpoint shows its shape before signing.

#Request body

None. This request has no body.

#Example request

Public preview of the credential of the item whose printed serial number is EXEMPLE00001.

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

#Example response

HTTP code 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."
}
FieldTypeDescription
@contextstring[]The two vocabularies of the document, in this order: the W3C verifiable credential model, then ours.
typestring[]Always ["VerifiableCredential", "DigitalProductPassport"].
issuerstringThe did:web identifier of the brand that would issue this credential. See below.
vctstringThe identifier of the credential type. Equals https://schema.sealtrust.io/vct/digital-product-passport when the brand has not defined another one.
credentialSubjectobjectThe passport rendered in JSON-LD, filtered at the tier requested. See below.
access_tierstringThe tier you requested.
signedbooleanAlways false on this endpoint.
notestringA fixed text, in English, that recalls that the preview is not signed. Do not hook any code on it.

The response's access_tier field and the X-DPP-Access-Tier header both repeat the tier you requested. The call succeeds at the tier requested or fails with 401 or 403. There is no silent fallback to a lower tier.

The response carries Cache-Control: no-store, max-age=0. No shared cache must therefore keep a response obtained at a professional tier.

#The issuer field

It is the identity of the issuer, in did:web form. It takes two forms depending on what the brand has chosen.

FormWhere the identity document is read
did:web:<host>:brand:<number>https://<host>/brand/<number>/did.json
did:web:<brand's domain>https://<brand's domain>/.well-known/did.json

The first form applies by default, and the brand has nothing to do to get it. The second requires the brand to declare its own domain and to publish its identity document there.

Read the value returned as it is. Do not rebuild it on your side: a brand can move from one form to the other.

#The credentialSubject field

It is the passport rendered in JSON-LD, with the Schema.org vocabulary, the GS1 web vocabulary and our ESPR extensions. It carries its own @context, which is an object, whereas the one at the top level is a list. The two coexist normally.

FieldTypePresenceDescription
@contextobjectalwaysThe three vocabularies used in this document.
@typestringalwaysAlways Product.
identifierstringalways for a minted itemThe hash of the item's unique identifier. It exists for a QR-only item as well as for a chipped item.
gtinstringif filled inThe product's GS1 trade item code.
namestringif filled inThe model declared in the passport. Failing that, the product's name.
brandobjectalwaysThe brand: name, and depending on what it has filled in identifier (its LEI code), url, address, email.
countryOfOriginstringif filled inThe declared country of manufacture.
gs1:productionFacilitystringif filled inThe declared production site.
espr:operatorIdentifierstringif filled inThe identifier of the economic operator in the sense of the ESPR.
espr:batteryPassportIdentifierstringif filled inThe battery passport identifier.
espr:uniqueBatteryIdentifierstringif filled inThe unique battery identifier.
espr:eprelRegistrationstringif filled in and visibleThe EPREL registration number of the energy label.
materialobject[]alwaysThe material composition. Empty list when no material is visible at the tier requested.
additionalPropertyobject[]alwaysThe environmental, circularity, battery and energy efficiency measurements, as name and value pairs. Empty list when none is visible.
maintenanceTechnicalDataUrlstringif filled in and visibleThe link to the disassembly instructions.
espr:complianceobjectif the compliance section is visibleThe compliance declarations kept at the tier requested.

An entry of additionalProperty carries @type equal to PropertyValue, a name in English, a value, and a unitText when the quantity has a unit. The names are the ones of the vocabulary, for example Recyclability (EN 45555) or gs1:recycledContentPercentage. Hook your code on name, on the exact value, with no translation.

#Errors

The body of an error response carries a detail field.

CodeConditionWhat to do
401access_tier=authority is requested without a valid session. detail equals Authority-tier access requires authentication.Log in with an account carrying the market surveillance authority role. A partner API key does not work.
401access_tier equals repairer, recycler or upstream, and the call carries no valid session. detail equals Professional-tier access requires authentication.Present an account session token. An expired token is treated as the absence of a session. Otherwise, request the public or end_user tier.
403The call carries an Origin or Referer header that designates a domain that is not ours. detail equals Forbidden origin.From your server, stop sending a Referer header, or present your session in Authorization: Bearer <token>.
403The call sends neither Origin nor Referer, and carries an access_token cookie. detail equals Origin or Referer header required.From your server, present the session in Authorization: Bearer <token> instead of the cookie.
403access_tier=authority is requested by a logged-in account that does not carry that role. detail equals Authority-tier access is restricted to market surveillance authorities.Request the tier that matches your entitlement.
403access_tier equals repairer, recycler or upstream, and the logged-in account belongs neither to the product's brand nor to the authorities, and does not hold the matching accreditation on that brand. detail equals This tier is restricted to the product's brand, partners holding the matching accreditation, and market-surveillance authorities.Get accredited by the product's brand, then request the tier of your trade.
404No public passport answers to this identifier. Either no item in the catalog matches this identifier, or the item exists and carries no passport published with public visibility, neither directly nor through its model.Do not treat this response as a failure. Check your identifier, and handle the case of an item without a public passport. A passport reserved for the owner or for the brand gives the same response, as does an item destroyed on the chain, replaced or archived.
404The passport found refers to a brand that no longer exists. detail equals Brand not found.Report the case to support. No action on your side corrects this state.
422The value of access_tier is not one of the six accepted values. detail is a list, each entry carrying loc, type and msg.Read loc to find out which parameter is at fault, then correct its value.
429The limit of 60 calls per 60 seconds is reached for your network address, across all the /passport paths. detail equals Rate limit exceeded: 60 requests per 60s.Wait the number of seconds given by Retry-After, then retry. Space out your calls.
500An unexpected error occurred while processing your call. detail equals Internal Server Error. The response carries an X-Request-Id header.Retry. If the error persists, contact support, giving the value of X-Request-Id.

The code carries one last case, 422 with detail equal to Brand has no website_url; cannot derive a did:web issuer. You will not meet it: every registered brand receives an issuer identity, did:web:api.sealtrust.io:brand:<number> when it has not declared its own domain.

#See also

Your answer opens a pre-filled email in your mail app, addressed to contact@sealtrust.io. You read it over before sending it.

Suggest a correctionReport a problem