# GET /01/{gtin}

Résoudre un lien GS1 Digital Link qui ne porte qu'un GTIN, vers la page publique du passeport de référence du modèle. Réponse 302, aucune clef d'API.

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

---

Vous envoyez un GTIN et vous recevez une redirection vers la page publique du
passeport de référence du modèle correspondant. Le GTIN, Global Trade Item
Number, est le numéro d'article commercial imprimé sous le code-barres. En
quittant cette page, vous saurez lire la redirection, choisir la langue de la
page d'arrivée, et reconnaître les réponses d'erreur.

Adresse complète :

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

Le même point d'entrée répond aussi sous le préfixe `/v1`, à
`https://api.sealtrust.io/v1/01/{gtin}`. Les deux adresses appellent le même
code. Un lien GS1 Digital Link porte le chemin `/01/{gtin}` sans préfixe, donc
c'est cette forme que rencontre un lecteur de code.

> [!INFO] Ce point d'entrée désigne un modèle
> Le chemin porte un GTIN et aucun numéro de série. Il nomme donc une référence
> commerciale. Le passeport visé est celui qui est rattaché à un modèle et à
> aucune unité. Un passeport rattaché à un exemplaire n'est jamais servi ici,
> même quand son modèle porte ce GTIN : montrer des données propres à un
> exemplaire pour un autre exemplaire du même modèle serait faux.
>
> Le règlement ESPR autorise un passeport au niveau du modèle, du lot ou de
> l'article. Un passeport de modèle couvre tous les exemplaires qui partagent
> le même code produit.
>
> Pour désigner un exemplaire physique, utilisez le lien qui porte aussi le
> numéro de série, `/01/{gtin}/21/{serial}`.

## Autorisation

Aucune, point d'entrée public. Ce point d'entrée répond sans clef d'API, sans
compte et sans cookie de session.

Une clef d'API partenaire présentée ici n'est pas lue. Elle ne change ni la
réponse, ni les quotas de votre offre.

## Plafond d'appels

Aucun plafond propre à ce point d'entrée. Il relève du compteur général de
l'API, commun à toutes les routes sans plafond dédié et compté par adresse IP
appelante sur une fenêtre de 60 secondes. Ce compteur est aussi unique pour
toutes les valeurs de GTIN : parcourir mille GTIN différents consomme mille
appels du même budget.

Chaque réponse porte trois en-têtes qui décrivent ce compteur.

| En-tête | Contenu |
| --- | --- |
| `X-RateLimit-Limit` | le plafond du compteur sur la fenêtre |
| `X-RateLimit-Remaining` | ce qu'il vous reste dans la fenêtre en cours |
| `X-RateLimit-Reset` | l'heure de remise à zéro, en secondes depuis le 1er janvier 1970 |

`X-RateLimit-Remaining` s'arrête à zéro. Ralentissez avant d'y arriver, et
traitez le code 429 dans votre client dès votre première intégration.

Cet appel n'entame ni le quota quotidien d'une clef d'API, ni le quota mensuel
de produits de votre offre.

> [!ATTENTION] Ne construisez pas sur la valeur du plafond général
> C'est un compteur de repli, commun à toutes les routes qui n'ont pas de
> plafond propre. Sa valeur peut changer sans que ce chemin soit modifié. Lisez
> les en-têtes `X-RateLimit-*` de vos réponses et n'inscrivez aucun nombre en dur
> dans votre code.

## Paramètres de chemin et de requête

| Nom | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `gtin` | `string` | oui | Le GTIN du modèle. Les formats GTIN-8, GTIN-12, GTIN-13 et GTIN-14 sont acceptés, avec ou sans séparateurs. Son dernier chiffre doit être la clef de contrôle des précédents : voir ci-dessous. |

Ce point d'entrée ne lit aucun paramètre de requête. Tout ce que vous ajoutez
après le `?` est ignoré, y compris `linkType`, et n'est pas recopié dans la
redirection. Le paramètre `linkType` n'a d'effet que sur les liens qui désignent
un exemplaire, `/p/{serial}` et `/01/{gtin}/21/{serial}`. Ici la destination est
déjà le passeport.

### Écrire le GTIN

Le serveur ramène votre GTIN à sa forme canonique de quatorze chiffres avant la
recherche. Il retire tous les caractères qui ne sont pas des chiffres, puis il
complète le résultat par des zéros à gauche jusqu'à quatorze chiffres.

Ces trois écritures désignent donc le même modèle : `3701234567891`,
`03701234567891` et `3-701234-567891`. C'est toujours la forme à quatorze
chiffres qui apparaît dans la redirection.

Une valeur qui ne contient aucun chiffre renvoie 400. Une valeur qui en contient
plus de quatorze renvoie 400 également : `0003701234567891` compte seize
chiffres et renvoie 400.

La recherche retrouve le modèle même si la marque a enregistré son GTIN sous une
forme plus courte, en GTIN-8, GTIN-12 ou GTIN-13.

### La clef de contrôle du GTIN

Le dernier chiffre d'un GTIN est sa clef de contrôle : la règle GS1 modulo 10 le
calcule à partir des chiffres qui le précèdent. Le serveur la recalcule et la
compare avant de chercher le modèle.

Envoyez donc 8, 12, 13 ou 14 chiffres, les quatre longueurs qu'un GTIN peut
avoir, et vérifiez que le dernier est bien la clef des précédents. Un GTIN qui
sort de cette règle reçoit un code 400, avec le corps
`{"detail": "Invalid GTIN: the check digit does not match."}`.

Recopiez le GTIN depuis le code-barres de la référence. Une faute de frappe sur
un seul chiffre se voit alors dès l'appel.

### Choisir la langue de la page d'arrivée

La redirection pointe vers une page dont l'adresse commence par la langue. Le
serveur choisit cette langue à partir de l'en-tête `Accept-Language` que vous
envoyez : il retient la première valeur de l'en-tête dont la langue principale
est `fr` ou `en`. Sans en-tête, ou sans valeur correspondante, il choisit `fr`.

Le serveur sert deux langues, `fr` et `en`.

### En-têtes de requête

| En-tête | Obligatoire | Description |
| --- | --- | --- |
| `Accept-Language` | non | Choisit la langue de la page d'arrivée. `fr` par défaut. |

## Corps de la requête

Aucun. Cette requête n'a pas de corps.

## Requête d'exemple

Résolution du GTIN `03701234567891`. La redirection n'est pas suivie, pour
pouvoir lire l'en-tête `Location`.

:::onglets
```bash title="curl"
curl -i "https://api.sealtrust.io/01/03701234567891"
```
```typescript title="TypeScript (fetch)"
const gtin = "03701234567891";

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

console.log(response.status);
console.log(response.headers.get("location"));
```
```python
import requests

gtin = "03701234567891"

response = requests.get(
    f"https://api.sealtrust.io/01/{gtin}",
    allow_redirects=False,
    timeout=30,
)

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

Pour obtenir la page en anglais, ajoutez l'en-tête de langue.

:::onglets
```bash title="curl"
curl -i \
  -H "Accept-Language: en" \
  "https://api.sealtrust.io/01/03701234567891"
```
```typescript title="TypeScript (fetch)"
const gtin = "03701234567891";

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

console.log(response.status);
console.log(response.headers.get("location"));
```
```python
import requests

gtin = "03701234567891"

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

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

> [!INFO] Le SDK TypeScript ne couvre pas ce point d'entrée
> `@sealtrust-io/sdk` n'expose aucune méthode pour cette adresse. Les exemples
> ci-dessus utilisent `fetch`, disponible sans dépendance. L'onglet est donc
> intitulé « TypeScript (fetch) ».

## Réponse d'exemple

Code HTTP `302`. La réponse n'a pas de corps. Toute l'information est dans
l'en-tête `Location`.

```http
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/passport/01/03701234567891
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 599
X-RateLimit-Reset: 1786000020
Content-Length: 0
```

Avec l'en-tête `Accept-Language: en`, la même requête renvoie ceci.

```http
HTTP/1.1 302 Found
Location: https://sealtrust.io/en/passport/01/03701234567891
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 598
X-RateLimit-Reset: 1786000020
Content-Length: 0
```

| En-tête | Contenu |
| --- | --- |
| `Location` | L'adresse complète de la page publique du passeport de référence, au chemin `/{locale}/passport/01/{gtin}`. Le GTIN y figure sous sa forme à quatorze chiffres. |

Lisez l'en-tête `Location` et suivez-le. N'écrivez pas l'hôte de destination en
dur dans votre code : il change selon le domaine sur lequel l'appel arrive, et
c'est la réponse qui fait autorité.

### Une seule redirection

Ce point d'entrée n'émet qu'un seul saut. La langue est déjà résolue dans
l'adresse rendue, donc la page d'arrivée ne vous redirige pas une seconde fois.
Le registre européen des passeports numériques va chercher les adresses
d'identifiant pour les valider et pénalise les chaînes de redirections.

### Sur le domaine personnalisé d'une marque

Quand une marque sert ce point d'entrée sur son propre nom de domaine, vérifié
chez nous, la redirection reste sur ce domaine. Un consommateur qui scanne un
produit ne quitte donc jamais le domaine de la marque.

Sur un tel domaine, seules les références commerciales de cette marque
répondent. Un GTIN qui appartient à une autre marque renvoie 404, avec le même
message que toutes les autres absences.

## Erreurs

Le corps d'une réponse d'erreur contient un seul champ, `detail`.

```json
{
  "detail": "Unknown GS1 Digital Link"
}
```

| Code | Condition | Que faire |
| --- | --- | --- |
| 400 | La valeur envoyée ne contient aucun chiffre, ou en contient plus de quatorze. Message `Invalid GTIN`. | Corrigez la valeur. Un GTIN valide compte au plus quatorze chiffres, séparateurs exclus. |
| 400 | La valeur envoyée ne compte pas 8, 12, 13 ou 14 chiffres, ou son dernier chiffre n'est pas la clef de contrôle des précédents. Message `Invalid GTIN: the check digit does not match.` | Recopiez le GTIN depuis le code-barres de la référence, puis rappelez. |
| 404 | Aucune page publique de passeport de référence ne répond pour ce GTIN sur ce domaine. Message `Unknown GS1 Digital Link`. | Vérifiez le GTIN, puis vérifiez dans la console que le passeport de référence de ce modèle est publié et que sa visibilité est publique. Un passeport rattaché à un exemplaire ne répond jamais ici. |
| 429 | Plus de 60 appels en 60 secondes depuis la même adresse IP, tous chemins `/01/` confondus. Message `Rate limit exceeded: 60 requests per 60s`. La réponse porte un en-tête `Retry-After` en secondes. | Attendez le nombre de secondes indiqué par `Retry-After`, puis réessayez. Suivez votre consommation avec les en-têtes `X-RateLimit-*` et étalez vos appels dans le temps. |
| 500 | Erreur inattendue du serveur. Corps figé `{"detail": "Internal Server Error"}`. | Réessayez. L'en-tête `X-Request-Id` identifie l'appel, transmettez-le nous s'il se répète. |

Ce point d'entrée ne renvoie pas de 422. Une valeur inexploitable ressort en
400, et un GTIN sans page publique ressort en 404.

> [!ATTENTION] Un 404 ne dit pas si le GTIN existe
> Toutes les absences renvoient le même code et le même message. C'est
> délibéré : des messages différents permettraient à un lecteur de code
> automatisé de séparer les GTIN réels des autres. Ne construisez donc aucune
> logique qui déduirait l'existence d'une référence à partir d'un 404.

## Voir aussi

- [`GET /01/{gtin}/21/{serial}`](/reference/get-gs1-gtin-serial/),
  résoudre un lien GS1 qui porte un GTIN et un numéro de série.
- [`GET /passport/01/{gtin}`](/reference/get-passport-gtin/),
  lire le passeport publié d'un modèle, à partir de son GTIN.
- [`GET /p/{serial}`](/reference/get-p-serial/),
  traduire le numéro de série imprimé en adresse de page consommateur.
- [Identification physique, QR et NFC](/identification-physique/),
  choisir le porteur physique et la forme exacte du lien GS1 Digital Link.
