Skip to main content

Documentation Index

Fetch the complete documentation index at: https://wiki.vivla.com/llms.txt

Use this file to discover all available pages before exploring further.

Integración con vivla-mobile

La app mobile de Vivla (vivla-mobile) consume endpoints específicos de este backend para ofrecer chat de soporte a los huéspedes. Estos endpoints están bajo /api/chat/mobile/ y manejan autenticación, tokens de Stream Chat y gestión de perfil.
El chat en vivla-mobile no usa el backend principal de Vivla. Todos los endpoints de chat se sirven desde este backend (Tools API).

Flujo de autenticación

┌─────────────┐     ┌───────────────┐     ┌──────────────┐
│ vivla-mobile │────▶│  Tools API    │────▶│  Stream Chat │
│              │     │  /chat/mobile │     │              │
└─────────────┘     └───────────────┘     └──────────────┘
       │                    │
       │  authToken +       │  Genera
       │  userId            │  streamToken
       │                    │  (1h expiry)
       ▼                    ▼
┌─────────────┐     ┌───────────────┐
│vivla-backend│     │   Supabase    │
│ (auth orig.)│     │  (users DB)   │
└─────────────┘     └───────────────┘
  1. La app mobile obtiene un authToken del backend principal de Vivla
  2. Envía authToken + userId al endpoint de login de Tools API
  3. Tools API valida el usuario y verifica que tenga acceso al chat (chat_enabled)
  4. Si tiene acceso, genera un token de Stream Chat con expiración de 1 hora
  5. La app usa el streamToken para conectarse directamente a Stream Chat

Endpoints

Login

POST /api/chat/mobile/auth/login
Autentica al usuario mobile y retorna un token de Stream Chat. Request:
{
  "authToken": "token-del-backend-principal",
  "userId": "vivla-user-id"
}
Respuestas posibles:
{
  "hasAccess": true,
  "streamUserId": "stream-user-id",
  "streamToken": "eyJ...",
  "expiresAt": "2025-01-15T12:00:00Z",
  "user": {
    "id": "uuid",
    "firstName": "Juan",
    "lastName": "Pérez",
    "email": "juan@example.com"
  }
}

Refresh token

POST /api/chat/mobile/auth/refresh
Renueva el token de Stream Chat. Debe llamarse antes de que expire (1 hora). Request:
{
  "authToken": "token-del-backend-principal",
  "userId": "vivla-user-id"
}
Response:
{
  "streamToken": "eyJ...",
  "expiresAt": "2025-01-15T13:00:00Z",
  "streamUserId": "stream-user-id"
}

Actualizar perfil

PATCH /api/chat/mobile/profile
Actualiza el perfil del usuario y sincroniza los cambios con Stream Chat (nombre y avatar). Request:
{
  "authToken": "token-del-backend-principal",
  "userId": "vivla-user-id",
  "firstName": "Juan",
  "lastName": "Pérez"
}

Crear invitación

POST /api/chat/mobile/invitations
Crea una invitación a un canal de chat con un deep link para compartir. Response:
{
  "id": "uuid",
  "streamChannelId": "channel-id",
  "status": "pending",
  "expiresAt": "2025-01-20T00:00:00Z",
  "deepLink": "vivla://chat/invitation/token-uuid"
}

Obtener información de invitación

GET /api/chat/mobile/invitations/:token
Endpoint público (sin autenticación). Permite previsualizar un canal antes de aceptar la invitación. Response:
{
  "channel": {
    "id": "uuid",
    "name": "Canal de soporte",
    "type": "support"
  },
  "inviter": {
    "name": "Agente Vivla",
    "avatar": "https://..."
  }
}

Endpoints de Surveys (Mobile)

La app mobile también consume endpoints de encuestas bajo /api/surveys/mobile/. Estos endpoints usan el mismo MobileAuthGuard para POST y son públicos para GET.

Obtener encuesta activa

GET /api/surveys/mobile/:slug
Retorna la definición completa de la encuesta activa para el slug dado (ej: home-review). Público, sin autenticación. Soporta ?lang=es para resolución de i18n.

Guardar respuesta parcial

POST /api/surveys/mobile/:slug/responses
Guarda o actualiza una respuesta parcial. La app guarda localmente (MMKV) y sincroniza al backend por step y al salir. Request:
{
  "authToken": "token-del-backend-principal",
  "userId": "vivla-user-id",
  "survey_id": "uuid-de-la-version",
  "scope_id": "home-id-o-booking-id",
  "status": "in_progress",
  "current_step": "step_2",
  "current_question": "kitchen_rating",
  "answers": {
    "general_rating": { "value": 4 },
    "kitchen_rating": { "value": 2 }
  }
}

Completar encuesta

POST /api/surveys/mobile/:slug/responses/complete
Marca la encuesta como completada y otorga automáticamente reward points. Una vez completada, la respuesta es inmutable.

Reanudar respuesta

POST /api/surveys/mobile/:slug/responses/resume
Retorna la respuesta parcial existente. Es POST (no GET) porque el MobileAuthGuard necesita leer authToken y userId del body. Response:
{
  "id": "uuid",
  "survey_id": "uuid",
  "status": "in_progress",
  "current_step": "step_2",
  "current_question": "kitchen_rating",
  "answers": { "...": "..." },
  "updated_at": "2026-03-15T10:00:00Z"
}

Rewards

POST /api/surveys/mobile/rewards/me       → Puntos, nivel y ciclo del usuario
POST /api/surveys/mobile/rewards/levels   → Definiciones de niveles
POST /api/surveys/mobile/rewards/recommend → Toggle de recomendación

Consideraciones técnicas

  • Los tokens de Stream Chat expiran en 1 hora. La app debe implementar auto-refresh.
  • El MobileAuthGuard valida authToken y userId en el body de cada request POST. Los endpoints GET de surveys mobile son públicos.
  • Las actualizaciones de perfil se sincronizan bidireccionalmente con Stream Chat.
  • Los deep links usan el formato vivla://chat/invitation/{token} para abrir invitaciones directamente en la app.
  • El endpoint de invitaciones (GET /invitations/:token) es público para permitir previsualización sin autenticación.
  • Las encuestas se envían como deep links generados desde el panel de administración.
  • La persistencia parcial de respuestas sigue un flujo local-first: guarda en MMKV, sincroniza al backend por step, y al reabrir compara timestamps local vs backend (usa el más reciente).