Errores
Todos los errores de la API de Ozzie siguen un formato consistente. Cuando una solicitud falla, el cuerpo de la respuesta siempre contiene un objeto error con un code legible por máquina, un message legible por humanos y un array details opcional con contexto adicional.
Formato de la respuesta de error
{
"error": {
"code": "ERROR_CODE",
"message": "Una descripción legible de qué salió mal.",
"details": []
}
}
| Campo | Tipo | Descripción |
|---|---|---|
error.code | string | Código de error legible por máquina — úsalo para manejo programático |
error.message | string | Descripción legible del error |
error.details | array | Contexto adicional opcional, como qué campos fallaron en validación |
Códigos de error
INVALID_JSON
| Estado HTTP | 400 Bad Request |
|---|---|
| Cuándo ocurre | El cuerpo de la solicitud no pudo ser analizado como JSON |
| Cómo resolver | Verifica que el header Content-Type sea application/json y que el cuerpo sea JSON válido. |
VALIDATION_ERROR
| Estado HTTP | 422 Unprocessable Entity |
|---|---|
| Cuándo ocurre | El cuerpo de la solicitud es JSON válido pero contiene valores de campo inválidos |
| Cómo resolver | Revisa el array details — cada entrada identifica el campo específico y la falla de validación. |
UNAUTHORIZED
| Estado HTTP | 401 Unauthorized |
|---|---|
| Cuándo ocurre | El header Authorization está ausente, malformado o contiene credenciales inválidas |
| Cómo resolver | Verifica que el token esté codificado correctamente como base64(client_id:client_secret). |
FORBIDDEN
| Estado HTTP | 403 Forbidden |
|---|---|
| Cuándo ocurre | Tus credenciales son válidas, pero estás intentando acceder a un recurso que pertenece al usuario de otro cliente |
| Cómo resolver | Verifica que el user_id en la ruta pertenezca a un usuario que creaste bajo tu client_id. |
NOT_FOUND
| Estado HTTP | 404 Not Found |
|---|---|
| Cuándo ocurre | El recurso solicitado no existe |
| Cómo resolver | Verifica que el ID en la URL sea correcto y que el recurso fue creado antes de intentar recuperarlo. |
CONFLICT
| Estado HTTP | 409 Conflict |
|---|---|
| Cuándo ocurre | La solicitud conflictúa con el estado actual de un recurso. Más comúnmente: intentar crear un usuario con un external_user_id que ya existe. |
| Cómo resolver | Usa GET /users?external_user_id=... para verificar si ya existe antes de crear. |
INTAKE_REQUIRED
| Estado HTTP | 422 Unprocessable Entity |
|---|---|
| Cuándo ocurre | Llamaste a un endpoint que requiere un intake financiero (ej: POST /plan), pero no se ha enviado ningún intake. |
| Cómo resolver | Llama a POST /users/{user_id}/financial-intake primero. |
PLAN_REQUIRED
| Estado HTTP | 422 Unprocessable Entity |
|---|---|
| Cuándo ocurre | Llamaste a un endpoint que requiere un plan (ej: POST /money-moves/generate), pero no se ha generado ningún plan. |
| Cómo resolver | Llama a POST /users/{user_id}/plan primero. |
PERSONALITY_REQUIRED
| Estado HTTP | 422 Unprocessable Entity |
|---|---|
| Cuándo ocurre | POST /plan/personalize fue llamado sin el campo personality_type en el cuerpo. |
| Cómo resolver | Incluye personality_type en el cuerpo de la solicitud. Valores válidos: "optimizer", "planner", "avoider", "spender". |
RATE_LIMIT_EXCEEDED
| Estado HTTP | 429 Too Many Requests |
|---|---|
| Cuándo ocurre | Tu cliente ha enviado más solicitudes de las que permite el límite de tasa. |
| Cómo resolver | Espera hasta el tiempo especificado en el header X-RateLimit-Reset, luego reintenta. Implementa backoff exponencial. |
INTERNAL_ERROR
| Estado HTTP | 500 Internal Server Error |
|---|---|
| Cuándo ocurre | Ocurrió un error inesperado en los servidores de Ozzie. |
| Cómo resolver | Reintenta después de un breve delay. Si el error persiste, verifica la página de estado de Ozzie. |
Estrategia de reintento
| Código de error | ¿Reintentar? | Estrategia |
|---|---|---|
INVALID_JSON | No | Corrige la solicitud |
VALIDATION_ERROR | No | Corrige los campos inválidos |
UNAUTHORIZED | No | Corrige las credenciales |
FORBIDDEN | No | Estás accediendo al recurso equivocado |
NOT_FOUND | No | El recurso no existe |
CONFLICT | No | El recurso ya existe |
INTAKE_REQUIRED | No | Redirige al usuario a completar el intake |
PLAN_REQUIRED | No | Llama a POST /plan primero |
RATE_LIMIT_EXCEEDED | Sí | Espera X-RateLimit-Reset, luego reintenta |
INTERNAL_ERROR | Sí | Reintenta con backoff exponencial |