Chat
POST /v1/users/:user_id/chat/completion es un endpoint de inferencia de chat IA sin estado. El que llama proporciona el mensaje del usuario, el historial de conversación y el tipo de personalidad. La capa de inteligencia devuelve una respuesta sin almacenar nada.
Tu aplicación es responsable de almacenar el historial de conversación y pasarlo en history en cada llamada.
Cómo funciona
- Tu aplicación carga el historial de conversación del usuario desde tu base de datos
- Tu aplicación llama a
POST /v1/users/{user_id}/chat/completioncon el mensaje, el historial y el tipo de personalidad - La capa de inteligencia devuelve una respuesta de IA
- Tu aplicación almacena tanto el mensaje del usuario como la respuesta
- En la siguiente llamada, incluye el historial actualizado
POST /v1/users/:user_id/chat/completion
Envía un mensaje y recibe una respuesta de IA sin estado.
Cuerpo de la solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
message | string | Sí | Mensaje del usuario. Máx 2000 caracteres. |
history | array | No | Turnos previos de conversación [{ role, content }] |
personality_type | string | No | HOTSHOT | STOCKPILER | GIVER | INDEPENDENT — moldea el tono |
language | string | No | Sobrescribe el idioma de respuesta para esta solicitud |
context | string | No | Pista de contexto de conversación, ej. "financial_planning" |
user_context | object | No | Instantánea rica del usuario — ver campos de user_context abajo |
Campos de user_context
Todos los campos dentro de user_context son opcionales. Pasa los que tengas disponibles — un contexto más rico produce respuestas más personalizadas.
| Campo | Tipo | Descripción |
|---|---|---|
name | string | Nombre de visualización del usuario |
language | string | Idioma preferido del usuario ("en" | "pt" | "es") |
personality_type | string | HOTSHOT | STOCKPILER | GIVER | INDEPENDENT |
plan_tier | string | Tier del plan de la última generación, ej. "20/80" |
plan_speed | string | Velocidad del plan de la última generación: "conservative" | "moderate" | "aggressive" |
monthly_income | number | Ingreso mensual bruto del usuario |
goal_progress | object | Instantánea de la meta — ver abajo |
goal_progress.target_amount_cents | number | Meta objetivo en centavos |
goal_progress.total_contributed_cents | number | Total contribuido hasta ahora en centavos |
goal_progress.percentage | number | Porcentaje de contribución (0–100) |
next_move | object | Detalles del próximo passo |
next_move.date | string | Fecha ISO del próximo movimiento de dinero, ej. "2026-05-20" |
next_move.amount_cents | number | Monto del próximo movimiento en centavos |
completed_moves_count | number | Total de passos completados por el usuario |
total_saved_cents | number | Monto total ahorrado en todos los passos en centavos |
last_confirmation_note | string | Nota en texto libre que el usuario dejó en su última confirmación de passo |
entry_point | string | Desde dónde llegó el usuario — moldea el mensaje de apertura de Ozzie. Ver valores de entry_point |
spending_alert_envelope | string | Nombre del sobre para una alerta de gasto, ej. "lifestyle" (usado con entry_point: "spending_alert") |
spending_alert_ratio | number | Ratio de gasto real respecto al asignado, ej. 1.25 significa 25% sobre el presupuesto |
rag_context | string | Contexto de recuperación en texto libre inyectado en el prompt de IA, ej. patrones de comportamiento de tu base de datos |
Valores de entry_point
entry_point le indica a Ozzie desde dónde llegó el usuario. Ozzie lo usa para generar un mensaje de apertura contextualizado devuelto como entry_point_opener en la respuesta.
| entry_point | Cuándo usarlo | Ozzie abre con |
|---|---|---|
weekly_expense | El usuario llega desde un prompt semanal de gastos de WhatsApp | Solicita los gastos con opciones de entrada |
spending_alert | El usuario llega desde una notificación push sobre exceso de gasto | Hace referencia al sobre específico (spending_alert_envelope) y pregunta sobre recalibración |
monthly_review | El usuario llega desde un enlace de revisión mensual de WhatsApp | Resume el mes pasado y pregunta sobre este mes |
move_reminder | El usuario llega desde un recordatorio de movimiento de dinero de WhatsApp | Devuelve entry_point_opener: null — el canal renderiza la tarjeta de confirmación del passo |
unprompted | El usuario abre la aplicación directamente (por defecto cuando no se proporciona entry_point) | Saludo personalizado con referencia al último passo y el total ahorrado |
Cuando no se proporciona entry_point, entry_point_opener es null en la respuesta.
- curl
- Node.js
- Python
curl -X POST https://channel.ozzieapp.com/v1/users/ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE/chat/completion \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"message": "How am I doing with my savings goal?",
"personality_type": "STOCKPILER",
"language": "en"
}'
const res = await fetch(
'https://channel.ozzieapp.com/v1/users/ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE/chat/completion',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: 'How am I doing with my savings goal?',
personality_type: 'STOCKPILER',
language: 'en',
history: previousTurns, // your stored conversation history
}),
}
);
const { data } = await res.json();
console.log(data.content);
import requests, base64
token = base64.b64encode(b'your_client_id:your_client_secret').decode()
response = requests.post(
'https://channel.ozzieapp.com/v1/users/ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE/chat/completion',
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json',
},
json={
'message': 'How am I doing with my savings goal?',
'personality_type': 'STOCKPILER',
'language': 'en',
}
)
print(response.json()['data']['content'])
Respuesta
| Campo | Tipo | Descripción |
|---|---|---|
object | string | Siempre "chat_completion" |
data.content | string | Texto de la respuesta de IA |
data.entry_point_opener | string | null | Mensaje de apertura pre-construido para la sesión. No es null cuando se proporcionó entry_point y no es move_reminder. Es null para move_reminder (el canal renderiza la tarjeta del passo) y cuando no se envió entry_point. |
data.context | string | Contexto de conversación activo |
{
"object": "chat_completion",
"data": {
"role": "assistant",
"content": "You're on track. Your STOCKPILER profile means consistent, automated saving is your edge — keep that monthly transfer running and you'll hit your monthly target comfortably.",
"entry_point_opener": null,
"context": "general",
"created_at": "2026-05-15T10:10:00Z"
}
}
Ejemplos de entry_point
unprompted — aplicación abierta directamente
Solicitud:
{
"message": "oi",
"user_context": {
"name": "Ramon",
"language": "pt",
"personality_type": "STOCKPILER",
"completed_moves_count": 8,
"total_saved_cents": 125000,
"next_move": {
"date": "2026-05-20",
"amount_cents": 20000
},
"entry_point": "unprompted"
}
}
Respuesta:
{
"object": "chat_completion",
"data": {
"content": "Oi Ramon! Você completou 8 passos e já guardou $1,250. Seu próximo passo é dia 2026-05-20. Sobre o que você quer falar hoje?",
"entry_point_opener": "Oi Ramon! Você completou 8 passos e já guardou $1,250. Seu próximo passo é dia 2026-05-20. Sobre o que você quer falar hoje?",
"context": "general"
}
}
weekly_expense — llegó desde un prompt de WhatsApp
Solicitud:
{
"message": "",
"user_context": {
"name": "Ramon",
"language": "pt",
"entry_point": "weekly_expense"
}
}
Respuesta:
{
"object": "chat_completion",
"data": {
"content": "Ramon, vamos registrar seus gastos da semana! Me conta o que você gastou — pode ser no formato livre ou escolha uma categoria para começar.",
"entry_point_opener": "Ramon, vamos registrar seus gastos da semana! Me conta o que você gastou — pode ser no formato livre ou escolha uma categoria para começar.",
"context": "weekly_expense"
}
}
spending_alert — llegó desde una notificación push de exceso de gasto
Solicitud:
{
"message": "",
"user_context": {
"name": "Ramon",
"language": "pt",
"entry_point": "spending_alert",
"spending_alert_envelope": "lifestyle",
"spending_alert_ratio": 1.25
}
}
Respuesta:
{
"object": "chat_completion",
"data": {
"content": "Ramon, seu envelope lifestyle está 25% acima do planejado este mês. Quer recalibrar ou conversar sobre o que aconteceu?",
"entry_point_opener": "Ramon, seu envelope lifestyle está 25% acima do planejado este mês. Quer recalibrar ou conversar sobre o que aconteceu?",
"context": "spending_alert"
}
}
monthly_review — llegó desde un enlace de revisión mensual de WhatsApp
Solicitud:
{
"message": "",
"user_context": {
"name": "Ramon",
"language": "pt",
"entry_point": "monthly_review",
"goal_progress": {
"target_amount_cents": 500000,
"total_contributed_cents": 125000,
"percentage": 25
}
}
}
Respuesta:
{
"object": "chat_completion",
"data": {
"content": "Ramon, o mês passou! Você contribuiu $1,250 e está 25% do caminho para sua meta. O que você quer priorizar no próximo mês?",
"entry_point_opener": "Ramon, o mês passou! Você contribuiu $1,250 e está 25% do caminho para sua meta. O que você quer priorizar no próximo mês?",
"context": "monthly_review"
}
}
move_reminder — llegó desde un recordatorio de passo de WhatsApp
Solicitud:
{
"message": "",
"user_context": {
"name": "Ramon",
"language": "pt",
"entry_point": "move_reminder",
"next_move": {
"date": "2026-05-20",
"amount_cents": 20000
}
}
}
Respuesta:
{
"object": "chat_completion",
"data": {
"content": null,
"entry_point_opener": null,
"context": "move_reminder"
}
}
entry_point_opener es null para move_reminder porque el canal (WhatsApp o la aplicación) es responsable de renderizar la tarjeta de confirmación del passo. Ozzie no genera un texto de apertura para este flujo.
Errores
| Código | HTTP | Cuándo |
|---|---|---|
UNAUTHORIZED | 401 | Credenciales ausentes o inválidas |
NOT_FOUND | 404 | El usuario no existe |
VALIDATION_ERROR | 400 | message faltante o supera los 2000 caracteres |
RATE_LIMIT_EXCEEDED | 429 | Demasiadas solicitudes de chat |
Coaching con consciencia de personalidad
El coach de IA adapta sus respuestas según el personality_type que pasas. Ejemplos:
STOCKPILER preguntando sobre el progreso de ahorro:
"You've built $750 of your $1,500 monthly target — exactly on pace. Your STOCKPILER profile means this consistency compounds. Keep the automation running and you'll hit your emergency fund milestone in 8 months."
HOTSHOT preguntando lo mismo:
"You're at 50% of your monthly savings target. That's solid, but if you redirect your $300 lifestyle envelope surplus this month, you'd hit 70% — which puts your investment timeline 3 weeks ahead of schedule."
GIVER preguntando sobre gastos en familia:
"Your people envelope has $285 left this month — well within your $375 allocation. Spending on family is part of your GIVER profile, not a deviation from your plan."
GET /v1/users/:user_id/chat/messages
Devuelve el historial de conversación completo de un usuario. Es un alias del registro de chat almacenado en el canal — los mismos mensajes que el canal inyecta en history en cada llamada a POST /chat/completion.
curl https://channel.ozzieapp.com/v1/users/external:usr_8821/chat/messages \
-H "Authorization: Bearer YOUR_TOKEN"
Respuesta (200 OK):
{
"object": "chat_history",
"data": {
"messages": [
{
"role": "user",
"content": "Como estou indo?",
"created_at": "2026-05-16T10:00:00Z"
},
{
"role": "assistant",
"content": "Você está no caminho certo.",
"created_at": "2026-05-16T10:00:01Z"
}
]
}
}
Errores:
| Código | HTTP | Cuándo |
|---|---|---|
UNAUTHORIZED | 401 | Credenciales ausentes o inválidas |
NOT_FOUND | 404 | El usuario no existe |