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"
} | Status | Znaczenie |
|---|---|
created | Wiersz sesji istnieje; nikt jeszcze nie dołączył. |
open | Użytkownik terenowy dołączył; sesja jest aktywna. |
recording | Nagrywanie w toku (opcjonalne, wyzwalane przez operatora). |
closed | Sesja zakończona. Głowica łańcucha zakotwiczona w TSA; raporty dostępne. |
expired | Zaplanowana 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
| Pole | Typ | Wymagane | Uwagi |
|---|---|---|---|
notes | string | nie | Widoczne dla operatora. Wyświetlane w emailach z zaproszeniem. |
scheduled_for | ISO 8601 | nie | Przyszła data wyzwala emaile z przypomnieniem 24h i 1h wcześniej. Pomiń dla „rozpocznij teraz”. |
locale | string | nie | Jedna z 14 obsługiwanych lokalizacji. Steruje językiem SPA i raportu PDF. Domyślnie preferencja organizacji. |
campaign | UUID | nie | Opcjonalny 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_code są wyś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+ bezrecipient_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}:
| Status | Treść | 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
| Status | Kod | Kiedy |
|---|---|---|
| 402 | billing.subscription_past_due | Subskrypcja Stripe organizacji jest przeterminowana. |
| 402 | billing.free_plan_minutes_exhausted | Poziom Free / Pilot wykorzystał swoje 5 inspekcji. |
| 403 | permission_denied | Poświadczenie nie posiada sessions:write zakres. |
| 409 | session.already_ended | Próba zakończenia sesji, która jest już zamknięta (rzadkie — `end` jest zwykle idempotentne). |
| 429 | rate_limited | Osią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.