# Štítky dopravcu

Nákup zásielky dopravcu: zoznam spôsobov → cenová ponuka → vytvorenie štítku → stiahnutie PDF → sledovanie → príjem udalostí → zrušenie (alebo uzavretie dňa).

Táto príručka dokumentuje iba nasledujúce operácie. Vykonajte ich v poradí.

Nahraďte `YOUR_HOST`, `ACCESS_TOKEN` a `shipping_method` svojimi hodnotami. Id spôsobov sa líšia podľa účtu — nikdy ich nehardcodujte.

## 1. Prihlásenie

```bash
curl -X POST https://YOUR_HOST/api/v1/user/login \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"your_password"}'
```

```
Authorization: Bearer ACCESS_TOKEN
```

GraphQL používa rovnakú hlavičku na `POST /api/graphql`.

[Príručka REST](/api/documentation#/paths/v1-user-login/post) · [Príručka GraphQL](/api/graphql/documentation#/user/userLogin)

**Overenie:** prihlásenie vráti `access_token`. Neskoršie volanie bez neho vráti `401`.

## 2. Zoznam spôsobov odoslania

**REST:** `POST /api/v1/labelservice/getShippingMethodList` — [Príručka REST](/api/documentation#/paths/v1-labelservice-getShippingMethodList/post)

```bash
curl -X POST https://YOUR_HOST/api/v1/labelservice/getShippingMethodList \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"detail": true}'
```

Každý riadok má:

| Pole | Použitie |
|---|---|
| `id` | `shipping_method` v každom neskoršom volaní |
| `name` | Zobrazovaný názov |
| `unique_identifier` | Stabilný kód |
| `options.signature_option` | Podpis dostupný |
| `options.insurance_option` | Poistenie dostupné |
| `options.multi_package` | Viac ako jeden kus |

**GraphQL:** `labelserviceGetShippingMethodList` ([Príručka GraphQL](/api/graphql/documentation#/labelservice/labelserviceGetShippingMethodList)) (JSON skalár).

**Overenie:** zoznam nie je prázdny. Vybrali ste jedno `id` a viete, či ten spôsob povoľuje podpis, poistenie a viac zásielok. Prázdny zoznam znamená, že na účte nie je zapnutý žiadny spôsob.

## 3. Cenová ponuka

Skúšobný beh. Dopravca je opýtaný na cenu; nič sa nerezervuje. Telo má rovnaký tvar ako pri vytváraní. `shipping_method` je povinné.

**REST:** `POST /api/v1/labelservice/rate` — [Príručka REST](/api/documentation#/paths/v1-labelservice-rate/post)

```bash
curl -X POST https://YOUR_HOST/api/v1/labelservice/rate \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "shipping_method": 59,
    "name": "Jane Recipient",
    "telephone": "5555555555",
    "email": "jane@example.com",
    "address_1": "6701 RUE HADLEY",
    "city": "Montreal",
    "province": "QC",
    "postcode": "H4E3R3",
    "country": "CA",
    "weight": 1,
    "length": 30,
    "width": 20,
    "height": 10,
    "dimension_unit": 2,
    "weight_unit": 2,
    "signature_option": 0,
    "insurance_option": 0,
    "package_type": "parcel",
    "ref": "DEV-LABEL-001",
    "sender_name": "Acme Warehouse",
    "sender_telephone": "5555555555",
    "sender_address_1": "2667 boul des sources",
    "sender_city": "Pointe-Claire",
    "sender_province": "QC",
    "sender_postcode": "H9S2H9",
    "sender_country": "CA"
  }'
```

`weight_unit`: `1` g, `2` kg, `3` oz, `4` lb. `dimension_unit`: `1` mm, `2` cm, `3` m, `4` in.

Pre viac ako jeden kus pošlite `packages: [{ ref, weight, length, width, height, weight_unit, dimension_unit }]`. `shipping_from` (id adresára) alebo `shipping_from_code` môže nahradiť blok `sender_*`.

**GraphQL:** `labelserviceRate` ([Príručka GraphQL](/api/graphql/documentation#/labelservice/labelserviceRate)).

**Overenie:** `result` je true a máte cenu (a dni prepravy, keď ich dopravca pošle). Ak nie je sadzba, opravte cieľ / zásielku / spôsob **pred** vytvorením.

## 4. Vytvorenie štítku

Tým sa zásielka rezervuje u dopravcu.

**REST:** `POST /api/v1/labelservice/submitOrder` — [Príručka REST](/api/documentation#/paths/v1-labelservice-submitOrder/post)

Rovnaké telo ako krok 3. Pošlite `Idempotency-Key`.

```bash
curl -X POST https://YOUR_HOST/api/v1/labelservice/submitOrder \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: dev-label-001" \
  -d '{
    "shipping_method": 59,
    "name": "Jane Recipient",
    "telephone": "5555555555",
    "email": "jane@example.com",
    "address_1": "6701 RUE HADLEY",
    "city": "Montreal",
    "province": "QC",
    "postcode": "H4E3R3",
    "country": "CA",
    "weight": 1,
    "length": 30,
    "width": 20,
    "height": 10,
    "dimension_unit": 2,
    "weight_unit": 2,
    "signature_option": 0,
    "insurance_option": 0,
    "package_type": "parcel",
    "ref": "DEV-LABEL-001",
    "sender_name": "Acme Warehouse",
    "sender_telephone": "5555555555",
    "sender_address_1": "2667 boul des sources",
    "sender_city": "Pointe-Claire",
    "sender_province": "QC",
    "sender_postcode": "H9S2H9",
    "sender_country": "CA"
  }'
```

**GraphQL:** `labelserviceSubmitOrder` ([Príručka GraphQL](/api/graphql/documentation#/labelservice/labelserviceSubmitOrder)).

```json
{
  "result": true,
  "id": 12345,
  "shipping_price": "12.50",
  "tracking_numbers": ["1Z999AA10123456784"],
  "external_id": "EXT_12345"
}
```

| Pole | Použitie |
|---|---|
| `id` | Id objednávky Superroute — stiahnutie a zrušenie |
| `tracking_numbers` | Dajte ich kupujúcemu; sledovanie ich prijíma |
| `external_id` | Id zásielky dopravcu |
| `shipping_price` | Účtovaná suma |

**Overenie:** `tracking_numbers` nie je prázdne. Uložte `id` a čísla. Rovnaký `Idempotency-Key` nesmie kúpiť druhý štítok.

## 5. Stiahnutie PDF

**REST:** `POST /api/v1/labelservice/getShippingLabel` — [Príručka REST](/api/documentation#/paths/v1-labelservice-getShippingLabel/post)

```bash
curl -X POST https://YOUR_HOST/api/v1/labelservice/getShippingLabel \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "12345",
    "type": "ORDER_ID",
    "base64": 1
  }'
```

`type` môže byť `ORDER_ID`, `TRACKING_NUMBER` alebo `REF`. `base64: 0` streamuje PDF. Toto je **oficiálny štítok dopravcu**. Počet kusov je daný rezerváciou.

**GraphQL:** `labelserviceGetShippingLabel` ([Príručka GraphQL](/api/graphql/documentation#/labelservice/labelserviceGetShippingLabel)).

**Overenie:** PDF sa otvorí a ukáže čiarový kód / sledovacie číslo dopravcu z kroku 4. Vytlačte jednu testovaciu kópiu a zahoďte ju — nedávajte testovací štítok dopravcovi.

## 6. Sledovanie

Bez tokenu. Použite číslo z `tracking_numbers`:

```bash
curl https://YOUR_HOST/api/v1/tracking/1Z999AA10123456784
```

[Príručka REST](/api/documentation#/operations/getPublicTracking) · [Príručka GraphQL](/api/graphql/documentation#/tracking/trackingPublic)

**GraphQL:**

```graphql
query {
  trackingPublic(trackingNumber: "1Z999AA10123456784") {
    result
    deliveried
    is_third_party_tracking
    data {
      tracking_event_status_id
      tracking_event_key
      description
      updated_at_localized
    }
    proofs { file_id type full_url signed_url }
  }
}
```

`is_third_party_tracking` je true, keď udalosti prichádzajú od dopravcu. Vetvenie podľa `tracking_event_status_id` / `tracking_event_key`, nie podľa `description`. Najnovšia udalosť je prvá v `data`. Rané udalosti môžu stále byť «informácie odoslané», kým dopravca nenačíta zásielku. `500` je doručené; `proofs[]` potom môže obsahovať podpis (`type` `1`) alebo fotku (`type` `2`).

**Overenie:** vyhľadanie vráti zásielku, ktorú ste práve vytvorili. Neznáme číslo je `result: false` / 404.

## 7. Konfigurácia oznámení o udalostiach

| Nastavenie | Udalosť | Kedy |
|---|---|---|
| `order_create_webhook_url` | `order.created` | Uložiť `id` a sledovacie čísla dopravcu |
| `tracking_event_webhook_url` | `tracking.event` | Skeny dopravcu, na ceste, doručené |
| `order_status_change_webhook_url` | `order.status_change` | Stav vo vašom systéme |
| `order_cancel_failed_webhook_url` | `order.cancel_failed` | Zrušenie odmietnuté, pretože dopravca už má zásielku |

**REST:** `PUT /api/v1/webhook-settings` — [Príručka REST](/api/documentation#/paths/v1-webhook-settings/put)

**GraphQL:** `webhookSettingsUpdate` ([Príručka GraphQL](/api/graphql/documentation#/webhooks/webhookSettingsUpdate)).

```bash
curl -X PUT https://YOUR_HOST/api/v1/webhook-settings \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "order_create_webhook_url": "https://erp.example.com/hooks/superroute",
    "tracking_event_webhook_url": "https://erp.example.com/hooks/superroute",
    "webhook_sign_secret": "YOUR_LONG_RANDOM_SECRET",
    "webhook_verify_ssl": 1
  }'
```

Overujte **v2** nad surovým telom: `HMAC_SHA256(timestamp + "." + raw_body, secret)` proti `X-Webhook-Signature-V2`. Deduplikujte podľa `X-Webhook-Event-Id`. Odpovedzte **2xx do 3 sekúnd**.

```php
$raw = file_get_contents('php://input');
$ts  = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE_V2'] ?? '';
$expected = hash_hmac('sha256', $ts . '.' . $raw, $sharedSecret);
if (!hash_equals($expected, $sig)) {
    http_response_code(401);
    exit;
}
```

**Overenie:** jeden testovací `submitOrder` vyprodukuje `order.created` s týmito `tracking_numbers`. Zlé tajomstvo je `401` od vášho prijímača.

## 8. Zrušenie

Len kým to dopravca ešte povoľuje (zvyčajne pred vyzdvihnutím).

**REST:** `POST /api/v1/labelservice/cancelShippingLabel` — [Príručka REST](/api/documentation#/paths/v1-labelservice-cancelShippingLabel/post)

```bash
curl -X POST https://YOUR_HOST/api/v1/labelservice/cancelShippingLabel \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"12345","type":"ORDER_ID"}'
```

**GraphQL:** `labelserviceCancelShippingLabel` ([Príručka GraphQL](/api/graphql/documentation#/labelservice/labelserviceCancelShippingLabel)).

Dopravca, ktorý už zásielku má, odmietne — to je `order.cancel_failed`.

**Overenie:** druhé zrušenie je bezpečné. Sledovanie už zásielku neberie ako živú.

## 9. Koniec dňa (len ak to tento spôsob vyžaduje)

Niektorí dopravcovia potrebujú denný manifest.

**REST:** `POST /api/v1/labelservice/endofday` — [Príručka REST](/api/documentation#/paths/v1-labelservice-endofday/post)

```bash
curl -X POST https://YOUR_HOST/api/v1/labelservice/endofday \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"shipping_method": 59}'
```

**GraphQL:** `labelserviceEndofday` ([Príručka GraphQL](/api/graphql/documentation#/labelservice/labelserviceEndofday)).

Zavolajte raz po poslednom štítku odosielacieho dňa. Tento krok preskočte, keď spôsob z kroku 2 takú požiadavku nemá.

**Overenie:** telo úspechu (alebo potvrdenie dopravcu) vypíše dnešné štítky. Spustite najprv na testovacom spôsobe.

## Zoznam testov

Použite cieľ, ktorý ovládate, a spôsob, ktorý možno zrušiť:

- [ ] Zoznam spôsobov nie je prázdny; zachytili ste jedno `id`.
- [ ] Sadzba vráti cenu pre ten spôsob a cieľ.
- [ ] Submit vráti `tracking_numbers`; rovnaký `Idempotency-Key` nekúpi druhý štítok.
- [ ] PDF štítku sa otvorí a ukáže sledovacie číslo dopravcu.
- [ ] Verejné sledovanie nájde zásielku podľa toho čísla.
- [ ] Príde `order.created`; podpis v2 overí.
- [ ] Zrušenie uspeje, **alebo** ste potvrdili, že tento spôsob po rezervácii nemožno zrušiť.
- [ ] Ak spôsob potrebuje koniec dňa, testovací beh skončí bez chyby.
