# Przewodnik po aktualizacjach integracji

Każda poniższa zmiana jest ściśle addytywna: istniejące punkty końcowe, pola odpowiedzi, kody statusów HTTP, bajty ładunków webhooków oraz starszy nagłówek `Signature` pozostają niezmienione. Integracje, które nic nie zrobią, działają dokładnie tak jak dotychczas. Każdą funkcję można wdrożyć niezależnie, w dowolnej kolejności.

Serwowane na żywo pod adresem https://api.superlabel.ca/api/documentation/integration-updates?lang=pl (`?download=1`, aby zapisać). Dokumenty towarzyszące: OpenAPI (https://api.superlabel.ca/api/documentation?lang=pl), kolekcja Postman (https://api.superlabel.ca/api/documentation/postman-collection), słownik i przepływ statusów (https://api.superlabel.ca/api/documentation/order-status-flow?lang=pl).

---

## 1. Anulowanie po numerze śledzenia (idempotentne)

`POST https://api.superlabel.ca/api/v1/orders/cancel` — podaj dokładnie jedno z: `order_id`, `tracking_number`, `external_tracking_number`.

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

- Sukces: `200 {"result":true,"id":123456,"already_cancelled":false,...}`
- Już anulowane (bezpieczne ponowienie): `200` z `"already_cancelled": true`
- Numer pasuje do kilku aktywnych zamówień: `409` z `"matched_order_ids": [...]` — ponów żądanie z `order_id`.
- Starszy punkt końcowy `GET /v1/orders/{orderId}/cancel` pozostaje niezmieniony.

## 2. Przyrostowe kanały uzgadniania danych

Przejrzyj wszystko, co zmieniło się w danym oknie czasowym; dzięki paginacji kursorowej nigdy nie pominiesz ani nie policzysz podwójnie żadnego rekordu.

- `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` przyjmują uniksowe znaczniki czasu lub ciągi w formacie `Y-m-d H:i:s` w strefie czasowej platformy. Podążaj za `next_cursor`, dopóki `has_more` nie będzie fałszywe; porównuj z uniksowymi polami `*_timestamp`, nigdy z ciągami czasu lokalnego. Elementy zdarzeń śledzenia zawierają `occurred_at` / `occurred_timestamp` (czas biznesowego wystąpienia; dla wierszy historycznych równy czasowi utworzenia).

## 3. Maszynowo odczytywalne kody błędów i śledzenie żądań

Częste odpowiedzi błędów tworzenia/anulowania zawierają teraz stabilne pole `code` obok niezmienionego `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`.
Kody są stabilnymi identyfikatorami — mogą pojawiać się nowe, istniejące nigdy nie zmieniają znaczenia. Każda odpowiedź API zwraca również nagłówek `X-Request-ID`; podaj go przy zgłaszaniu problemu.

## 4. Ulepszenia wykrywania duplikatów

Przy `auto_deduplication=1` wpisy `exist_package_ref` / `exist_external_tracking_number` zablokowanego żądania utworzenia zawierają teraz istniejące `order_id` i `order_ref`, a koperta zawiera `"duplicate": true`. Opcjonalny tryb ścisły: wyślij `strict_duplicate_check=1`, aby otrzymać HTTP `409` zamiast dotychczasowego `200` + `result:false` (pomiń flagę, aby zachować dotychczasowe zachowanie).

## 5. Opcje tworzenia wsadowego

- `per_order_transaction: 1` (na najwyższym poziomie treści wsadu): każde zamówienie zatwierdzane jest niezależnie — pojedyncze niepowodzenie nie wycofuje już pozostałych. Jeśli przetwarzanie zakończy się przedwcześnie, nadal otrzymasz wiersze dla wszystkiego, co się powiodło, plus końcowy wiersz `{"result":false,"batch_aborted":true}`.
- Wsady powyżej 100 zamówień otrzymują doradczy nagłówek odpowiedzi `X-Batch-Size-Warning`; dla dużych wolumenów preferuj `POST /v1/client/batchOrderCreateAsync`.

## 6. Synchronizacja plików potwierdzenia doręczenia

Wpisy `proofs[]` w odpowiedziach śledzenia zawierają teraz również:

```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 }
```

Używaj `file_id` jako klucza deduplikacji / synchronizacji przyrostowej. `signed_url` to wygasający link (7 dni) — po wygaśnięciu ponownie odpytaj śledzenie o świeży. Trwałe linki `url` / `full_url` pozostają niezmienione.

## 7. Webhooki: nagłówki podpisu v2 (wszystkie dostarczenia)

Każdy webhook wysyła teraz DODATKOWO, obok niezmienionego starszego nagłówka `Signature`:

| Nagłówek | Znaczenie |
|---|---|
| `X-Webhook-Event-Id` | UUID, stały pomiędzy ponowieniami — używaj do deduplikacji |
| `X-Webhook-Timestamp` | sekundy uniksowe w momencie pierwszej wysyłki |
| `X-Webhook-Signature-V2` | HMAC-SHA256 z `"<timestamp>.<raw body>"` |

Weryfikacja (dowolny język): `expected = HMAC_SHA256(timestamp + "." + raw_body, your_secret)`; porównuj z nagłówkiem w czasie stałym. Znacznik czasu jest ustalany przy pierwszej wysyłce i ponownie używany przy ponowieniach (ponowienia mogą trwać do ~3 godzin), więc połącz szerokie okno tolerancji z deduplikacją po `X-Webhook-Event-Id`, zamiast stosować rygorystyczne odcięcie antyreplay. Twoja dotychczasowa weryfikacja starszego nagłówka `Signature` działa bez zmian — wdroż v2, kiedy zechcesz. Przetestuj oba podpisy względem swojego punktu końcowego na stronie przewodnika po webhookach (`/webhooks-guide`).

## 8. Webhooki: opcjonalna koperta ładunku

Ustaw `webhook_payload_envelope = 1` w ustawieniach webhooków, aby otrzymywać, wewnątrz treści JSON zdarzeń w formie obiektu: `event_id`, `event_time` (ISO8601 z przesunięciem), `event_timestamp` (uniksowy), a także — tam, gdzie ma to zastosowanie — `is_correction: true` (zamówienie wcześniej doręczone/przekazane ponownie weszło do przepływu) oraz `occurred_at` / `occurred_timestamp` w zdarzeniach śledzenia. Bez tej flagi ładunek pozostaje bajt w bajt identyczny jak dotychczas. Ładunki w formie listy (`order.create_async`) nigdy nie są modyfikowane.

## 9. Nowe zdarzenia webhooków (opcjonalne adresy URL)

- `pod.files_updated` — zdjęcie doręczenia/podpis zostało dodane lub usunięte po fakcie. Skonfiguruj `pod_files_webhook_url`. Ładunek:
  `{"action":"added|removed","order_id":...,"order_ref":...,
  "tracking_number":[...],"external_tracking_number":[...],
  "file":{"file_id":...,"type":1|2,"note":null}, "event_id":..., ...}`
- `order.deleted` — zamówienie zostało trwale usunięte. Skonfiguruj `order_deleted_webhook_url`. Ładunek: `{"action":"deleted","order_id":...,
  "order_ref":...,"tracking_number":[...],"external_tracking_number":[...],
  "event_id":..., ...}`

Oba zdarzenia zawsze zawierają pola koperty i są wysyłane tylko wtedy, gdy skonfigurowano ich adres URL.

## 10. Webhooki: opcje dostarczania

- **Wiele punktów końcowych na zdarzenie**: każde ustawienie adresu URL webhooka akceptuje pojedynczy URL (jak dotychczas), listę rozdzielaną przecinkami lub tablicę JSON. Każdy punkt końcowy ma własny cykl dostarczania i ponowień.
- **Weryfikacja TLS**: ustaw `webhook_verify_ssl = 1`, aby wychodzące wywołania weryfikowały Twój certyfikat. Domyślnie pozostaje wyłączona (zachowanie historyczne).
- **order.created dla wszystkich typów zamówień**: ustaw `order_created_webhook_all_types = 1`, aby rozszerzyć zdarzenie utworzenia zamówienia poza zamówienia doręczeń lokalnych. Domyślnie zachowywany jest historyczny zakres.
- **Sekrety podpisujące**: konfiguracje tworzone po raz pierwszy otrzymują silny losowy sekret; istniejące sekrety nigdy nie są rotowane automatycznie.

## 11. Zakresy tokenów API i listy dozwolonych IP (opcjonalne)

Poszczególne tokeny można ograniczyć do `orders:read`, `orders:write` i/lub `webhooks:manage` oraz do listy dozwolonych adresów IP. Tokeny bez ograniczeń (domyślne oraz wszystkie istniejące wcześniej) zachowują się dokładnie tak jak dotychczas. Ograniczony token wywołujący poza swoimi zakresami/adresami IP otrzymuje `403`. Skontaktuj się z pomocą techniczną, aby ograniczyć token.

## 12. Przesyłanie paczek przewoźnika (Smart Locker)

Zewnętrzni przewoźnicy przesyłają paczki do strefy przygotowania w magazynie jednym wywołaniem wsadowym. Opcjonalnie można dołączyć telefon/e-mail odbiorcy, aby powiadomić odbiorcę kodem odbioru po umieszczeniu paczki w inteligentnej szafce. Pola odbiorcy są opcjonalne — endpoint pozostaje wstecznie zgodny.

```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)
}
```

- Uwierzytelnianie: token Bearer jak zwykle. Konta klientów muszą mieć autoryzację przesyłania przewoźnika (przewoźnik + magazyn); konta client, employee i partner używają własnego zakresu magazynu.
- Na paczkę: member_number i/lub carrier_reference_number zgodnie z ustawieniami przewoźnika; opcjonalnie carrier_order_id, batch, ref, grid_code (tylko personel), recipient_phone, recipient_email.
- Każdy wiersz odpowiedzi zwraca pickup_code; ten sam kod jest dostarczany odbiorcy w powiadomieniu o odbiorze.

Kontakt odbiorcy jest przechowywany w postaci zaszyfrowanej i nigdy nie jest zwracany. Gdy podano telefon i e-mail, powiadamiane są oba kanały; telefon/e-mail mają priorytet nad powiadomieniem w aplikacji przez powiązanie członkowskie.

## Gwarancja zgodności

Zobacz politykę zarządzania zmianami: odpowiedzi wyłącznie addytywne, nowe punkty końcowe obok starych, treści webhooków domyślnie zamrożone, wartości domyślne nigdy nie są zmieniane, wycofania ogłaszane z co najmniej 30-dniowym wyprzedzeniem z nagłówkami `Deprecation` / `Sunset`. Gwarancje te są egzekwowane przez zautomatyzowane testy zgodności na poziomie bajtów przy każdym wydaniu.