LIVE · AUDIT-KEDJA · EU-VÄRD
SYSTEM · 99,99 % DRIFTSTID
v 1.0 ↗ TILLVERKAT I EU

Sessions-API

En Session är en inspektion. Skapa en, utfärda en inbjudan till fältanvändare, fånga bevis, avsluta den. Allt annat hänger på denna resurs.

Session-objektet

{
  "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"
}
StatusBetydelse
createdSessionsraden finns; ingen har anslutit ännu.
openFältanvändaren har anslutit; sessionen är live.
recordingInspelning pågår (valfritt, utlöst av operatören).
closedSessionen avslutad. Kedjehuvudet förankrat hos TSA; rapporter tillgängliga.
expiredSchemalagd session som ingen anslöt till inom TTL:en.

Skapa en session

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"
  }'

Returnerar det nyss skapade Session-objektet (HTTP 201).

Body-fält

FältTypObligatorisktAnteckningar
notesstringnejSynligt för operatören. Visas i inbjudningsmejl.
scheduled_forISO 8601nejEtt framtida datum utlöser påminnelsemejl 24h + 1h innan. Utelämna för "starta nu".
localestringnejEn av de 14 språk som stöds. Styr språket i SPA:n + PDF-rapporten. Faller tillbaka på organisationens inställning.
campaignUUIDnejValfri FK till en Campaign för batchad rapportering.

Lista sessioner

GET /api/v1/public/sessions — scope sessions:read

curl https://app.nexbasira.com/api/v1/public/sessions?limit=25 \
  -H "Authorization: Bearer nb_sec_..."

Markörpaginerat. Skicka cursor från föregående svars next_cursor för att bläddra.

{
  "data": [{ /* Session, Session, ... */ }],
  "has_more": true,
  "next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAy..."
}

Hämta en session

GET /api/v1/public/sessions/{session_id} — scope sessions:read

Avsluta en session

POST /api/v1/public/sessions/{session_id}/end — scope sessions:write

Stänger sessionen, utlöser förankringen av kedjehuvudet hos alla konfigurerade TSA:er och startar efterbearbetningen av inspelningen om en inspelning kördes. Idempotent — anrop på en redan stängd session returnerar det stängda Session-objektet utan att förankra på nytt.

Skapa en fältanvändarinbjudan

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

Fälten join_url och otp_code visas exakt en gång i svaret. Tokens är IP/UA-bundna, engångsbruk och tidsbegränsade.

Tvåfaktorsanslutning (OTP)

När du anger minst en av recipient_email eller recipient_phone skapar plattformen automatiskt en 6-siffrig numerisk OTP och skickar den på matchande kanal(er) i ett separat meddelande från anslutnings-URL:en — försvar på djupet, så att ett vidarebefordrat mejl eller SMS inte läcker båda faktorerna samtidigt. Den klartextkoden returneras också i svaret ( otp_code) så att du kan dela den manuellt igen om leveransen misslyckas.

På fältsidan visar SPA:n OTP-prompten vid första inlösen. Skicka koden via X-Join-OTP -headern i ett nytt försök av GET /v1/sessions/{id}/join/{token} — headern (inte URL:en) håller koden utanför webbläsarhistorik och åtkomstloggar.

OTP-regler:

  • 6-siffrig numerisk, hashad med SHA-256 + pepper i vila.
  • 10-minuters TTL från utfärdande.
  • 5 felaktiga försök låser inbjudan (HTTP 423) — operatören måste utfärda den på nytt.
  • Verifieras en gång vid första inlösen; ny inlösen från samma IP-/UA-par hoppar över spärren (token är redan bunden).
  • Överlämning av URL ansikte mot ansikte (ingen recipient_email + ingen recipient_phone) hoppar över OTP-skapandet — URL:en ensam är autentiseringsfaktorn. Använd detta enbart för överlämningar på plats.

Svarskoder på GET /v1/sessions/{id}/join/{token}:

StatusBodyBetydelse
200{field_session_token, livekit, ...}OTP godkänd (eller krävs inte); fältsessionen är live.
401{detail:"otp_required", channels:[...], channel_hint_email, channel_hint_phone}SPA:n bör visa OTP-inmatningsformuläret.
401{detail:"otp_invalid", attempts_remaining}Fel kod; visa återstående försök.
401{detail:"otp_expired"}10-minutersfönstret har löpt ut; operatören måste utfärda på nytt.
423{detail:"otp_locked"}5 felaktiga försök; inbjudan är död tills den utfärdas på nytt.

Vanliga fel

StatusKodNär
402billing.subscription_past_dueOrganisationens Stripe-prenumeration är förfallen.
402billing.free_plan_minutes_exhaustedFree-/Pilot-nivån har förbrukat sina 5 inspektioner.
403permission_deniedBehörigheten saknar sessions:write scope.
409session.already_endedFörsök att avsluta en session som redan är stängd (ovanligt — `end` är normalt idempotent).
429rate_limitedBegränsningen 60 rpm per behörighet eller 600 rpm per organisation nåddes. Se X-RateLimit-Reset -headern.

Se Fel + hastighetsgränser för hela felkuvertets form och riktlinjer för återförsök.