# Umgebungen und Basis-URL

> Wo die API Ihrer Organisation liegt, welche Adressen sie bedient und wie Sie gefahrlos testen.

## Basis-URL

BatteryPass läuft je Instanz; einen gemeinsamen, globalen API-Host gibt es nicht. Ihre Basis-URL ist die
BatteryPass-Adresse Ihrer Organisation, also dieselbe Adresse, unter der Sie das Portal nutzen, zum Beispiel
`https://batterypass.example.com`. Die API liegt unter `/api/v1` auf dieser Adresse.

## Adressen

| Pfad auf Ihrer BatteryPass-Adresse             | Was                                                                   | Authentifizierung |
| ---------------------------------------------- | --------------------------------------------------------------------- | ----------------- |
| `/api/v1/...`                                  | Die Integrations-API                                                  | API-Schlüssel     |
| `/api/v1/public/...`                           | Öffentliche Abrufe von Pässen                                         | Keine             |
| `/api/v1/openapi.json`, `/api/v1/openapi.yaml` | Der veröffentlichte Vertrag                                           | Keine             |
| `/01/{gtin}/21/{serial}`                       | GS1-Digital-Link-Resolver, das Ziel der QR-Codes                      | Keine             |
| `/pass/{passportId}`                           | Öffentliche Passseite für Browser                                     | Keine             |
| `/.well-known/batterypass/keys.json`           | Öffentliche Signaturschlüssel (JWK-Set) zum Prüfen von Passsignaturen | Keine             |
| `/docs/`                                       | Diese Dokumentation                                                   | Keine             |

> [!NOTE]
> Eine Instanz kann einen eigenen Resolver-Host in ihre QR-Codes drucken. Übernehmen Sie den Digital Link einer
> Einheit aus dem Feld `gs1_digital_link` von
> [`getPassport`](https://passport.kabin.sh/docs/de/api-reference/passports/get-passport), statt ihn selbst zusammenzusetzen. Siehe
> [GS1 Digital Link](https://passport.kabin.sh/docs/de/concepts/digital-link).

## Konventionen

- **HTTPS.** Senden Sie Anfragen und vor allem Schlüssel nur über HTTPS.
- **JSON.** Request- und Response-Bodys sind UTF-8-JSON; senden Sie zu einem Body
  `Content-Type: application/json`. Bodys sind standardmäßig auf 1 MiB begrenzt (`413 payload_too_large`),
  unbekannte Eigenschaften werden abgelehnt.
- **Zeitpunkte** (`date-time`) sind UTC nach RFC 3339, z. B. `2026-10-24T02:00:00Z`. Senden Sie Zeitpunkte
  mit Zeitzonenversatz; UTC ist die sicherste Wahl.
- **Datumsangaben** (`date`, z. B. `occurred_on`, `manufacturing_date`) haben die Form `YYYY-MM-DD` ohne
  Zeitzone.
- **IDs** sind UUID-Strings. Die dauerhafte Passkennung ist `urn:dpp:{uuid}`; öffentliche Routen erwarten nur
  die UUID.

## Client einrichten

Alle Beispiele lesen zwei Umgebungsvariablen:

| Variable              | Wert                                                                                               |
| --------------------- | -------------------------------------------------------------------------------------------------- |
| `BATTERYPASS_URL`     | Ihre BatteryPass-Adresse ohne abschließenden Schrägstrich, z. B. `https://batterypass.example.com` |
| `BATTERYPASS_API_KEY` | Ein API-Schlüssel Ihrer Organisation, `bp_live_...`                                                |

```bash title="Shell"
export BATTERYPASS_URL="https://batterypass.example.com"
export BATTERYPASS_API_KEY="bp_live_..."
```

```ts title="TypeScript"
const url = process.env.BATTERYPASS_URL?.replace(/\/+$/, '');
const key = process.env.BATTERYPASS_API_KEY;
if (!url || !key) throw new Error('BATTERYPASS_URL und BATTERYPASS_API_KEY setzen.');
if (!url.startsWith('https://')) console.warn('BATTERYPASS_URL sollte HTTPS verwenden.');

export const api = `${url}/api/v1`;
export const headers = { Authorization: `Bearer ${key}` };
```

```python title="Python"
import os

url = os.environ.get("BATTERYPASS_URL", "").rstrip("/")
key = os.environ.get("BATTERYPASS_API_KEY", "")
if not url or not key:
    raise SystemExit("BATTERYPASS_URL und BATTERYPASS_API_KEY setzen.")
if not url.startswith("https://"):
    print("BATTERYPASS_URL sollte HTTPS verwenden.")

api = f"{url}/api/v1"
headers = {"Authorization": f"Bearer {key}"}
```

```go title="Go"
package main

import (
	"fmt"
	"log"
	"os"
	"strings"
)

func main() {
	url := strings.TrimRight(os.Getenv("BATTERYPASS_URL"), "/")
	key := os.Getenv("BATTERYPASS_API_KEY")
	if url == "" || key == "" {
		log.Fatal("BATTERYPASS_URL und BATTERYPASS_API_KEY setzen.")
	}
	if !strings.HasPrefix(url, "https://") {
		log.Print("BATTERYPASS_URL sollte HTTPS verwenden.")
	}
	api := url + "/api/v1"
	fmt.Println("API-Basis:", api)
}
```

Bewahren Sie den Schlüssel in einem Secret-Speicher oder der Secret-Verwaltung Ihrer Plattform auf, nicht im
Quellcode oder in Dateien, die Sie committen. Siehe
[Sichere Schlüsselverwaltung](https://passport.kabin.sh/docs/de/guides/secure-key-handling).

## Testen

BatteryPass hat keine öffentliche Sandbox. Testen Sie in einer Umgebung, in der Fehler keinen Schaden
anrichten:

- **Eine eigene Testorganisation** oder eine eigene BatteryPass-Instanz mit eigenen Schlüsseln. Daten sind
  immer nach Organisation getrennt; ein Testschlüssel sieht oder ändert also nie Produktionsdaten. Bitten Sie
  die Betreiber Ihrer BatteryPass-Instanz, sie einzurichten.
- **Schreibzugriffe nicht gegen die Produktion testen.** Eine Zustandsmeldung per Schlüssel kann einen
  öffentlichen Pass je nach Einstellung der Organisation sofort neu veröffentlichen, und
  Lebenszyklusereignisse lassen sich über die API nicht löschen.
- **Auf Öffentliches achten.** Pässe, die in einer Testorganisation veröffentlicht werden, sind ebenfalls
  öffentlich, unter denselben Adressen. Verwenden Sie für Testdaten keine GTINs echter Produkte und drucken
  oder verteilen Sie keine QR-Codes aus Tests.
- **Konfiguration trennen.** Halten Sie Test- und Produktionswerte von `BATTERYPASS_URL` und
  `BATTERYPASS_API_KEY` auseinander und geben Sie Testschlüsseln nur die Scopes, die der Test braucht.
