Visión General de la API
URL Base: https://channel.ozzieapp.com/v1
La Channel API es el único punto de integración para todas las aplicaciones de consumo. Es stateful — gestiona usuarios, autenticación OTP, onboarding, historial de chat y transacciones.
La capa de inteligencia está disponible en api.ozzieapp.com pero es un servicio interno. Las aplicaciones de consumo — incluida Lovable — no la llaman directamente. Todas las solicitudes pasan por channel.ozzieapp.com.
Endpoints
| Método | Ruta | Descripción |
|---|---|---|
POST | /v1/auth/otp/request | Solicitar un código OTP de 6 dígitos (WhatsApp o correo) |
POST | /v1/auth/otp/verify | Verificar código OTP — devuelve user_id + onboarding_stage |
POST | /v1/users | Crear identidad de usuario |
GET | /v1/users/:user_id | Obtener usuario |
GET | /v1/users/:user_id/profile | Obtener perfil de usuario del canal (onboarding_stage, plan_speed, etc.) |
PATCH | /v1/users/:user_id/onboarding/complete | Avanzar el onboarding de plan → active |
POST | /v1/users/:user_id/financial-intake | Enviar intake financiero |
GET | /v1/users/:user_id/financial-intake | Obtener intake |
POST | /v1/users/:user_id/plan/generate | Generar plan — acepta personality_type en el cuerpo |
GET | /v1/users/:user_id/plan | Obtener plan |
GET | /v1/users/:user_id/financial-profile | Asignaciones de sobres — acepta ?personality_type= |
POST | /v1/users/:user_id/chat/completion | Inferencia de chat IA sin estado |
GET | /v1/users/:user_id/chat/messages | Recuperar historial de chat |
POST | /v1/transactions/parse | Análisis de transacciones IA sin estado |
GET | /v1/personality/questions | Catálogo de preguntas del quiz (no requiere user_id) |
POST | /v1/personality/score | Puntuar respuestas del quiz y devolver tipo de personalidad |
POST | /v1/money-moves/generate | Generar recomendaciones de movimientos semanales |
Autenticación
HTTP Bearer con un token client_id:client_secret codificado en base64.
Formato del token:
base64(client_id + ":" + client_secret)
Encabezado:
Authorization: Bearer <base64_encoded_credentials>
Generando el token:
- Node.js
- Python
- curl
const token = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
// Authorization: `Bearer ${token}`
import base64
token = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()
# f"Bearer {token}"
TOKEN=$(echo -n "your_client_id:your_client_secret" | base64)
curl -H "Authorization: Bearer $TOKEN" https://channel.ozzieapp.com/v1/users
Nunca expongas tu client_secret en código del lado del cliente, aplicaciones móviles o repositorios públicos. Todas las llamadas a la API deben originarse desde tu backend.
Convenciones de solicitud y respuesta
Encabezados de solicitud
| Encabezado | Requerido | Valor |
|---|---|---|
Authorization | Sí | Bearer <token> |
Content-Type | Sí (POST/PATCH) | application/json |
Idempotency-Key | No | UUID v4 — para solicitudes POST idempotentes |
Envelope de respuesta
{
"object": "object_type_name",
"data": { ... }
}
Códigos de estado HTTP
| Estado | Significado |
|---|---|
200 OK | Solicitud exitosa |
201 Created | Recurso creado |
400 Bad Request | JSON malformado o error de validación |
401 Unauthorized | Credenciales ausentes o inválidas |
403 Forbidden | Credenciales válidas, permisos insuficientes |
404 Not Found | El recurso no existe |
409 Conflict | El recurso ya existe |
422 Unprocessable Entity | Error de lógica de negocio (ej., intake faltante) |
429 Too Many Requests | Límite de tasa excedido |
500 Internal Server Error | Error en el servidor |
Códigos de error
Todos los errores siguen esta estructura:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable explanation."
}
}
| Código | HTTP | Descripción |
|---|---|---|
INVALID_JSON | 400 | El cuerpo de la solicitud no es JSON válido |
VALIDATION_ERROR | 400 | Un campo falló la validación |
INVALID_CODE | 400 | El código OTP es incorrecto o ya fue utilizado |
CODE_EXPIRED | 400 | El código OTP superó su TTL de 10 minutos |
UNAUTHORIZED | 401 | Credenciales ausentes o inválidas |
FORBIDDEN | 403 | Credenciales válidas pero acceso denegado |
NOT_FOUND | 404 | El recurso no existe |
CONFLICT | 409 | Conflicto de restricción única (ej., external_user_id duplicado) |
INTAKE_REQUIRED | 422 | Primero debe enviarse el intake financiero |
PLAN_REQUIRED | 422 | Primero debe generarse el plan |
RATE_LIMIT_EXCEEDED | 429 | Límite de tasa excedido — consulta el encabezado Retry-After |
INTERNAL_ERROR | 500 | Error inesperado en el servidor |
Límite de tasa
Los límites de tasa se aplican por client_id. Al excederlos, la API devuelve HTTP 429:
HTTP/1.1 429 Too Many Requests
Retry-After: 15
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1746460800
| Tier | Solicitudes por minuto |
|---|---|
| Standard | 120 |
| Growth | 600 |
| Enterprise | Personalizado |
Implementa siempre backoff exponencial al manejar respuestas 429.