Method GET/p/{serial}

Translate the serial number printed on an item into the address of its consumer page. Public endpoint, no API key, which answers with a redirect.

On this page

You turn an item's serial number into the address of the page that presents it to a consumer, through a redirect.

#Authorization

None, public endpoint. We expect neither an API key, nor a session cookie, nor an Authorization header. You can call this address from a server.

#Rate limit

This address has no limit of its own. It falls under the general API counter, counted per calling IP address over a 60-second window, and shared with all the other addresses that have no limit of their own.

Plan for the 429 code in your client and honor the Retry-After header it carries. The value of this counter may change without notice, so hard-code no number in your code.

The response carries the headers X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, the last one giving the reset time in seconds since January 1, 1970. Do not make your client depend on their presence: treat a response that does not carry them as a normal response, and base your call rate on the values you receive.

This address consumes no quota from your plan.

#Path and query parameters

NameTypeRequiredDescription
serialstringyesThe item's public serial number, 12 characters. Path parameter.
linkTypestringnoAsks for the passport rather than the consumer page. Five values trigger it: dpp, passport, gs1:dpp, gs1:digitalproductpassport, digitalproductpassport. Case and edge spaces do not matter. We treat any other value as if the parameter were absent. We also accept the spelling linktype, all in lowercase.

This serial number is the unique product identifier within the meaning of the EN 18219 standard, the one the European digital product passport registry expects, and the one encoded by the QR code printed on your items. The European registry accepts no registration today, from anyone. We will submit this identifier as soon as its registration opens.

This endpoint addresses a physical unit. A passport does not have to cover a unit: the ESPR regulation provides for three levels, the model, the batch and the item. Today we serve the model level and the item level. For a model passport, the identifier to use is GET /01/{gtin}, which resolves the reference passport shared by all the units that carry the same product code. So you do not have to number every unit in order to publish a passport.

The serial number is written in a 32-character alphabet: the digits 0 through 9 and the letters A through Z, except I, L, O and U. Those four letters are set aside because they get confused with digits on a label.

Before any lookup, we clean up the value received: we strip edge spaces, we replace I and L with 1, O with 0, and we put the whole thing in uppercase. So someone retyping a number by hand can get I, L and O wrong with no consequence. We understand ilo2345678ab as 1102345678AB, and it is that corrected form that appears in the destination address. The letter U is not corrected: a value that contains one goes out as a 404.

After this cleanup, we refuse with a 404 any value that is not exactly 12 characters, or that contains a character outside the alphabet. The authentication parameters that some NFC chips add to the address at scan time are query parameters: we do not read them here and they change nothing in the response.

#Request body

None. This is a GET request: everything goes through the path and the query parameters.

#Example request

Do not follow the redirect. What you want to read is the Location header.

#Two addresses for the same route

For a server call, call https://api.sealtrust.io/v1/p/{serial}. The same endpoint also answers without the /v1 prefix. For a new server integration, use the /v1 form.

The QR code we generate for your items, for its part, carries the form without a prefix, on the domain name of your consumer pages, for example https://sealtrust.io/p/{serial}. That is the form that gets printed and that serves as the identifier, because an identifier printed on a label can no longer be corrected.

curl -i https://api.sealtrust.io/v1/p/000000000000 \
  -H "Accept-Language: fr"

#Example response

HTTP code 302. The body is empty, all the information is in the Location header.

HTTP
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/product/000000000000

With Accept-Language: en-GB,en;q=0.9, the same request returns the English version of the page.

HTTP
HTTP/1.1 302 Found
Location: https://sealtrust.io/en/product/000000000000

With ?linkType=dpp, the destination becomes the item's passport.

HTTP
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/passport/0x0000000000000000000000000000000000000000000000000000000000000000

#How we choose the destination

This endpoint returns no authenticity verdict. We find the item that carries this serial number, then we return the address of the page to display. For a verdict, call GET /qr/verify with the signed parameters of the QR code.

CaseDestination
Item in the catalog, with no recognized linkTypeThe item's consumer page, addressed by its corrected serial number.
Recognized linkTypeThe item's passport, addressed by its hash. If the item has no hash, by its token identifier, and failing that by its serial number.
Item withdrawn from the catalogThe passport, with or without linkType. An item replaced by a more recent mint or archived therefore remains resolvable, which the EN 18219 standard requires for a withdrawn identifier.

The destination's language comes from the Accept-Language header. We take the first declared language that is French or English. With no header, or with a language we do not serve, we answer with a destination in French.

If you serve your consumer pages on your own domain name, we build the destination on that domain name, over https, and the visitor therefore does not leave your domain.

When several records carry the same serial number, because you have re-minted an item, we answer for the record that is still in the catalog. If there is none, we answer for the most recent one.

#Errors

CodeConditionWhat to do
400The call arrives on a host name we do not serve, for example a brand domain whose verification is no longer valid. The response carries no JSON body.Call api.sealtrust.io, or have your domain name verified again in the console.
404The serial number is malformed: length other than 12 after cleanup, or a character outside the alphabet. Message Unknown product identifier.Check the value you copied. Add nothing to the number in the path, every extra parameter goes in the query string.
404No item carries this serial number. Message Unknown product identifier.Nothing to fix in the call. The number was never assigned, or it belongs to another system.
404The call arrives on a brand's domain name and the item belongs to another brand. Message Unknown product identifier.Call this serial number on the domain of the brand it belongs to, or on api.sealtrust.io.
429More than 60 calls in 60 seconds from the same IP address, across every /p/ path. Message Rate limit exceeded: 60 requests per 60s. The response carries the Retry-After header, in seconds.Wait the number of seconds indicated by Retry-After. Spread out your calls instead of sending them in bursts.
500Unexpected error on our side. Fixed body {"detail": "Internal Server Error"}.Try again. The X-Request-Id header identifies the call, pass it on to us if it happens repeatedly.

#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