Method GET/01/{gtin}

Resolve a GS1 Digital Link that carries only a GTIN, to the public page of the model's reference passport. 302 response, no API key.

On this page

You send a GTIN and you receive a redirect to the public page of the reference passport of the matching model. The GTIN, Global Trade Item Number, is the trade item number printed under the barcode. By the time you leave this page, you will know how to read the redirect, choose the language of the landing page, and recognize the error responses.

Full URL:

HTTP
GET https://api.sealtrust.io/01/{gtin}

The same endpoint also answers under the /v1 prefix, at https://api.sealtrust.io/v1/01/{gtin}. Both URLs call the same code. A GS1 Digital Link carries the path /01/{gtin} without a prefix, so that is the form a code reader encounters.

#Authorization

None, public endpoint. This endpoint answers without an API key, without an account and without a session cookie.

A partner API key presented here is not read. It changes neither the response nor the quotas of your plan.

#Rate limit

This endpoint has a dedicated and enforced cap of 60 calls per 60 seconds, counted per calling IP address. The counter covers all /01/ paths together, and it is a single one for every GTIN value: walking through a thousand different GTINs consumes a thousand calls from the same budget.

Every response carries three headers that describe this counter.

HeaderContent
X-RateLimit-Limitthe ceiling of the counter over the window
X-RateLimit-Remainingwhat is left to you in the current window
X-RateLimit-Resetthe reset time, in seconds since January 1, 1970

X-RateLimit-Remaining stops at zero. Slow down before reaching it, and handle the 429 code in your client from your very first integration.

This call does not touch the daily quota of an API key, and counts no piece.

#Path and query parameters

NameTypeRequiredDescription
gtinstringyesThe GTIN of the model. The GTIN-8, GTIN-12, GTIN-13 and GTIN-14 formats are accepted, with or without separators. Its last digit must be the check digit of the preceding ones: see below.

This endpoint reads no query parameter. Everything you add after the ? is ignored, including linkType, and is not carried over into the redirect. The linkType parameter has an effect only on the links that designate a single item, /p/{serial} and /01/{gtin}/21/{serial}. Here the destination is already the passport.

#Writing the GTIN

The server brings your GTIN back to its canonical form of fourteen digits before the lookup. It removes every character that is not a digit, then it pads the result with zeros on the left up to fourteen digits.

These three spellings therefore designate the same model: 3701234567891, 03701234567891 and 3-701234-567891. It is always the fourteen digit form that appears in the redirect.

A value that contains no digit returns 400. A value that contains more than fourteen of them returns 400 as well: 0003701234567891 counts sixteen digits and returns 400.

The lookup finds the model even if the brand recorded its GTIN in a shorter form, in GTIN-8, GTIN-12 or GTIN-13.

#The check digit of the GTIN

The last digit of a GTIN is its check digit: the GS1 modulo 10 rule computes it from the digits that precede it. The server recomputes it and compares it before looking for the model.

So send 8, 12, 13 or 14 digits, the four lengths a GTIN can have, and check that the last one really is the check digit of the preceding ones. A GTIN that falls outside this rule gets a 400 code, with the body {"detail": "Invalid GTIN: the check digit does not match."}.

Copy the GTIN from the barcode of the reference. A typing mistake on a single digit then shows up as soon as you call.

#Choosing the language of the landing page

The redirect points to a page whose URL starts with the language. The server picks that language from the Accept-Language header you send: it keeps the first value of the header whose main language is fr or en, and it skips a language you refuse with q=0.

With no header, or with no matching value, it looks at the domain called: on a brand's verified domain name it picks the language that brand kept in its console; on ours, or if it kept none, it picks en. A language you ask for always comes before the brand's.

The server serves two languages, fr and en. The response carries Vary: Accept-Language, since its destination depends on that header.

#Request headers

HeaderRequiredDescription
Accept-LanguagenoPicks the language of the landing page. Without this header, the brand's language on its own domain, otherwise en.

#Request body

None. This request has no body.

#Example request

Resolution of the GTIN 03701234567891. The redirect is not followed, so that the Location header can be read.

curl -i "https://api.sealtrust.io/01/03701234567891"

To get the page in English, add the language header.

curl -i \
  -H "Accept-Language: en" \
  "https://api.sealtrust.io/01/03701234567891"

#Example response

HTTP code 302. The response has no body. All the information is in the Location header.

HTTP
HTTP/1.1 302 Found
Location: https://sealtrust.io/en/passport/01/03701234567891
Vary: Accept-Language
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1786000020
Content-Length: 0

With the Accept-Language: en header, the same request returns this.

HTTP
HTTP/1.1 302 Found
Location: https://sealtrust.io/en/passport/01/03701234567891
Vary: Accept-Language
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1786000020
Content-Length: 0
HeaderContent
LocationThe full URL of the public page of the reference passport, at the path /{locale}/passport/01/{gtin}. The GTIN appears there in its fourteen digit form.

Read the Location header and follow it. Do not hard-code the destination host in your code: it changes with the domain the call arrives on, and it is the response that is authoritative.

#A single redirect

This endpoint emits one hop only. The language is already resolved in the URL returned, so the landing page does not redirect you a second time.

The European registry of digital passports fetches identifier URLs in order to validate them, and it accepts no more than three redirects. The Commission's help desk gave that figure on August 31, 2026. It also states that no maximum response size is published, but that a passport URL should avoid large responses and resolve efficiently, and that URLs resolving to a local endpoint, localhost or 127.0.0.1, are rejected.

One hop therefore leaves two of margin for your own infrastructure, for example one redirect from http to https and one from www to the bare domain.

#On a brand's custom domain

When a brand serves this endpoint on its own domain name, verified with us, the redirect stays on that domain. A consumer who scans a product therefore never leaves the brand's domain.

On such a domain, only the trade references of that brand answer. A GTIN that belongs to another brand returns 404, with the same message as every other absence.

On a reseller's shared domain, the trade references of the reseller and of its client brands answer, and only those. The brand is the one that publishes the reference passport of this GTIN, read from our database, never from the domain name.

#The scan is counted, keeping nothing of the reader

Every GET call made by a browser that leads to a passport adds one to that passport's number of scans for the current month. Not counted: robots and link previews, HEAD requests, and a link that leads nowhere. No address, no country and no time are kept: only the number of scans per passport and per month exists. The brand reads it by model and by lot. The current month is completed every ten minutes.

#When the brand shows its passports at a partner's

A brand, or its reseller, can show its passports in a partner's page, see Show the passport in your page. When it has switched this on in the console, this address answers 302 to the partner's page instead of ours, with the parameters level (which is model), gtin and lang. A request that carries ?linkType=dpp still gets our passport.

#Errors

A browser, which asks for text/html in its Accept header, receives a short page in its language instead of JSON: same status, and the same text for every error, so it reveals nothing more than the JSON does. A program that asks for JSON, or sends no Accept header, receives the bodies described below.

The body of an error response contains a single field, detail.

JSON
{
  "detail": "Unknown GS1 Digital Link"
}
CodeConditionWhat to do
400The value sent contains no digit, or contains more than fourteen of them. Message Invalid GTIN.Fix the value. A valid GTIN counts at most fourteen digits, separators excluded.
400The value sent does not count 8, 12, 13 or 14 digits, or its last digit is not the check digit of the preceding ones. Message Invalid GTIN: the check digit does not match.Copy the GTIN from the barcode of the reference, then call again.
404No public reference passport page answers for this GTIN on this domain. Message Unknown GS1 Digital Link.Check the GTIN, then check in the console that the reference passport of this model is published and that its visibility is public. A passport attached to a single item never answers here.
429More than 60 calls in 60 seconds from the same IP address, across every /01/ path. Message Rate limit exceeded: 60 requests per 60s. The response carries a Retry-After header in seconds.Wait the number of seconds given by Retry-After, then try again. Follow your consumption with the X-RateLimit-* headers and spread your calls out over time.
500Unexpected server error. Fixed body {"detail": "Internal Server Error"}.Try again. The X-Request-Id header identifies the call, pass it on to us if it repeats.

This endpoint does not return a 422. An unusable value comes out as a 400, and a GTIN with no public page comes out as a 404.

#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