Tema
Endpoint /api/v1/* — mappa concettuale
Per la firma esatta (path, body, response, status code) di ogni operazione consulta lo Schema OpenAPI. Questa pagina elenca raggruppamenti, scope, regole semantiche e flussi multi-step non rappresentabili in OpenAPI.
Convenzioni:
- Tutti i path sotto
https://<instance>/api/v1/. Authorization: Bearer <token>su ogni chiamata.uid= IMEI del device (stringa, 15 cifre).id= UUID LifeDome.- Default-deny: lo schema OpenAPI elenca l'intera superficie partner. Qualunque altro endpoint risponde
403 scope_not_available.
Utenti
Path base: /api/v1/auth/users/. Gestione anagrafica utenti scoped alla org del partner.
| Metodo | Path | Scope |
|---|---|---|
GET | / | users:read |
POST | / | users:write |
GET | /{id}/ | users:read |
PATCH | /{id}/ | users:write |
DELETE | /{id}/ | users:write |
POST | /{id}/invite/ | users:invite |
Regole semantiche:
POSTè idempotente suemail. Email già esistente in altra org → membership allegata all'utente esistente, response includemerged: true. Per prevenire leak cross-tenant, i campifirst_name/last_name/phone_numberin risposta riflettono il body della richiesta, non il profilo stored.- Utenti creati con password inutilizzabile (
portal_active: false). Per accesso portale →POST /{id}/invite/(vedi Invito portale). PATCHha allow-list stretta:first_name,last_name,phone_number,role(soloVIEWER/USER— promozione aADMIN/OWNER→ 400). Non scrivibili:email,password,is_active. Per disattivare →DELETE+ ri-POSTper riattivare.DELETE= soft-close della membership nella org del partner. L'utente globale non viene eliminato.POST /{id}/invite/rate-limited a 1/ora per utente. Risposte:202(in coda),200 { already_active: true },404(non in org).
Dispositivi
Path base: /api/v1/devices/. Registry dei device fisici (IMEI-keyed).
| Metodo | Path | Scope |
|---|---|---|
GET | / | devices:read |
POST | / | devices:write |
GET | /{uid}/ | devices:read |
PATCH | /{uid}/ | devices:write |
DELETE | /{uid}/ | devices:write |
GET | /{uid}/capabilities/ | catalog:read |
Regole semantiche:
POSTcon IMEI già presente nella stessa org = upsert (200). IMEI registrato in altra org →409 imei_conflict.- La risposta partner per un device non include la lista
assignmentsné PII degli utenti assegnati (vedi Assegnazioni). DELETE= soft-delete (impostadeleted_at). Il device esce dagli endpoint partner dopo la cancellazione.capabilities/ritorna le capability risolte per il device (config catalog + override per-istanza).
Shape last_status (per-metric freshness)
last_status (su lista/dettaglio device) espone uno snapshot per-metric. Ogni chiave allow-listed mappa a un oggetto { value, ts } dove ts è il timestamp server-side del pacchetto che ha riportato quella metrica per ultimo. Metriche diverse possono avere ts diversi perché il device le invia in pacchetti distinti.
json
"last_status": {
"hr": { "value": 72, "ts": "2026-04-17T08:22:11Z" },
"sbp": { "value": 122, "ts": "2026-04-17T08:18:02Z" },
"dbp": { "value": 80, "ts": "2026-04-17T08:18:02Z" },
"spo2": { "value": 97, "ts": "2026-04-17T08:18:02Z" },
"bat": { "value": 83, "ts": "2026-04-17T08:22:11Z" }
}Allow-list delle chiavi wire (chiavi fuori lista vengono droppate server-side):
| Chiave | Unità | Descrizione |
|---|---|---|
bat | int (0-100) | Batteria % |
hr | int | Frequenza cardiaca (bpm) |
sbp / dbp | int | Pressione sistolica / diastolica (mmHg) |
spo2 | int | Saturazione ossigeno (%) |
temp | float | Temperatura corporea (°C) |
glucose | float | Glicemia (mg/dL) |
steps | int | Contapassi |
gsm_signal | int | Segnale GSM (0-31) |
satellites | int | Satelliti GPS agganciati |
Timestamp semantica: ts è il momento server-side di ingestione del pacchetto. ts: null indica una entry legacy precedente all'introduzione di questo shape; si auto-corregge al pacchetto successivo del device.
Assegnazioni
Path base: /api/v1/devices/{uid}/ (scritture) + /api/v1/assignments/ (lettura). Relazione utente↔device.
Ruoli
| Ruolo | Valore | Italiano | Semantica |
|---|---|---|---|
OWNER | 30 | Proprietario | Holder principale. Creato dal partner al provisioning. Controllo completo. |
ASSIGNED | 20 | Assegnato | Co-holder. Controllo operativo, no delete né trasferimento. |
VIEWER | 10 | Visualizzatore | Read-only. Creato tipicamente via flow share (invito). |
Endpoint
| Metodo | Path | Scope | Note |
|---|---|---|---|
GET | /api/v1/assignments/ | assignments:read | Lista assignment attivi |
GET | /api/v1/assignments/{id}/ | assignments:read | Dettaglio |
POST | /api/v1/devices/{uid}/assign/ | assignments:write | role: owner/assigned |
POST | /api/v1/devices/{uid}/unassign/ | assignments:write | Soft-close (is_active=false) |
POST | /api/v1/devices/{uid}/share/ | assignments:share | Crea VIEWER via invito email |
DELETE | /api/v1/devices/{uid}/share/{user_id}/ | assignments:share | Revoca share VIEWER |
POST | /api/v1/organizations/invitations/server-accept/ | invitations:write | Server-side accept di token share |
Regole semantiche
assignaccetta soloowner/assigned. Per VIEWER usareshare/.- Errori
assign: utente non in org → 400User not found in this organization.; già assegnato attivo → 400User already has an active assignment for this device.. share/ha due rami:- Email già nella org → crea direttamente assignment VIEWER, nessuna email inviata.
- Email sconosciuta → crea invito (scadenza 7 giorni, device target in metadata privato) e accoda email.
link_baseopzionale, HTTPS, host nella allow-list configurata sul partner.
server-accept/è il path partner-side (separato dal/accept/umano unauthenticated). Il campopasswordè vietato (400password_not_allowed_in_partner_flow); utente creato con password inutilizzabile.
Trasferimento ownership
Non c'è endpoint dedicato. Sequenza due chiamate, non atomica:
POST /api/v1/devices/{uid}/unassign/con{ "user_id": "<vecchio_owner>" }POST /api/v1/devices/{uid}/assign/con{ "user_id": "<nuovo_owner>", "role": "owner" }
Proprietà:
- Dati storici (locations, telemetry, events, geofences, commands) conservati — sono org-scoped, non owner-scoped.
- Storico assignment conservato (soft-close + nuova riga).
- Se step 2 fallisce, device resta unassigned. Il caller deve fare rollback ri-assegnando il vecchio owner.
Posizioni
Path base: /api/v1/devices/{uid}/locations/. Scope: locations:read.
| Metodo | Path | Descrizione |
|---|---|---|
GET | /latest/ | Ultima posizione nota |
GET | / | Storico, cursor pagination |
GET | /segments/ | Segmenti viaggio (sosta/movimento) in finestra temporale |
Note:
sourceè enum (gps,lbs,wifi, ...).carrierè stringa (nome MCC/MNC risolto) onull.addressè reverse-geocoding opzionale.- Storico filtrabile per
ts_after,ts_before,source,ordering(ts/-ts). segments/default window = ultime 6 ore. Tipi segmento:moving|stopped.
Telemetria
Path base: /api/v1/devices/{uid}/telemetry/. Scope: telemetry:read.
| Metodo | Path | Descrizione |
|---|---|---|
GET | /latest/ | Merge ultime 50 righe per chiave metrica |
GET | / | Storico, cursor pagination |
Note:
/latest/ritorna{ data: { <metric>: { value, ts }, … } }. Il merge usa le ultime 50 righe Telemetry, newest-wins per chiave; ogni entry porta iltsdella riga Telemetry sorgente. Nessuntstop-level: la freshness è per-metric.- Chiavi
dataidentiche alast_status(vedi Dispositivi). Valorinullsono omessi; valori0(es.bat: 0dispositivo morente,steps: 0paziente fermo) passano: la validità è valutata in fase di ingestione del pacchetto, non in fase di serializzazione della response. - Storico
/ritorna righe raw{ id, ts, device_ts, received_at, data }.tsè server-side (canonico),device_tsè l'orologio del device dal payload (audit-only, può esserenullo sballato),received_atè il timestamp di INSERT su DB (interno).dataè il dizionario chiave→valore così come ingestito, senza ulteriori filtri sui valori. - Storico filtrabile per
cursor,ts_after,ts_before,metric(es.?metric=hr). - 404 se nessun dato disponibile.
Eventi / Allarmi
Path base: /api/v1/events/. Scope: events:read, events:acknowledge.
| Metodo | Path | Scope |
|---|---|---|
GET | / | events:read |
GET | /{id}/ | events:read |
POST | /{id}/acknowledge/ | events:acknowledge |
Note:
- Cursor pagination. Filtri:
device_uid,event_type,severity,acknowledged,ts_after,ts_before,fence_id,ordering. event_typeeseveritysono enum integer serializzati come label lowercase (info,warning,critical,geofence_exit, ...).- Detail include il campo
notes(assente in lista). - Su acknowledge da token partner,
acknowledged_byènull(no attribuzione umana);notesopzionale.
Comandi
Path base: /api/v1/devices/{uid}/commands/.
| Metodo | Path | Scope |
|---|---|---|
GET | / | commands:read |
POST | / | commands:write |
GET | /{command_uuid}/ | commands:read |
DELETE | /{command_uuid}/ | commands:write |
Regole semantiche:
- Cursor pagination. Filtri:
status,command_type,created_after,created_before. command_typedipende dalle capability del device — consultaGET /api/v1/devices/{uid}/capabilities/per la lista supportata. Tipici:locate_now,send_message,set_working_mode,set_timezone,restart,power_off,test_heart_rate,test_blood_pressure,test_temperature,test_blood_oxygen,calibrate_bp,factory_reset.Idempotency-Keyraccomandato sulle POST.- Lifecycle status pubblico:
pending→sending→sent→ack_ok|ack_error|timeout.sending= preso in carico, in scrittura sul trasporto del dispositivo. - 429 se la coda comandi del device è piena.
Messaging
Path base: /api/v1/devices/{uid}/messages/. Opt-in per partner (capability gating).
| Metodo | Path | Scope |
|---|---|---|
GET | / | messaging:read |
GET | /{id}/ | messaging:read |
DELETE | /{id}/ | messaging:write |
POST | /send-text/ | messaging:write |
POST | /send-tts/ | messaging:write |
POST | /upload-voice/ | messaging:write (multipart/form-data) |
POST | /bulk-delete/ | messaging:write |
Note:
- Enum values come label lowercase:
direction(inbound/outbound),message_type(text/voice),device_delivery_status(pending/processing/ready/sending/delivered/failed). - TTS non è un message_type — è un'azione (
POST /send-tts/) che crea un messaggiovoice(audio sintetizzato server-side). - Limiti:
send-text200 caratteri;send-tts500 caratteri;upload-voice10 MB / 30 s (AMR o simili);bulk-delete1–100 UUID. - Messaggi inviati da token partner hanno
sender_user_id: null(no attribuzione umana).sender_namevalorizzato da request o logica di servizio.
Geofence
Path base: /api/v1/geofences/. Scope: geofences:read, geofences:write.
| Metodo | Path | Scope |
|---|---|---|
GET | / | geofences:read |
POST | / | geofences:write |
GET | /{id}/ | geofences:read |
PATCH | /{id}/ | geofences:write |
DELETE | /{id}/ | geofences:write |
POST | /{id}/devices/ | geofences:write (solo scope=device) |
DELETE | /{id}/devices/{uid}/ | geofences:write |
Regole semantiche:
- Solo fence circolari in questa versione.
fence_type≠circle→ 400. center{lat, lng}obbligatorio per circle.radiusin metri,> 0e≤ 50 000.dwell_threshold_secondsrichiesto setrigger_on_dwell: true.- Regole
scope(validazione server-side):org— feature flaggeofence_scopingrichiesta;group/userdevono esserenull. Si applica a tutti i device attivi della org.group— non esposto ai partner (primitiva admin umana).user—userobbligatorio nella org;groupnull. Risolve via assegnazioni del device.device(default) —group/usernull. Si applica solo ai device linkati esplicitamente viaPOST /{id}/devices/. Lista vuota → fence non matcha nulla.
PATCHconsente cambio diname/description/center/radius/trigger_*/schedule/is_active. Non consente cambio discope/group/user.- Response list include
device_count. Response detail includedevices,schedulee i campi scope-dipendenti (group_id/user_id/...).
Soglie di allerta
Path base: /api/v1/alert-thresholds/.
| Metodo | Path | Scope |
|---|---|---|
GET | / | thresholds:read |
POST | / | thresholds:write |
GET | /{id}/ | thresholds:read |
PATCH | /{id}/ | thresholds:write |
DELETE | /{id}/ | thresholds:write |
Regole semantiche:
scopeenum integer:ORGANIZATION(10),DEVICE(15),USER(20).USER→userobbligatorio,devicenull.DEVICE→deviceobbligatorio,usernull.ORGANIZATION→ entrambi null.
metric_keyvalidato contro il catalogo telemetria — stesse chiavi dilast_status(vedi Dispositivi).low/high— almeno uno richiesto; se entrambi presenti,low ≤ high.- In response, enum integer sono serializzati come label stringa (
scope: "Organization",severity: "Warning",override_mode: "Replace").
Audit log
Path base: /api/v1/audit-log/. Scope: audit:read. Solo righe della propria org.
| Metodo | Path |
|---|---|
GET | / |
GET | /{id}/ |
Filtri: actor (UUID utente), actor_partner_integration (UUID), actor_type (partners/users/system), action (0=created, 1=updated, 2=deleted), content_type, model_name, timestamp_after, timestamp_before, search (su object_repr).
Note:
actor_type:partners→ scrittura via token partner →actor_partner_integrationpopolato.users→ scrittura umana →actorpopolato ({id, email, full_name}).system→ evento senza request-context (task automatici, migrazioni).
actor_partner_integration.deleted: trueindica snapshot conservato di integrazione cancellata.- Detail aggiunge raw
changes({field: [old, new]}) eadditional_data(metadati arbitrari). La lista espone solochanges_summaryderivato.
Org self
Path: /api/v1/organizations/self/. Scope: org:read. Solo partner auth — JWT umani ricevono 403.
Ritorna metadata della org: name, slug, timezone, default_locale, enabled_features (solo feature truthy), integration_status ("Active" per token validi), rate_limits (per_minute, per_hour).
Inviti
Path base: /api/v1/organizations/invitations/. Gate: feature flag managed_onboarding sulla org del partner.
| Metodo | Path | Scope |
|---|---|---|
GET | / | invitations:read |
GET | /{id}/ | invitations:read |
DELETE | /{id}/ | invitations:write (soft-delete) |
POST | /{id}/revoke/ | invitations:write |
POST | /server-accept/ | invitations:write (vedi Assegnazioni) |
Note:
- La creazione di inviti generici (
POST /) è riservata al flow umano. Il partner crea share viaPOST /api/v1/devices/{uid}/share/(vedi Assegnazioni). - Il campo
metadata(che contienedevice_uidper inviti share) non è esposto in response. Per ricavare il device target, il partner intercetta il token nell'email e chiama/server-accept/(vedi Share device).
Catalogo device
Path: /api/v1/protocols/, /api/v1/models/. Scope: catalog:read. Reference data read-only, non tenant-scoped.
| Metodo | Path | Contenuto |
|---|---|---|
GET | /api/v1/protocols/ | Lista protocolli |
GET | /api/v1/protocols/{slug}/ | Dettaglio protocollo |
GET | /api/v1/models/ | Modelli device cross-protocollo |
GET | /api/v1/protocols/{slug}/models/ | Modelli per protocollo |
GET | /api/v1/protocols/{slug}/models/{model_slug}/ | Dettaglio modello |
GET | /api/v1/protocols/{slug}/models/{model_slug}/capabilities/ | Capability del modello |
GET | /api/v1/devices/{uid}/capabilities/ | Capability risolte per il singolo device (override inclusi) |
Use case: popolare dropdown nella UI client ("scegli modello al registro device"); determinare quali command_type / metriche telemetria accetta un device dato.