Skip to content

Richieste API

Base URL

Tutti gli endpoint vivono sotto https://<instance>/api/v1/. Prefisso v1 parte del contratto. Breaking change vanno in v2. In v1 aggiungiamo campi ma non rinominiamo né rimuoviamo mai. I campi sconosciuti in response possono essere ignorati.

Header richiesti

HeaderValoreNote
AuthorizationBearer <access_token>Sempre
Acceptapplication/jsonDefault
Content-Typeapplication/jsonSulle POST/PATCH con body
Idempotency-KeyUUID generato dal partnerRaccomandato su ogni POST (vedi Idempotenza)

Isolamento tenant

Un partner è legato a esattamente una Organization. Non puoi vedere dati di altri partner, di LifeDome interni, o di org concorrenti. ID fuori tenant → 404 Not Found.

Rate limit

Limiti registrati sul partner (default: 100 req/min, 5 000 req/h). Gestire sempre 429 Too Many Requests con Retry-After e backoff esponenziale + jitter.

Paginazione

Due strategie, dipende dall'endpoint:

  • Cursor pagination per endpoint time-series o ad alto volume: /devices/{uid}/locations/, /devices/{uid}/telemetry/, /events/, /devices/{uid}/commands/. La response ritorna {"next": "<url-opaco>", "previous": "<url-opaco>", "results": [...]} — segui next per la pagina successiva. Query param cursor=<token>. Non c'è count totale.
  • Page-number pagination per liste collezionali: /devices/, /auth/users/, /assignments/, /alert-thresholds/, /geofences/, /audit-log/. Query params page=N&page_size=M. Response include count, total_pages, next, previous, results.

Date e orari

Tutti i campi timestamp nelle response (ts, device_ts, received_at, created_at, updated_at, deleted_at, connected_at, last_seen, ecc.) sono UTC in formato ISO-8601 con offset esplicito +00:00. Esempio: 2026-05-20T14:32:11+00:00.

Su Location e Telemetry ci sono tre timestamp distinti:

  • ts — orologio del server al momento in cui il protocol server riceve e processa il pacchetto dal device. Canonico, da usare per ordinamento, paginazione, display.
  • device_ts — orologio del device parsato dal payload del pacchetto. Audit-only. Può essere null (pacchetto senza data/ora) o sballato (RTC del device che deriva). Non usarlo per ordinamento.
  • received_at — istante dell'INSERT su database. Campo interno, quasi sempre vicinissimo a ts. Ignoralo lato applicazione.

Conseguenze:

  • Nessun campo è in ora locale o fuso server. Il partner converte alla timezone dell'utente finale lato proprio.
  • I parametri query ts_after / ts_before (storici location / telemetry / events) accettano ISO-8601. Passare sempre con offset esplicito (+00:00 o Z); un input senza offset viene interpretato come ora locale del server e produce risultati ambigui.
  • L'endpoint /organizations/self/ espone il campo timezone (IANA, es. Europe/Rome) come preferenza di display della org; non altera mai la rappresentazione dei ts in response.

Idempotenza

Sulle POST il partner può inviare l'header Idempotency-Key valorizzato con un UUIDv4 generato lato partner. Semantica (uguale a Stripe / GitHub / PayPal):

  • Stessa key + stesso body → response cacheata (status + body), header X-Idempotent-Replayed: true. Side-effect eseguito una volta sola.
  • Stessa key + body diverso409 Conflict, body {"detail": "Idempotency key already used with different request body."}.
  • Key assente → nessun dedup, la richiesta prosegue normalmente.
  • TTL cache: 24 ore. Chiave di cache scoped per application del partner.

Politica consigliata: un UUID per operazione logica, riusato in caso di retry (errori di rete, timeout, 5xx). Nuovo UUID solo quando l'operazione è abbandonata.

L'header copre solo POST. Per PATCH / DELETE accettare semantica at-least-once oppure forzare manualmente l'idempotenza lato partner.


Errori

Shape

Endpoint /api/v1/* — response uniforme:

json
{
  "code": "insufficient_scope",
  "detail": "Token missing required scope: devices:write"
}

Il campo code è opzionale (non sempre presente in errori di validazione nested). Fare matching prima sullo status HTTP, poi su code se presente.

Endpoint /o/token/ — RFC 6749 §5.2:

json
{ "error": "invalid_scope", "error_description": "..." }

Quando fare retry

ClasseStatusRetry?
Auth401No — ri-autenticarsi; se persiste → credenziali errate
Scope / permission403No — chiedere grant a LifeDome
Tenant boundary404 su risorsa attesaNo — fuori dal tuo tenant
Validation400No — correggere il body
Conflict409 su idempotency reuseNo — usare chiave nuova
Conflict409 su conflict di versioneSì — ri-leggere + ri-provare
Rate limit429Sì — rispettare Retry-After, backoff esp. + jitter
Server5xxSì — 3–5 tentativi, backoff esp., stesso Idempotency-Key

Codici da riconoscere a memoria

CodiceDoveSignificato
scope_not_availableauth gateEndpoint non parte della superficie partner
insufficient_scopeauth gateToken valido ma scope mancante
invalid_scope/o/token/Scope fuori allow-list del partner
partner_suspendedauth layerIl partner non è ACTIVE
idempotency_key_reuse (detail)idempotencyStessa key, body diverso

© Mastersoft — LifeDome