# Leitfaden zu Integrations-Updates

Jede unten aufgeführte Änderung ist strikt additiv: Bestehende Endpunkte, Antwortfelder, HTTP-Statuscodes, Webhook-Payload-Bytes und der bisherige `Signature`-Header bleiben unverändert. Integrationen, die nichts unternehmen, funktionieren exakt wie zuvor weiter. Übernehmen Sie jede Funktion unabhängig und in beliebiger Reihenfolge.

Live bereitgestellt unter https://api.superlabel.ca/api/documentation/integration-updates?lang=de (`?download=1` zum Speichern). Begleitdokumente: OpenAPI (https://api.superlabel.ca/api/documentation?lang=de), Postman-Sammlung (https://api.superlabel.ca/api/documentation/postman-collection), Status-Wörterbuch & Ablauf (https://api.superlabel.ca/api/documentation/order-status-flow?lang=de).

---

## 1. Stornierung per Sendungsnummer (idempotent)

`POST https://api.superlabel.ca/api/v1/orders/cancel` — geben Sie genau einen der Werte `order_id`, `tracking_number`, `external_tracking_number` an.

```json
POST /api/v1/orders/cancel
Authorization: Bearer <token>
{ "external_tracking_number": "WP1234567890" }
```

- Erfolg: `200 {"result":true,"id":123456,"already_cancelled":false,...}`
- Bereits storniert (sichere Wiederholung): `200` mit `"already_cancelled": true`
- Nummer passt auf mehrere aktive Aufträge: `409` mit `"matched_order_ids": [...]` — wiederholen Sie die Anfrage mit `order_id`.
- Der bisherige Endpunkt `GET /v1/orders/{orderId}/cancel` bleibt unverändert.

## 2. Inkrementelle Abgleich-Feeds

Erfassen Sie alles, was sich innerhalb eines Zeitfensters geändert hat; dank Cursor-Paginierung wird kein Datensatz übersehen oder doppelt gezählt.

- `GET https://api.superlabel.ca/api/v1/orders-reconciliation?updated_from=&updated_to=&per_page=&cursor=`
- `GET https://api.superlabel.ca/api/v1/tracking-events/reconciliation?...`

`updated_from` / `updated_to` akzeptieren Unix-Zeitstempel oder `Y-m-d H:i:s`-Zeichenketten in der Plattform-Zeitzone. Folgen Sie `next_cursor`, bis `has_more` false ist; vergleichen Sie mit den `*_timestamp`-Unix-Feldern, niemals mit Ortszeit-Zeichenketten. Tracking-Ereignis-Einträge enthalten `occurred_at` / `occurred_timestamp` (fachlicher Ereigniszeitpunkt; entspricht bei historischen Zeilen dem Erstellungszeitpunkt).

## 3. Maschinenlesbare Fehlercodes & Anfrage-Tracing

Häufige Fehlerantworten beim Erstellen/Stornieren tragen nun ein stabiles `code`-Feld neben der unveränderten `message`:
`VALIDATION_FAILED`, `MISSING_IDENTIFIER`, `ORDER_NOT_FOUND`,
`ORDER_CANCEL_UNAUTHORIZED`, `ORDER_STATUS_NOT_CANCELLABLE`,
`ORDER_CANCEL_BLOCKED_THIRD_PARTY`, `LABEL_CANCEL_FAILED`,
`DUPLICATE_TRACKING_NUMBER`, `MULTIPLE_ORDERS_MATCHED`.
Die Codes sind stabile Bezeichner — neue können hinzukommen, bestehende ändern niemals ihre Bedeutung. Jede API-Antwort gibt zudem `X-Request-ID` zurück; geben Sie diese bei der Meldung eines Problems an.

## 4. Verbesserungen der Duplikaterkennung

Mit `auto_deduplication=1` enthalten die Einträge `exist_package_ref` / `exist_external_tracking_number` einer blockierten Erstellung nun auch die bestehende `order_id` und `order_ref`, und der Umschlag trägt `"duplicate": true`. Optionaler strikter Modus: Senden Sie `strict_duplicate_check=1`, um HTTP `409` anstelle des bisherigen `200` + `result:false` zu erhalten (lassen Sie das Flag weg, um das bisherige Verhalten beizubehalten).

## 5. Optionen für die Stapelerstellung

- `per_order_transaction: 1` (auf oberster Ebene des Stapel-Bodys): Jeder Auftrag wird unabhängig festgeschrieben — ein Fehlschlag macht die übrigen Aufträge nicht mehr rückgängig. Bricht die Verarbeitung vorzeitig ab, erhalten Sie dennoch Zeilen für alles Abgeschlossene sowie eine abschließende Zeile `{"result":false,"batch_aborted":true}`.
- Stapel mit mehr als 100 Aufträgen erhalten einen beratenden Antwort-Header `X-Batch-Size-Warning`; bevorzugen Sie bei großen Mengen `POST /v1/client/batchOrderCreateAsync`.

## 6. Synchronisierung von Zustellnachweis-Dateien

Die `proofs[]`-Einträge in Tracking-Antworten enthalten nun zusätzlich:

```json
{ "url": "...", "full_url": "...", "type": 2,
  "file_id": 234567, "uploaded_at": "2026-07-20 14:30:05",
  "uploaded_timestamp": 1784745005,
  "signed_url": "https://.../files/pod/234567?expires=...&signature=...",
  "signed_url_expires_at": 1784745005 }
```

Verwenden Sie `file_id` als Schlüssel für Deduplizierung und inkrementelle Synchronisierung. `signed_url` ist ein ablaufender Link (7 Tage) — fragen Sie nach Ablauf das Tracking erneut ab, um einen neuen zu erhalten. Die permanenten Links `url` / `full_url` bleiben unverändert.

## 7. Webhooks: v2-Signatur-Header (alle Zustellungen)

Jeder Webhook sendet nun ZUSÄTZLICH, neben dem unveränderten bisherigen `Signature`-Header:

| Header | Bedeutung |
|---|---|
| `X-Webhook-Event-Id` | UUID, über Wiederholungen hinweg stabil — zur Deduplizierung verwenden |
| `X-Webhook-Timestamp` | Unix-Sekunden zum Zeitpunkt der ersten Zustellung |
| `X-Webhook-Signature-V2` | HMAC-SHA256 von `"<timestamp>.<raw body>"` |

Verifizierung (in jeder Sprache): `expected = HMAC_SHA256(timestamp + "." + raw_body, your_secret)`; vergleichen Sie in konstanter Zeit mit dem Header. Der Zeitstempel wird bei der ersten Zustellung festgelegt und bei Wiederholungen wiederverwendet (Wiederholungen können bis zu ~3 Stunden laufen); kombinieren Sie daher ein großzügiges Toleranzfenster mit einer Deduplizierung über `X-Webhook-Event-Id` statt einer engen Replay-Grenze. Ihre bestehende Verifizierung des bisherigen `Signature`-Headers funktioniert unverändert weiter — stellen Sie auf v2 um, wann immer Sie möchten. Testen Sie beide Signaturen gegen Ihren Endpunkt über die Webhook-Leitfaden-Seite (`/webhooks-guide`).

## 8. Webhooks: optionaler Payload-Umschlag

Setzen Sie `webhook_payload_envelope = 1` in Ihren Webhook-Einstellungen, um im JSON-Body objektförmiger Ereignisse Folgendes zu erhalten: `event_id`, `event_time` (ISO8601 mit Offset), `event_timestamp` (Unix) sowie — wo zutreffend — `is_correction: true` (ein zuvor zugestellter/übergebener Auftrag ist erneut in den Ablauf eingetreten) und `occurred_at` / `occurred_timestamp` auf Tracking-Ereignissen. Ohne das Flag bleibt Ihre Nutzlast byteidentisch zu vorher. Listenförmige Nutzlasten (`order.create_async`) werden niemals verändert.

## 9. Neue Webhook-Ereignisse (Opt-in-URLs)

- `pod.files_updated` — ein Zustellfoto bzw. eine Unterschrift wurde nachträglich hinzugefügt oder entfernt. Konfigurieren Sie `pod_files_webhook_url`. Nutzlast:
  `{"action":"added|removed","order_id":...,"order_ref":...,
  "tracking_number":[...],"external_tracking_number":[...],
  "file":{"file_id":...,"type":1|2,"note":null}, "event_id":..., ...}`
- `order.deleted` — ein Auftrag wurde endgültig gelöscht. Konfigurieren Sie `order_deleted_webhook_url`. Nutzlast: `{"action":"deleted","order_id":...,
  "order_ref":...,"tracking_number":[...],"external_tracking_number":[...],
  "event_id":..., ...}`

Beide Ereignisse enthalten stets die Umschlagfelder und werden nur gesendet, wenn ihre URL konfiguriert ist.

## 10. Webhooks: Zustelloptionen

- **Mehrere Endpunkte pro Ereignis**: Jede Webhook-URL-Einstellung akzeptiert eine einzelne URL (wie bisher), eine kommagetrennte Liste oder ein JSON-Array. Jeder Endpunkt erhält seinen eigenen Zustell- und Wiederholungszyklus.
- **TLS-Verifizierung**: Setzen Sie `webhook_verify_ssl = 1`, damit ausgehende Aufrufe Ihr Zertifikat prüfen. Die Standardeinstellung bleibt aus (historisches Verhalten).
- **order.created für alle Auftragstypen**: Setzen Sie `order_created_webhook_all_types = 1`, um das Auftragserstellungs-Ereignis über lokale Zustellaufträge hinaus zu erweitern. Die Standardeinstellung behält den historischen Umfang bei.
- **Signaturgeheimnisse**: Bei Ersteinrichtungen wird ein starkes Zufallsgeheimnis erzeugt; bestehende Geheimnisse werden niemals automatisch rotiert.

## 11. API-Token-Scopes & IP-Zulassungslisten (optional)

Einzelne Token können auf `orders:read`, `orders:write` und/oder `webhooks:manage` sowie auf eine Liste zugelassener IPs beschränkt werden. Uneingeschränkte Token (die Standardeinstellung und jedes bereits bestehende Token) verhalten sich exakt wie zuvor. Ein eingeschränktes Token, das außerhalb seiner Scopes/IPs aufruft, erhält `403`. Wenden Sie sich an den Support, um ein Token einzuschränken.

## 12. Carrier-Paketübermittlung (Smart Locker)

Externe Carrier übermitteln Pakete mit einem einzigen Batch-Aufruf in den Bereitstellungsbereich eines Lagers. Optional kann eine Empfänger-Telefonnummer/E-Mail angehängt werden, sodass der Empfänger nach dem Einlegen ins Smart Locker mit einem Abholcode benachrichtigt wird. Empfängerfelder sind optional — der Endpunkt bleibt abwärtskompatibel.

```json
POST https://api.superlabel.ca/api/v1/inventories/carrier-staging-stockin
Authorization: Bearer <token>
{ "carrier_id": 1, "warehouse_id": 10, "data": [
  { "carrier_reference_number": "TRK1", "ref": "REF1",
    "recipient_phone": "+14165550123", "recipient_email": "r@example.com" }
] }
```

```graphql
mutation($carrierId: Int!, $warehouseId: Int, $packages: Json) {
  submitCarrierPackages(carrierId: $carrierId, warehouseId: $warehouseId, packages: $packages)
}
```

- Authentifizierung: Bearer-Token wie üblich. Kundenkonten benötigen eine Carrier-Upload-Berechtigung (Carrier + Lager); Client-, Mitarbeiter- und Partnerkonten nutzen ihren eigenen Lagerbereich.
- Pro Paket: member_number und/oder carrier_reference_number gemäß den Carrier-Einstellungen; optional carrier_order_id, batch, ref, grid_code (nur Personal), recipient_phone, recipient_email.
- Jede Antwortzeile liefert einen pickup_code; derselbe Code wird dem Empfänger in der Abholbenachrichtigung zugestellt.

Empfängerkontakt wird verschlüsselt gespeichert und nie zurückgegeben. Wenn Telefon und E-Mail angegeben sind, werden beide Kanäle benachrichtigt; Telefon/E-Mail haben Vorrang vor der In-App-Benachrichtigung per Mitgliedsbindung.

## Kompatibilitätsversprechen

Siehe die Change-Management-Richtlinie: ausschließlich additive Antworten, neue Endpunkte neben den alten, Webhook-Bodys standardmäßig eingefroren, Standardwerte werden niemals geändert, Abkündigungen werden mindestens 30 Tage im Voraus mit `Deprecation`- / `Sunset`-Headern angekündigt. Diese Garantien werden bei jedem Release durch automatisierte Kompatibilitätstests auf Byte-Ebene durchgesetzt.