# GET /01/{gtin}/10/{lot}

Resolve the GS1 Digital Link of a production batch to the public page of that batch's passport. 302 response, no API key.

Source: https://docs.sealtrust.io/en/reference/get-gs1-gtin-lot/

---

You send the GTIN of a model and the number of one of its production batches,
and you receive a redirect to the public page of that batch's passport. It is
the address of a batch, the one that batch QR codes already printed carry. When you leave this page, you will
know how to write that link, how to read the redirect, and what the server does
when the batch has no passport yet.

Full address:

```http
GET https://api.sealtrust.io/01/{gtin}/10/{lot}
```

> [!INFO] This link names a batch
> `10` is the GS1 application identifier of the lot number. The link therefore
> names one production batch of a commercial reference, neither one item nor
> the whole reference. The passport it targets is the batch's: it is shared by
> every item of the batch and attached to the model through the batch.
>
> When the batch has no published passport, the link resolves to the model's
> passport, exactly like [`GET /01/{gtin}`](/en/reference/get-gs1-gtin/). A
> label printed before the batch passport was published therefore keeps
> answering, with the most precise passport that exists.

## Authorization

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

## Rate limit

This endpoint shares the limit of the `/01/` family: 60 calls per 60 seconds,
counted per calling IP address, all `/01/` paths together. Every response
carries the `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`
headers. Beyond that, the response is a 429 with `Retry-After`.

## Path and query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `gtin` | `string` | yes | The GTIN of the batch's model. Same rules as for `/01/{gtin}`: form brought to fourteen digits, check digit verified. |
| `lot` | `string` | yes | The number of the batch, as it is recorded on the batch in the console. |

The lot number is compared **exactly**, case included: `LOT-26A` and `lot-26a`
are two different batches, as GS1 provides. It is at most twenty characters,
taken from the GS1 character set: ASCII letters, digits and
`! " & ' ( ) * + , - . : ; < = > ? _`. Encode in the address the characters
that need it, for example `%3F` for `?`. The slash and the `%` sign, allowed
by GS1, are not accepted here: a path cannot carry the first, and the second
can no longer be told apart from an encoded character once the page has read
the address. The console refuses to create the passport of such a batch.

This endpoint reads no query parameter.

The language of the landing page is chosen as for `/01/{gtin}`: your
`Accept-Language` header first, then the brand's language on its own domain,
otherwise `en`. The response carries `Vary: Accept-Language`.

## Request body

None. This request has no body.

## Example request

Resolution of batch `LOT-26A` of GTIN `03701234567891`. The redirect is not
followed, so that the `Location` header can be read.

:::onglets
```bash title="curl"
curl -i -H "Accept-Language: fr" "https://api.sealtrust.io/01/03701234567891/10/LOT-26A"
```
```typescript title="TypeScript (fetch)"
const gtin = "03701234567891";
const lot = "LOT-26A";

const response = await fetch(
  `https://api.sealtrust.io/01/${gtin}/10/${encodeURIComponent(lot)}`,
  { method: "GET", redirect: "manual", headers: { "Accept-Language": "fr" } },
);

console.log(response.status);
console.log(response.headers.get("location"));
```
```python
from urllib.parse import quote

import requests

gtin = "03701234567891"
lot = "LOT-26A"

response = requests.get(
    f"https://api.sealtrust.io/01/{gtin}/10/{quote(lot, safe='')}",
    headers={"Accept-Language": "fr"},
    allow_redirects=False,
    timeout=30,
)

print(response.status_code)
print(response.headers["Location"])
```
:::

> [!INFO] The TypeScript SDK does not cover this endpoint
> `@sealtrust-io/sdk` exposes no method for this address. The examples above
> use `fetch`, available without any dependency.

## Example response

HTTP code `302`, when the batch has a published passport. The response has no
body.

```http
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/passport/01/03701234567891/10/LOT-26A
Vary: Accept-Language
Content-Length: 0
```

When the batch has no published passport, the same request resolves to the
model's passport.

```http
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/passport/01/03701234567891
Vary: Accept-Language
Content-Length: 0
```

| Header | Content |
| --- | --- |
| `Location` | The public page of the batch's passport, at the path `/{locale}/passport/01/{gtin}/10/{lot}`, or the one of the model's passport, at the path `/{locale}/passport/01/{gtin}`. The GTIN appears in its fourteen digit form, the lot number encoded for an address. |

Read the `Location` header and follow it. This endpoint emits a single hop, the
language being already resolved.

### Where the brand comes from

The server finds the batch from the data alone: the models that carry this
GTIN, then, among their batches, the one that carries this number. It never
uses the request's host to choose a brand. On a brand's verified domain name,
the redirect stays on that domain, and a batch belonging to another brand
answers 404.

If the same GTIN and the same lot number publish a passport in several brands,
the server does not choose: it resolves to the model level, which applies the
same rule. The console refuses to publish a batch passport that would create
that situation.

A GTIN belongs to one brand. If the batch belongs to a brand other than the one
that publishes the model passport of this GTIN, it does not answer under that
code: the redirect leads to the model passport, the one of the brand that
publishes the GTIN. The console also refuses to publish such a batch passport.

### 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](/en/api-affichage-partenaire/). 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 `lot`),
`gtin` and `lot` 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`.

| Code | Condition | What to do |
| --- | --- | --- |
| 400 | The GTIN contains no digit, or more than fourteen. Message `Invalid GTIN`. | Correct the value. |
| 400 | The GTIN check digit does not match. Message `Invalid GTIN: the check digit does not match.` | Copy the GTIN again from the barcode, then call again. |
| 404 | Neither this batch nor its model has a published passport that answers on this domain. Message `Unknown GS1 Digital Link`. | Check the GTIN and the lot number, case included, then check in the console that the passport of the batch or of the model is published. |
| 429 | More than 60 calls in 60 seconds from the same IP address, all `/01/` paths together. | Wait the number of seconds given by `Retry-After`. |

> [!ATTENTION] A 404 does not say whether the batch exists
> Every absence returns the same code and the same message, so that an automated
> reader cannot separate real batches from the others.

## See also

- [`GET /passport/01/{gtin}/10/{lot}`](/en/reference/get-passport-gtin-lot/),
  read the published passport of a batch.
- [`GET /01/{gtin}`](/en/reference/get-gs1-gtin/),
  resolve the link of a model.
- [Physical identification, QR and NFC](/en/identification-physique/),
  choose the physical carrier and the exact form of the link.
