# Guida agli aggiornamenti di integrazione

Ogni modifica riportata di seguito è strettamente additiva: endpoint esistenti, campi di risposta, codici di stato HTTP, byte dei payload dei webhook e l'header legacy `Signature` restano invariati. Le integrazioni che non fanno nulla continuano a funzionare esattamente come prima. Adottate ciascuna funzionalità in modo indipendente, in qualsiasi ordine.

Servito in tempo reale all'indirizzo https://api.superlabel.ca/api/documentation/integration-updates?lang=it (`?download=1` per salvarlo). Documenti correlati: OpenAPI (https://api.superlabel.ca/api/documentation?lang=it), raccolta Postman (https://api.superlabel.ca/api/documentation/postman-collection), dizionario e flusso degli stati (https://api.superlabel.ca/api/documentation/order-status-flow?lang=it).

---

## 1. Annullamento tramite numero di tracciamento (idempotente)

`POST https://api.superlabel.ca/api/v1/orders/cancel` — fornire esattamente uno tra `order_id`, `tracking_number`, `external_tracking_number`.

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

- Successo: `200 {"result":true,"id":123456,"already_cancelled":false,...}`
- Già annullato (nuovo tentativo sicuro): `200` con `"already_cancelled": true`
- Il numero corrisponde a più ordini attivi: `409` con `"matched_order_ids": [...]` — ripetere la richiesta con `order_id`.
- Il legacy `GET /v1/orders/{orderId}/cancel` resta invariato.

## 2. Feed di riconciliazione incrementale

Scansionate tutto ciò che è cambiato all'interno di una finestra temporale; grazie alla paginazione a cursore nessun record viene perso o conteggiato due volte.

- `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` accettano timestamp unix o stringhe `Y-m-d H:i:s` nel fuso orario della piattaforma. Seguire `next_cursor` finché `has_more` è false; effettuare i confronti con i campi unix `*_timestamp`, mai con stringhe in ora locale. Gli elementi degli eventi di tracciamento includono `occurred_at` / `occurred_timestamp` (momento in cui l'evento è avvenuto a livello di business; coincide con la data di creazione per le righe storiche).

## 3. Codici di errore leggibili dalle macchine e tracciamento delle richieste

Le risposte di errore ad alta frequenza per creazione/annullamento ora includono un campo `code` stabile accanto al `message` invariato:
`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`.
I codici sono identificatori stabili — possono comparirne di nuovi, quelli esistenti non cambiano mai significato. Ogni risposta API restituisce inoltre `X-Request-ID`; citatelo quando segnalate un problema.

## 4. Miglioramenti al rilevamento dei duplicati

Con `auto_deduplication=1`, le voci `exist_package_ref` / `exist_external_tracking_number` di una creazione bloccata ora includono gli `order_id` e `order_ref` esistenti, e l'envelope contiene `"duplicate": true`. Modalità rigorosa opzionale: inviate `strict_duplicate_check=1` per ricevere HTTP `409` invece del legacy `200` + `result:false` (omettete il flag per mantenere il comportamento legacy).

## 5. Opzioni di creazione in batch

- `per_order_transaction: 1` (al livello superiore del corpo del batch): ogni ordine viene salvato in modo indipendente — un errore non annulla più gli altri ordini del batch. Se l'elaborazione si interrompe in anticipo, ricevete comunque le righe di tutto ciò che è stato completato, più una riga finale `{"result":false,"batch_aborted":true}`.
- I batch con più di 100 ordini ricevono un header di risposta informativo `X-Batch-Size-Warning`; per grandi volumi preferite `POST /v1/client/batchOrderCreateAsync`.

## 6. Sincronizzazione dei file di prova di consegna

Le voci `proofs[]` delle risposte di tracciamento ora includono anche:

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

Usate `file_id` come chiave di deduplicazione / sincronizzazione incrementale. `signed_url` è un link a scadenza (7 giorni) — dopo la scadenza, interrogate di nuovo il tracciamento per ottenerne uno aggiornato. I link permanenti `url` / `full_url` restano invariati.

## 7. Webhook: header di firma v2 (tutte le consegne)

Ogni webhook ora invia ANCHE, accanto all'header legacy `Signature` invariato:

| Header | Significato |
|---|---|
| `X-Webhook-Event-Id` | UUID, stabile tra i tentativi — da usare per la deduplicazione |
| `X-Webhook-Timestamp` | secondi unix al primo invio |
| `X-Webhook-Signature-V2` | HMAC-SHA256 di `"<timestamp>.<raw body>"` |

Verifica (in qualsiasi linguaggio): `expected = HMAC_SHA256(timestamp + "." + raw_body, your_secret)`; confronto a tempo costante con l'header. Il timestamp viene fissato al primo invio e riutilizzato nei tentativi successivi (che possono protrarsi fino a ~3 ore), quindi abbinate una finestra di tolleranza generosa alla deduplicazione tramite `X-Webhook-Event-Id` invece di un limite di replay troppo stretto. La verifica esistente della `Signature` legacy continua a funzionare senza modifiche — adottate la v2 quando preferite. Potete testare entrambe le firme sul vostro endpoint dalla pagina della guida ai webhook (`/webhooks-guide`).

## 8. Webhook: envelope del payload opzionale

Impostate `webhook_payload_envelope = 1` nelle impostazioni dei webhook per ricevere, all'interno del corpo JSON degli eventi a forma di oggetto: `event_id`, `event_time` (ISO8601 con offset), `event_timestamp` (unix), più — dove applicabile — `is_correction: true` (un ordine già consegnato/consegnato a terzi è rientrato nel flusso) e `occurred_at` / `occurred_timestamp` sugli eventi di tracciamento. Senza il flag il payload resta identico byte per byte a prima. I payload a forma di lista (`order.create_async`) non vengono mai modificati.

## 9. Nuovi eventi webhook (URL opzionali)

- `pod.files_updated` — una foto/firma di consegna è stata aggiunta o rimossa a posteriori. Configurate `pod_files_webhook_url`. Payload:
  `{"action":"added|removed","order_id":...,"order_ref":...,
  "tracking_number":[...],"external_tracking_number":[...],
  "file":{"file_id":...,"type":1|2,"note":null}, "event_id":..., ...}`
- `order.deleted` — un ordine è stato eliminato definitivamente. Configurate `order_deleted_webhook_url`. Payload: `{"action":"deleted","order_id":...,
  "order_ref":...,"tracking_number":[...],"external_tracking_number":[...],
  "event_id":..., ...}`

Entrambi gli eventi includono sempre i campi dell'envelope e vengono inviati solo quando il rispettivo URL è configurato.

## 10. Webhook: opzioni di consegna

- **Endpoint multipli per evento**: ogni impostazione di URL webhook accetta un singolo URL (come prima), un elenco separato da virgole o un array JSON. Ogni endpoint ha il proprio ciclo di consegna e di tentativi.
- **Verifica TLS**: impostate `webhook_verify_ssl = 1` perché le chiamate in uscita verifichino il vostro certificato. Il valore predefinito resta disattivato (comportamento storico).
- **order.created per tutti i tipi di ordine**: impostate `order_created_webhook_all_types = 1` per estendere l'evento di creazione ordine oltre gli ordini di consegna locale. Il valore predefinito mantiene l'ambito storico.
- **Segreti di firma**: le nuove configurazioni ricevono un segreto casuale robusto; i segreti esistenti non vengono mai ruotati automaticamente.

## 11. Ambiti dei token API e liste di IP consentiti (opzionale)

I singoli token possono essere limitati a `orders:read`, `orders:write` e/o `webhooks:manage`, nonché a un elenco di IP consentiti. I token senza restrizioni (l'impostazione predefinita, e ogni token preesistente) si comportano esattamente come prima. Un token con restrizioni che effettua chiamate al di fuori dei propri ambiti/IP riceve `403`. Contattate il supporto per applicare restrizioni a un token.

## 12. Invio pacchi corriere (Smart Locker)

I corrieri esterni inviano i pacchi nell'area di staging di un magazzino con un'unica chiamata batch. Facoltativamente è possibile allegare telefono/email del destinatario per notificarlo con un codice di ritiro una volta collocato il pacco nell'armadietto intelligente. I campi del destinatario sono facoltativi: l'endpoint resta retrocompatibile.

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

- Autenticazione: token Bearer come al solito. Gli account cliente devono avere un'autorizzazione al caricamento corriere (corriere + magazzino); gli account client, employee e partner usano il proprio ambito di magazzino.
- Per pacco: member_number e/o carrier_reference_number secondo le impostazioni del corriere; facoltativi carrier_order_id, batch, ref, grid_code (solo personale), recipient_phone, recipient_email.
- Ogni riga della risposta restituisce un pickup_code; lo stesso codice viene consegnato al destinatario nella notifica di ritiro.

Il contatto del destinatario è memorizzato cifrato e mai restituito. Quando vengono forniti telefono ed email, vengono notificati entrambi i canali; telefono/email hanno priorità sulla notifica in-app tramite associazione socio.

## Impegno di compatibilità

Consultate la policy di gestione delle modifiche: risposte solo additive, nuovi endpoint affiancati a quelli esistenti, corpi dei webhook congelati per impostazione predefinita, valori predefiniti mai modificati, deprecazioni annunciate con almeno 30 giorni di anticipo tramite gli header `Deprecation` / `Sunset`. Queste garanzie sono applicate da test di compatibilità automatizzati a livello di byte a ogni release.