Sessions API
Een Session is één inspectie. Maak er een, genereer een veldgebruiker-uitnodiging, leg bewijs vast, beëindig hem. Al het andere hangt aan deze resource.
Het Session-object
{
"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"
} | Status | Betekenis |
|---|---|
created | Session-rij bestaat; nog niemand is binnengekomen. |
open | Veldgebruiker is binnengekomen; sessie is live. |
recording | Opname bezig (optioneel, door operator gestart). |
closed | Sessie beëindigd. Ketenkop verankerd bij TSA; rapporten beschikbaar. |
expired | Geplande sessie waar niemand binnen de TTL is binnengekomen. |
Een sessie aanmaken
POST /api/v1/public/sessions — scope 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"
}' Retourneert het zojuist aangemaakte Session-object (HTTP 201).
Body-velden
| Veld | Type | Vereist | Opmerkingen |
|---|---|---|---|
notes | string | nee | Zichtbaar voor de operator. Weergegeven in uitnodigingsmails. |
scheduled_for | ISO 8601 | nee | Toekomstige datum activeert herinneringsmails 24u + 1u van tevoren. Weglaten voor "nu starten". |
locale | string | nee | Een van de 14 ondersteunde locales. Bepaalt de taal van de SPA + het PDF-rapport. Standaard de voorkeur van de org. |
campaign | UUID | nee | Optionele FK naar een Campaign voor gebundelde rapportage. |
Sessies lijsten
GET /api/v1/public/sessions — scope sessions:read
curl https://app.nexbasira.com/api/v1/public/sessions?limit=25 \
-H "Authorization: Bearer nb_sec_..." Cursor-gepagineerd. Geef cursor uit de vorige response's next_cursor mee om te pagineren.
{
"data": [{ /* Session, Session, ... */ }],
"has_more": true,
"next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAy..."
} Een sessie ophalen
GET /api/v1/public/sessions/{session_id} — scope sessions:read
Een sessie beëindigen
POST /api/v1/public/sessions/{session_id}/end — scope sessions:write
Sluit de sessie, activeert de ketenkopverankering bij alle geconfigureerde TSA's, en start de nabewerking van de opname als er een opname liep. Idempotent — aanroepen op een reeds gesloten sessie retourneert het gesloten Session-object zonder opnieuw te verankeren.
Een veldgebruiker-uitnodiging genereren
POST /api/v1/public/sessions/{session_id}/participants — scope 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"
} De join_url en otp_code worden precies één keer getoond in de response. Tokens zijn IP/UA-gebonden, eenmalig en in de tijd begrensd.
Tweefactor-join (OTP)
Wanneer u ten minste een van recipient_email of recipient_phone opgeeft, genereert het platform automatisch een 6-cijferige numerieke OTP en verstuurt die op de bijbehorende kana(a)l(en) in een apart bericht dan de join-URL — defence-in-depth zodat een doorgestuurde e-mail of sms niet beide factoren tegelijk lekt. De platte code wordt ook geretourneerd in de response ( otp_code) zodat u die handmatig opnieuw kunt delen als bezorging mislukt.
Aan de veldkant toont de SPA de OTP-prompt bij de eerste inwisseling. Dien de code in via de X-Join-OTP header bij een retry van GET /v1/sessions/{id}/join/{token} — de header (niet de URL) houdt de code buiten de browsergeschiedenis en access logs.
OTP-regels:
- 6-cijferig numeriek, in rust gehasht met SHA-256 + pepper.
- TTL van 10 minuten vanaf afgifte.
- 5 foute pogingen vergrendelen de uitnodiging (HTTP 423) — operator moet opnieuw uitgeven.
- Eenmalig geverifieerd bij de eerste inwisseling; herinwisseling vanaf hetzelfde IP-/UA-paar slaat de gate over (het token is al gebonden).
- Face-to-face URL-overdracht (geen
recipient_email+ geenrecipient_phone) slaat OTP-generatie over — de URL alleen is de auth-factor. Gebruik dit alleen voor persoonlijke overdrachten.
Response-codes op GET /v1/sessions/{id}/join/{token}:
| Status | Body | Betekenis |
|---|---|---|
| 200 | {field_session_token, livekit, ...} | OTP geslaagd (of niet vereist); veldsessie is live. |
| 401 | {detail:"otp_required", channels:[...], channel_hint_email, channel_hint_phone} | SPA moet het OTP-invoerformulier tonen. |
| 401 | {detail:"otp_invalid", attempts_remaining} | Foute code; toon resterende pogingen. |
| 401 | {detail:"otp_expired"} | Venster van 10 min verstreken; operator moet opnieuw uitgeven. |
| 423 | {detail:"otp_locked"} | 5 foute pogingen; uitnodiging is dood tot heruitgave. |
Veelvoorkomende fouten
| Status | Code | Wanneer |
|---|---|---|
| 402 | billing.subscription_past_due | Stripe-abonnement van de org is achterstallig. |
| 402 | billing.free_plan_minutes_exhausted | Gratis / Pilot-niveau heeft zijn 5 inspecties gebruikt. |
| 403 | permission_denied | Credential mist sessions:write scope. |
| 409 | session.already_ended | Poging om een sessie te beëindigen die al gesloten is (zeldzaam — `end` is normaal idempotent). |
| 429 | rate_limited | 60-rpm per-credential- of 600-rpm per-org-throttle bereikt. Zie X-RateLimit-Reset header. |
Zie Fouten + rate limits voor de volledige vorm van de error-envelope en retry-richtlijnen.