AO VIVO · AUDIT CHAIN · UE
SISTEMA · 99,99% DISPONIBILIDADE
v 1.0 ↗ FEITO NA UE

API de Sessões

Uma Sessão é uma inspeção. Crie uma, emita um convite de utilizador de terreno, capture provas, termine-a. Tudo o resto depende deste recurso.

O objeto 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"
}
EstadoSignificado
createdA linha da sessão existe; ninguém entrou ainda.
openO utilizador de terreno entrou; a sessão está em direto.
recordingGravação em curso (opcional, acionada pelo operador).
closedSessão terminada. Topo da cadeia ancorado na TSA; relatórios disponíveis.
expiredSessão agendada em que ninguém entrou dentro do TTL.

Criar uma sessão

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

Devolve o objeto Session acabado de criar (HTTP 201).

Campos do corpo

CampoTipoObrigatórioNotas
notesstringnãoVisível para o operador. Mostrado nos emails de convite.
scheduled_forISO 8601nãoUma data futura aciona emails de lembrete 24h + 1h antes. Omita para "começar agora".
localestringnãoUm dos 14 locales suportados. Determina a língua da SPA + do relatório PDF. Assume por defeito a preferência da organização.
campaignUUIDnãoFK opcional para uma Campaign para relatórios em lote.

Listar sessões

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

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

Paginado por cursor. Passe cursor da next_cursor da resposta anterior para paginar.

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

Obter uma sessão

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

Terminar uma sessão

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

Fecha a sessão, aciona a ancoragem do topo da cadeia em todas as TSAs configuradas e arranca o pós-processamento da gravação se estava a decorrer uma gravação. Idempotente — chamar numa sessão já fechada devolve o objeto Session fechado sem voltar a ancorar.

Emitir um convite de utilizador de terreno

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

O join_url e o otp_code são mostrados uma única vez na resposta. Os tokens são fixados por IP/UA, de uso único e limitados no tempo.

Entrada de dois fatores (OTP)

Quando fornece pelo menos um de recipient_email ou recipient_phone, a plataforma emite automaticamente um OTP numérico de 6 dígitos e envia-o no(s) canal(is) correspondente(s) numa mensagem separada do URL de entrada — defesa em profundidade para que um email ou SMS reencaminhado não deixe vazar os dois fatores de uma só vez. O código simples é também devolvido na resposta ( otp_code) para que o possa voltar a partilhar manualmente se a entrega falhar.

Do lado do terreno, a SPA apresenta o prompt de OTP na primeira redenção. Submeta o código via o cabeçalho X-Join-OTP numa retentativa de GET /v1/sessions/{id}/join/{token} — o cabeçalho (não o URL) mantém o código fora do histórico do navegador e dos logs de acesso.

Regras do OTP:

  • Numérico de 6 dígitos, com hash SHA-256 + pepper em repouso.
  • TTL de 10 minutos a partir da emissão.
  • 5 tentativas erradas bloqueiam o convite (HTTP 423) — o operador tem de reemitir.
  • Verificado uma vez na primeira redenção; a re-redenção do mesmo par IP / UA salta a barreira (o token já está fixado).
  • A entrega presencial do URL (sem recipient_email + sem recipient_phone) salta a emissão do OTP — só o URL é o fator de autenticação. Use isto apenas para entregas presenciais.

Códigos de resposta em GET /v1/sessions/{id}/join/{token}:

EstadoCorpoSignificado
200{field_session_token, livekit, ...}OTP validado (ou não obrigatório); a sessão de terreno está em direto.
401{detail:"otp_required", channels:[...], channel_hint_email, channel_hint_phone}A SPA deve renderizar o formulário de introdução do OTP.
401{detail:"otp_invalid", attempts_remaining}Código errado; mostre as tentativas restantes.
401{detail:"otp_expired"}A janela de 10 min decorreu; o operador tem de reemitir.
423{detail:"otp_locked"}5 tentativas erradas; o convite está morto até nova emissão.

Erros comuns

EstadoCódigoQuando
402billing.subscription_past_dueA subscrição Stripe da organização está em atraso.
402billing.free_plan_minutes_exhaustedO escalão Free / Pilot usou as suas 5 inspeções.
403permission_deniedA credencial não tem sessions:write scope.
409session.already_endedTentar terminar uma sessão que já está fechada (raro — `end` é normalmente idempotente).
429rate_limitedThrottle de 60 rpm por credencial ou de 600 rpm por organização atingido. Ver X-RateLimit-Reset cabeçalho.

Ver Erros + limites de taxa para a forma completa do envelope de erro e orientação sobre retentativas.