API Sesiuni
O Sesiune este o inspecție. Creați una, generați o invitație pentru utilizatorul de teren, capturați probe, încheiați-o. Tot restul se sprijină pe această resursă.
Obiectul Session
{
"id": "0c8f4d2e-1a3b-4c5d-9e7f-1234567890ab",
"status": "open",
"operator_email": "ops@yourco.com",
"scheduled_for": "2026-05-23T10:00:00Z",
"started_at": "2026-05-23T10:00:14Z",
"ended_at": null,
"notes": "Vehicle damage — claim CL-2026-0042",
"locale": "fr",
"consent_state": { "camera": "granted", "gps": "granted" },
"campaign": null,
"created_at": "2026-05-21T14:21:00Z",
"updated_at": "2026-05-23T10:00:14Z"
} | Stare | Semnificație |
|---|---|
created | Rândul sesiunii există; nimeni nu s-a alăturat încă. |
open | Utilizatorul de teren s-a alăturat; sesiunea este live. |
recording | Înregistrare în curs (opțională, declanșată de operator). |
closed | Sesiune încheiată. Capul lanțului ancorat la TSA; rapoarte disponibile. |
expired | Sesiune planificată la care nimeni nu s-a alăturat în timpul TTL. |
Creați o sesiune
POST /api/v1/public/sessions — permisiune sessions:write
curl -X POST https://app.nexbasira.com/api/v1/public/sessions \
-H "Authorization: Bearer nb_sec_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"notes": "Vehicle damage — claim CL-2026-0042",
"scheduled_for": "2026-05-23T10:00:00Z",
"locale": "fr"
}' Returnează obiectul Session nou creat (HTTP 201).
Câmpuri ale corpului
| Câmp | Tip | Obligatoriu | Note |
|---|---|---|---|
notes | string | nu | Vizibil pentru operator. Afișat în e-mailurile de invitație. |
scheduled_for | ISO 8601 | nu | O dată viitoare declanșează e-mailuri de reamintire cu 24h + 1h înainte. Omiteți pentru „start acum”. |
locale | string | nu | Una dintre cele 14 locale suportate. Determină limba SPA + a raportului PDF. Implicit, preferința organizației. |
campaign | UUID | nu | FK opțional către o Campanie pentru raportare grupată. |
Listați sesiunile
GET /api/v1/public/sessions — permisiune sessions:read
curl https://app.nexbasira.com/api/v1/public/sessions?limit=25 \
-H "Authorization: Bearer nb_sec_..." Paginat prin cursor. Transmiteți cursor cu next_cursor din răspunsul anterior pentru a naviga între pagini.
{
"data": [{ /* Session, Session, ... */ }],
"has_more": true,
"next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAy..."
} Obțineți o sesiune
GET /api/v1/public/sessions/{session_id} — permisiune sessions:read
Încheiați o sesiune
POST /api/v1/public/sessions/{session_id}/end — permisiune sessions:write
Închide sesiunea, declanșează ancorarea capului de lanț la toate TSA-urile configurate și pornește postprocesarea înregistrării dacă rula o înregistrare. Idempotent — apelarea pe o sesiune deja închisă returnează obiectul Session închis fără a reancora.
Generați o invitație pentru utilizatorul de teren
POST /api/v1/public/sessions/{session_id}/participants — permisiune participants:write
curl -X POST https://app.nexbasira.com/api/v1/public/sessions/0c8f.../participants \
-H "Authorization: Bearer nb_sec_..." \
-H "Content-Type: application/json" \
-d '{
"recipient_first_name": "Alex",
"recipient_last_name": "Garcia",
"recipient_email": "alex@policyholder.com",
"send_email": true,
"ttl_minutes": 1440
}' {
"id": "i-1",
"session": "0c8f...",
"role": "field",
"expires_at": "2026-05-24T10:00:00Z",
"recipient_first_name": "Alex",
"recipient_last_name": "Garcia",
"recipient_email": "alex@policyholder.com",
"recipient_phone": "",
"join_url": "https://app.nexbasira.com/join/0c8f.../?t=tok_PLAINTEXT_ONCE",
"otp_code": "487192",
"otp_required": true,
"otp_expires_at": "2026-05-23T10:10:00Z",
"created_at": "2026-05-23T10:00:00Z"
} Atât join_url cât și otp_code sunt afișate exact o dată în răspuns. Token-urile sunt legate de IP/UA, de unică folosință și limitate în timp.
Alăturare cu doi factori (OTP)
Când furnizați cel puțin unul dintre recipient_email sau recipient_phone, platforma generează automat un OTP numeric din 6 cifre și îl trimite pe canalul (canalele) corespunzător(oare) într-un mesaj separat de URL-ul de alăturare — apărare în profunzime, astfel încât un e-mail sau SMS redirecționat să nu dezvăluie ambii factori deodată. Codul în clar este de asemenea returnat în răspuns ( otp_code) ca să îl puteți re-partaja manual dacă livrarea eșuează.
Pe partea de teren, SPA afișează solicitarea OTP la prima utilizare. Trimiteți codul prin antetul X-Join-OTP la o reîncercare a GET /v1/sessions/{id}/join/{token} — antetul (nu URL-ul) ține codul departe de istoricul browserului și de jurnalele de acces.
Reguli OTP:
- Numeric din 6 cifre, hash-uit cu SHA-256 + pepper în repaus.
- TTL de 10 minute de la emitere.
- 5 încercări greșite blochează invitația (HTTP 423) — operatorul trebuie să reemită.
- Verificat o dată la prima utilizare; reutilizarea de la aceeași pereche IP / UA sare peste verificare (token-ul este deja legat).
- Predarea URL-ului față în față (fără
recipient_email+ fărărecipient_phone) sare peste generarea OTP — doar URL-ul este factorul de autentificare. Folosiți asta doar pentru predări în persoană.
Coduri de răspuns pentru GET /v1/sessions/{id}/join/{token}:
| Stare | Corp | Semnificație |
|---|---|---|
| 200 | {field_session_token, livekit, ...} | OTP a trecut (sau nu este necesar); sesiunea de teren este live. |
| 401 | {detail:"otp_required", channels:[...], channel_hint_email, channel_hint_phone} | SPA ar trebui să afișeze formularul de introducere a OTP. |
| 401 | {detail:"otp_invalid", attempts_remaining} | Cod greșit; afișați încercările rămase. |
| 401 | {detail:"otp_expired"} | Fereastra de 10 min a expirat; operatorul trebuie să reemită. |
| 423 | {detail:"otp_locked"} | 5 încercări greșite; invitația este moartă până la reemitere. |
Erori frecvente
| Stare | Cod | Când |
|---|---|---|
| 402 | billing.subscription_past_due | Abonamentul Stripe al organizației are plata restantă. |
| 402 | billing.free_plan_minutes_exhausted | Nivelul Gratuit / Pilot și-a folosit cele 5 inspecții. |
| 403 | permission_denied | Credențialul nu are sessions:write permisiune. |
| 409 | session.already_ended | Încercare de a încheia o sesiune deja închisă (rar — `end` este de obicei idempotent). |
| 429 | rate_limited | Limită de 60-rpm per credențial sau 600-rpm per organizație atinsă. Vedeți antetul X-RateLimit-Reset . |
Vedeți Erori + limite de rată pentru forma completă a plicului de eroare și ghidul de reîncercare.