NA ŻYWO · ŁAŃCUCH AUDYTU · UE
SYSTEM · 99,99% DOSTĘPNOŚĆ
v 1.0 ↗ WYPRODUKOWANO W UE

API Sesji

Sesja to jedna inspekcja. Utwórz ją, wygeneruj zaproszenie dla użytkownika terenowego, zbierz materiał dowodowy, zakończ ją. Wszystko inne zależy od tego zasobu.

Obiekt 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"
}
StatusZnaczenie
createdWiersz sesji istnieje; nikt jeszcze nie dołączył.
openUżytkownik terenowy dołączył; sesja jest aktywna.
recordingNagrywanie w toku (opcjonalne, wyzwalane przez operatora).
closedSesja zakończona. Głowica łańcucha zakotwiczona w TSA; raporty dostępne.
expiredZaplanowana sesja, do której nikt nie dołączył w ramach TTL.

Utwórz sesję

POST /api/v1/public/sessions — zakres 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"
  }'

Zwraca świeżo utworzony obiekt Session (HTTP 201).

Pola treści

PoleTypWymaganeUwagi
notesstringnieWidoczne dla operatora. Wyświetlane w emailach z zaproszeniem.
scheduled_forISO 8601niePrzyszła data wyzwala emaile z przypomnieniem 24h i 1h wcześniej. Pomiń dla „rozpocznij teraz”.
localestringnieJedna z 14 obsługiwanych lokalizacji. Steruje językiem SPA i raportu PDF. Domyślnie preferencja organizacji.
campaignUUIDnieOpcjonalny FK do Kampanii na potrzeby raportowania wsadowego.

Listuj sesje

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

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

Paginacja kursorowa. Przekaż cursor z pola next_cursor poprzedniej odpowiedzi, aby stronicować.

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

Pobierz sesję

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

Zakończ sesję

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

Zamyka sesję, wyzwala zakotwiczenie głowicy łańcucha we wszystkich skonfigurowanych TSA oraz uruchamia post-processing nagrania, jeśli nagrywanie było w toku. Idempotentne — wywołanie na już zamkniętej sesji zwraca zamknięty obiekt Session bez ponownego zakotwiczania.

Wygeneruj zaproszenie dla użytkownika terenowego

POST /api/v1/public/sessions/{session_id}/participants — zakres 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"
}

Pola join_url oraz otp_codewyświetlane dokładnie raz w odpowiedzi. Tokeny są powiązane z IP/UA, jednorazowe i ograniczone czasowo.

Dołączanie dwuskładnikowe (OTP)

Gdy podasz co najmniej jedno z recipient_email lub recipient_phone, platforma automatycznie generuje 6-cyfrowy numeryczny OTP i wysyła go na pasującym kanale/kanałach w oddzielnej wiadomości od URL dołączenia — obrona w głąb, tak aby przekazany dalej email lub SMS nie ujawnił obu czynników naraz. Kod w postaci jawnej jest również zwracany w odpowiedzi ( otp_code), abyś mógł go ponownie udostępnić ręcznie, jeśli dostarczenie zawiedzie.

Po stronie terenowej SPA wyświetla monit OTP przy pierwszej realizacji. Prześlij kod za pomocą nagłówka X-Join-OTP przy ponowieniu GET /v1/sessions/{id}/join/{token} — nagłówek (nie URL) utrzymuje kod poza historią przeglądarki i logami dostępu.

Reguły OTP:

  • 6-cyfrowy numeryczny, hashowany SHA-256 + pepper w spoczynku.
  • 10-minutowy TTL od wystawienia.
  • 5 błędnych prób blokuje zaproszenie (HTTP 423) — operator musi wystawić je ponownie.
  • Weryfikowany raz przy pierwszej realizacji; ponowna realizacja z tej samej pary IP / UA pomija bramkę (token jest już powiązany).
  • Przekazanie URL twarzą w twarz (bez recipient_email + bez recipient_phone) pomija generowanie OTP — sam URL jest czynnikiem uwierzytelniającym. Używaj tego wyłącznie przy przekazaniach osobistych.

Kody odpowiedzi na GET /v1/sessions/{id}/join/{token}:

StatusTreśćZnaczenie
200{field_session_token, livekit, ...}OTP zaliczony (lub niewymagany); sesja terenowa jest aktywna.
401{detail:"otp_required", channels:[...], channel_hint_email, channel_hint_phone}SPA powinno wyrenderować formularz wprowadzania OTP.
401{detail:"otp_invalid", attempts_remaining}Błędny kod; pokaż pozostałe próby.
401{detail:"otp_expired"}Upłynęło okno 10 min; operator musi wystawić ponownie.
423{detail:"otp_locked"}5 błędnych prób; zaproszenie jest martwe do czasu ponownego wystawienia.

Częste błędy

StatusKodKiedy
402billing.subscription_past_dueSubskrypcja Stripe organizacji jest przeterminowana.
402billing.free_plan_minutes_exhaustedPoziom Free / Pilot wykorzystał swoje 5 inspekcji.
403permission_deniedPoświadczenie nie posiada sessions:write zakres.
409session.already_endedPróba zakończenia sesji, która jest już zamknięta (rzadkie — `end` jest zwykle idempotentne).
429rate_limitedOsiągnięto limit 60 rpm per poświadczenie lub 600 rpm per organizacja. Zobacz nagłówek X-RateLimit-Reset .

Zobacz Błędy + limity zapytań aby poznać pełny kształt koperty błędu i wskazówki dotyczące ponawiania.