EN VIVO · CON AUDITORÍA · UE
SISTEMA · 99,99% UPTIME
v 1.0 ↗ HECHO EN UE

API de sesiones

Una Session es una inspección. Cree una, genere una invitación de usuario de campo, capture pruebas, finalícela. Todo lo demás depende de este recurso.

El 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
createdLa fila de la sesión existe; nadie se ha unido todavía.
openEl usuario de campo se ha unido; la sesión está en directo.
recordingGrabación en curso (opcional, iniciada por el operador).
closedSesión finalizada. Cabeza de la cadena anclada en la TSA; informes disponibles.
expiredSesión programada a la que nadie se unió dentro del TTL.

Crear una sesión

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

Devuelve el objeto Session recién creado (HTTP 201).

Campos del cuerpo

CampoTipoObligatorioNotas
notesstringnoVisible para el operador. Aparece en los correos de invitación.
scheduled_forISO 8601noUna fecha futura activa correos de recordatorio 24 h y 1 h antes. Omítalo para "empezar ahora".
localestringnoUno de los 14 idiomas admitidos. Determina el idioma de la SPA y del informe PDF. Por defecto usa la preferencia de la organización.
campaignUUIDnoFK opcional a una Campaign para informes por lotes.

Listar sesiones

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

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

Paginado por cursor. Pase cursor del next_cursor de la respuesta anterior para paginar.

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

Recuperar una sesión

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

Finalizar una sesión

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

Cierra la sesión, activa el anclaje de la cabeza de la cadena en todas las TSA configuradas e inicia el posprocesamiento de la grabación si había una grabación en curso. Idempotente — llamarlo en una sesión ya cerrada devuelve el objeto Session cerrado sin volver a anclar.

Generar una invitación de usuario de campo

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

El join_url y el otp_code se muestran exactamente una vez en la respuesta. Los tokens están fijados a IP/UA, son de un solo uso y tienen límite de tiempo.

Unión de dos factores (OTP)

Cuando proporciona al menos uno de recipient_email o recipient_phone, la plataforma genera automáticamente un OTP numérico de 6 dígitos y lo envía por el/los canal(es) correspondiente(s) en un mensaje separado de la URL de acceso — defensa en profundidad para que un correo o SMS reenviado no filtre ambos factores a la vez. El código en texto plano también se devuelve en la respuesta ( otp_code) para que pueda volver a compartirlo manualmente si la entrega falla.

En el lado de campo, la SPA muestra el aviso de OTP en el primer canje. Envíe el código mediante la X-Join-OTP cabecera en un reintento de GET /v1/sessions/{id}/join/{token} — la cabecera (no la URL) mantiene el código fuera del historial del navegador y de los registros de acceso.

Reglas del OTP:

  • Numérico de 6 dígitos, con hash SHA-256 + pepper en reposo.
  • TTL de 10 minutos desde la emisión.
  • 5 intentos incorrectos bloquean la invitación (HTTP 423) — el operador debe reemitirla.
  • Verificado una vez en el primer canje; volver a canjear desde el mismo par IP / UA omite la comprobación (el token ya está fijado).
  • Entrega de la URL en persona (sin recipient_email + sin recipient_phone) omite la generación del OTP — la URL por sí sola es el factor de autenticación. Use esto solo para entregas en persona.

Códigos de respuesta en GET /v1/sessions/{id}/join/{token}:

EstadoCuerpoSignificado
200{field_session_token, livekit, ...}OTP superado (o no requerido); la sesión de campo está en directo.
401{detail:"otp_required", channels:[...], channel_hint_email, channel_hint_phone}La SPA debería mostrar el formulario de entrada del OTP.
401{detail:"otp_invalid", attempts_remaining}Código incorrecto; muestra los intentos restantes.
401{detail:"otp_expired"}Ventana de 10 min transcurrida; el operador debe reemitir.
423{detail:"otp_locked"}5 intentos incorrectos; la invitación queda inactiva hasta la reemisión.

Errores comunes

EstadoCódigoCuándo
402billing.subscription_past_dueLa suscripción de Stripe de la organización está vencida.
402billing.free_plan_minutes_exhaustedEl nivel Free / Piloto ha agotado sus 5 inspecciones.
403permission_deniedLa credencial no tiene sessions:write alcance.
409session.already_endedIntentar finalizar una sesión que ya está cerrada (poco común — `end` normalmente es idempotente).
429rate_limitedSe alcanzó el límite de 60 rpm por credencial o 600 rpm por organización. Consulte la cabecera X-RateLimit-Reset .

Consulte Errores y límites de tasa para la forma completa del sobre de error y la guía de reintentos.