LIVE · AUDIT-KÆDE · EU-HOSTET
SYSTEM · 99,99 % OPPETID
v 1.0 ↗ FREMSTILLET I EU

Sessions API

En Session er én inspektion. Opret en, præg en feltbruger-invitation, opsaml beviser, afslut den. Alt andet hænger på denne ressource.

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"
}
StatusBetydning
createdSessionsrækken findes; ingen har tilsluttet sig endnu.
openFeltbrugeren har tilsluttet sig; sessionen er live.
recordingOptagelse i gang (valgfri, operatør-udløst).
closedSessionen er afsluttet. Kædens hoved forankret hos TSA; rapporter tilgængelige.
expiredPlanlagt session, som ingen tilsluttede sig inden for TTL'en.

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

Returnerer det netop oprettede Session-objekt (HTTP 201).

Body-felter

FeltTypePåkrævetNoter
notesstringnejSynlig for operatøren. Vises i invitations-e-mails.
scheduled_forISO 8601nejEn fremtidig dato udløser påmindelses-e-mails 24 t + 1 t før. Udelad for "start nu".
localestringnejEn af de 14 understøttede locales. Styrer sproget for SPA'en + PDF-rapporten. Falder tilbage til organisationens præference.
campaignUUIDnejValgfri FK til en Campaign for samlet rapportering.

List 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_..."

Cursor-pagineret. Send cursor fra det forrige svars next_cursor for at paginere.

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

Hent en session

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

Afslut en session

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

Lukker sessionen, udløser forankring af kædens hoved hos alle konfigurerede TSA'er og starter efterbehandling af optagelsen, hvis en optagelse kørte. Idempotent — et kald på en allerede lukket session returnerer det lukkede Session-objekt uden at forankre igen.

Præg en feltbruger-invitation

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

Både join_url og otp_code vises præcis én gang i svaret. Tokens er IP/UA-bundne, engangsbrug og tidsbegrænsede.

To-faktor-tilslutning (OTP)

Når du angiver mindst én af recipient_email eller recipient_phone, præger platformen automatisk en 6-cifret numerisk OTP og sender den på de(n) matchende kanal(er) i en separat besked adskilt fra tilslutnings-URL'en — defence-in-depth, så en videresendt e-mail eller SMS ikke lækker begge faktorer på én gang. Den rå kode returneres også i svaret ( otp_code) så du kan dele den manuelt igen, hvis leveringen fejler.

På feltsiden viser SPA'en OTP-prompten ved første indløsning. Indsend koden via X-Join-OTP -headeren ved et gentaget forsøg på GET /v1/sessions/{id}/join/{token} — headeren (ikke URL'en) holder koden ude af browserhistorik og adgangslogs.

OTP-regler:

  • 6-cifret numerisk, hashet med SHA-256 + pepper i hvile.
  • 10-minutters TTL fra udstedelse.
  • 5 forkerte forsøg låser invitationen (HTTP 423) — operatøren skal genudstede.
  • Verificeres én gang ved første indløsning; genindløsning fra samme IP/UA-par springer kontrollen over (tokenet er allerede bundet).
  • Ansigt-til-ansigt-URL-overdragelse (ingen recipient_email + ingen recipient_phone) springer OTP-prægning over — URL'en alene er autentifikationsfaktoren. Brug kun dette til personlige overdragelser.

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

StatusBodyBetydning
200{field_session_token, livekit, ...}OTP bestået (eller ikke påkrævet); feltsessionen er live.
401{detail:"otp_required", channels:[...], channel_hint_email, channel_hint_phone}SPA'en skal vise OTP-indtastningsformularen.
401{detail:"otp_invalid", attempts_remaining}Forkert kode; vis resterende forsøg.
401{detail:"otp_expired"}10-minutters-vinduet er udløbet; operatøren skal genudstede.
423{detail:"otp_locked"}5 forkerte forsøg; invitationen er død, indtil den genudstedes.

Almindelige fejl

StatusKodeHvornår
402billing.subscription_past_dueOrganisationens Stripe-abonnement er forfaldent.
402billing.free_plan_minutes_exhaustedGratis-/Pilot-niveauet har brugt sine 5 inspektioner.
403permission_deniedLegitimationen mangler sessions:write scope.
409session.already_endedForsøg på at afslutte en session, der allerede er lukket (sjældent — `end` er normalt idempotent).
429rate_limitedGrænsen på 60 rpm pr. legitimation eller 600 rpm pr. organisation er nået. Se X-RateLimit-Reset -headeren.

Se Fejl + rate limits for den fulde fejlkonvolut-struktur og vejledning om genforsøg.