# GS1 Digital Link und Resolver

> Der Link in jedem QR-Code und wie der Resolver Browser zur öffentlichen Seite und Maschinen zum öffentlichen JSON leitet.

Jeder Pass hat eine Webadresse, die die Batterie kennzeichnet: einen GS1 Digital Link. Genau diesen Link trägt
der QR-Code auf der Batterie. Dieselbe Adresse bedient Menschen und Maschinen: Der Resolver dahinter entscheidet
anhand der Anfrage, was er zurückgibt.

## Der Link

```text
https://batterypass.example.com/01/04012345000023/21/SV2027-000184
```

| Teil                              | Bedeutung                                                                                                                   |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `https://batterypass.example.com` | Der Ursprung des Resolvers: Ihre BatteryPass-Adresse oder ein eigener Resolver-Hostname, den Ihr Betreiber eingerichtet hat |
| `/01/04012345000023`              | GS1-Datenbezeichner `01`: die GTIN des Modells, immer 14-stellig                                                            |
| `/21/SV2027-000184`               | GS1-Datenbezeichner `21`: die Seriennummer der Einheit; ein `/` in der Seriennummer wird prozentkodiert (`%2F`) übertragen  |

Der Link steht in `gs1_digital_link` von [`getPassport`](https://passport.kabin.sh/docs/de/api-reference/passports/get-passport) und ist
fest, sobald die Kennungen gesperrt sind. [`getPassportQr`](https://passport.kabin.sh/docs/de/api-reference/passports/get-passport-qr)
erzeugt aus genau diesem Link ein PNG oder SVG (Fehlerkorrekturstufe M, Ruhezone von vier Modulen). Übernehmen
Sie den Link immer aus der API, statt ihn selbst zusammenzusetzen.

## Was der Resolver liefert

Der Resolver liegt an der Wurzel des Ursprungs (`/01/…/21/…`), nicht unter `/api/v1`, und braucht keinen
Schlüssel.

| Anfrage                                                                                                                | Antwort                                                                       |
| ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| Ein Browser (`Accept: text/html` oder ohne Vorliebe für JSON)                                                          | `307` zur öffentlichen Passseite `/pass/{passportId}`                         |
| `?linkType=describedby` (oder `gs1:describedby`)                                                                       | `307` zum öffentlichen JSON `/api/v1/public/passports/{passportId}`           |
| `?linkType=all` oder `Accept: application/json`, `application/linkset+json` bzw. `application/ld+json` ohne `linkType` | `200` mit einem Linkset (`application/linkset+json`)                          |
| Unbekannte GTIN und Seriennummer                                                                                       | `404`: eine kurze Seite für Browser, ein Problem `not_found` für JSON-Clients |
| Zu viele Anfragen von einer Adresse                                                                                    | `429 rate_limited` mit `Retry-After`                                          |

Jede Antwort zu einem bekannten Pass trägt die Links zusätzlich im Header `Link`, mit den Relationen
`https://gs1.org/voc/pip` (die Seite), `describedby` (das öffentliche JSON) und `linkset`. Antworten dürfen fünf
Minuten zwischengespeichert werden und unterscheiden sich nach `Accept`.

Ein Pass, dessen Kennungen gesperrt, der aber noch nicht veröffentlicht ist, oder einer, der zurückgezogen wurde,
wird trotzdem aufgelöst: Seine Seite erklärt den Zustand, und das öffentliche JSON liefert den Status ohne Inhalt.

## Den Link aus Code verfolgen

```bash title="cURL"
# Das öffentliche JSON des Passes hinter einem QR-Code
curl -sL "https://batterypass.example.com/01/04012345000023/21/SV2027-000184?linkType=describedby"

# Das Linkset
curl -s -H "Accept: application/linkset+json" \
  "https://batterypass.example.com/01/04012345000023/21/SV2027-000184"
```

Das Linkset nennt die Seite und das öffentliche JSON:

```json title="Linkset"
{
  "linkset": [
    {
      "anchor": "https://batterypass.example.com/01/04012345000023/21/SV2027-000184",
      "https://gs1.org/voc/pip": [
        { "href": "https://batterypass.example.com/pass/0192f0c4-7b1e-7c3a-9d2e-5a8b6c4d3e21", "type": "text/html", "title": "Battery passport" }
      ],
      "describedby": [
        { "href": "https://batterypass.example.com/api/v1/public/passports/0192f0c4-7b1e-7c3a-9d2e-5a8b6c4d3e21", "type": "application/json", "title": "Public passport (JSON)" }
      ]
    }
  ]
}
```

Kennen Sie GTIN und Seriennummer bereits, können Sie den Resolver überspringen und
[`getPublicPassportByProductId`](https://passport.kabin.sh/docs/de/api-reference/public/get-public-passport-by-product-id) mit
`{gtin}:{serial}` aufrufen, zum Beispiel `04012345000023:SV2027-000184`. Die GTIN darf dort 8, 12, 13 oder 14
Stellen haben.

> [!NOTE]
> Resolver, öffentliche Passabfragen und öffentliche Dokumente teilen sich ein Limit von 300 Anfragen pro Minute und
> Client-Adresse. Eine Scanner-App, die viele Codes auflöst, sollte die Cache-Header beachten; öffentliche
> Passabfragen dürfen fünf Minuten zwischengespeichert werden.

## Verwandte Seiten

[**Digital Link auflösen**](https://passport.kabin.sh/docs/de/guides/resolve-digital-link): Aus einem gescannten Code die öffentlichen Passdaten gewinnen.

[**QR-Etiketten für eine Charge**](https://passport.kabin.sh/docs/de/recipes/qr-labels-for-a-batch): Die QR-Codes für die Einheiten einer Charge abrufen.
