Chat
POST /v1/users/:user_id/chat/completion é um endpoint de inferência de chat com IA sem estado. O chamador fornece a mensagem do usuário, o histórico da conversa e o tipo de personalidade. A camada de inteligência retorna uma resposta sem armazenar nada.
Sua aplicação é responsável por armazenar o histórico da conversa e passá-lo em history a cada chamada.
Como funciona
- Seu app carrega o histórico de conversa do usuário do seu banco de dados
- Seu app chama
POST /v1/users/{user_id}/chat/completioncom a mensagem, o histórico e o tipo de personalidade - A camada de inteligência retorna uma resposta de IA
- Seu app armazena tanto a mensagem do usuário quanto a resposta
- Na próxima chamada, inclua o histórico atualizado
POST /v1/users/:user_id/chat/completion
Envie uma mensagem e receba uma resposta de IA sem estado.
Corpo da requisição
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
message | string | Sim | Mensagem do usuário. Máx 2000 caracteres. |
history | array | Não | Turnos anteriores da conversa [{ role, content }] |
personality_type | string | Não | HOTSHOT | STOCKPILER | GIVER | INDEPENDENT — molda o tom |
language | string | Não | Sobrepõe o idioma da resposta para esta requisição |
context | string | Não | Dica de contexto da conversa, ex.: "financial_planning" |
user_context | object | Não | Snapshot rico do usuário — veja os campos de user_context abaixo |
Campos de user_context
Todos os campos dentro de user_context são opcionais. Passe o máximo de informações disponíveis — contexto mais rico produz respostas mais personalizadas.
| Campo | Tipo | Descrição |
|---|---|---|
name | string | Nome de exibição do usuário |
language | string | Idioma preferido do usuário ("en" | "pt" | "es") |
personality_type | string | HOTSHOT | STOCKPILER | GIVER | INDEPENDENT |
plan_tier | string | Tier do plano da última geração, ex.: "20/80" |
plan_speed | string | Velocidade do plano da última geração: "conservative" | "moderate" | "aggressive" |
monthly_income | number | Renda bruta mensal do usuário |
goal_progress | object | Snapshot da meta — veja abaixo |
goal_progress.target_amount_cents | number | Meta alvo em centavos |
goal_progress.total_contributed_cents | number | Total contribuído até o momento em centavos |
goal_progress.percentage | number | Percentual de contribuição (0–100) |
next_move | object | Detalhes do próximo passo |
next_move.date | string | Data ISO do próximo movimento financeiro, ex.: "2026-05-20" |
next_move.amount_cents | number | Valor do próximo movimento em centavos |
completed_moves_count | number | Total de passos concluídos pelo usuário |
total_saved_cents | number | Total economizado em todos os passos em centavos |
last_confirmation_note | string | Nota em texto livre que o usuário deixou na confirmação do último passo |
entry_point | string | De onde o usuário chegou — molda a mensagem de abertura do Ozzie. Veja os valores de entry_point |
spending_alert_envelope | string | Nome do envelope de alerta de gastos, ex.: "lifestyle" (usado com entry_point: "spending_alert") |
spending_alert_ratio | number | Razão entre gastos reais e alocados, ex.: 1.25 significa 25% acima do orçamento |
rag_context | string | Contexto de recuperação em texto livre injetado no prompt de IA, ex.: padrões comportamentais do seu banco de dados |
Valores de entry_point
entry_point indica ao Ozzie de onde o usuário chegou. O Ozzie usa isso para gerar uma mensagem de abertura contextualmente adequada, retornada como entry_point_opener na resposta.
| entry_point | Quando usar | Ozzie abre com |
|---|---|---|
weekly_expense | Usuário chegou por um prompt de despesas semanais do WhatsApp | Pede as despesas com opções de entrada |
spending_alert | Usuário chegou por uma notificação push de gastos excessivos | Faz referência ao envelope específico (spending_alert_envelope) e pergunta sobre recalibração |
monthly_review | Usuário chegou por um link de revisão mensal do WhatsApp | Resume o mês passado e pergunta sobre este mês |
move_reminder | Usuário chegou por um lembrete de movimento financeiro do WhatsApp | Retorna entry_point_opener: null — o canal renderiza o card de confirmação do passo |
unprompted | Usuário abriu o app diretamente (padrão quando nenhum entry_point é fornecido) | Saudação personalizada referenciando o último passo e o total economizado |
Quando nenhum entry_point é fornecido, entry_point_opener é null na resposta.
- 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'])
Resposta
| Campo | Tipo | Descrição |
|---|---|---|
object | string | Sempre "chat_completion" |
data.content | string | Texto da resposta de IA |
data.entry_point_opener | string | null | Mensagem de abertura pré-construída para a sessão. Não nulo quando entry_point foi fornecido e não é move_reminder. Nulo para move_reminder (o canal renderiza o card do passo) e quando nenhum entry_point foi enviado. |
data.context | string | Contexto ativo da conversa |
{
"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"
}
}
Exemplos de entry_point
unprompted — app aberto diretamente
Requisição:
{
"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"
}
}
Resposta:
{
"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 — chegou pelo prompt do WhatsApp
Requisição:
{
"message": "",
"user_context": {
"name": "Ramon",
"language": "pt",
"entry_point": "weekly_expense"
}
}
Resposta:
{
"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 — chegou por notificação push de gastos excessivos
Requisição:
{
"message": "",
"user_context": {
"name": "Ramon",
"language": "pt",
"entry_point": "spending_alert",
"spending_alert_envelope": "lifestyle",
"spending_alert_ratio": 1.25
}
}
Resposta:
{
"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 — chegou pelo link de revisão mensal do WhatsApp
Requisição:
{
"message": "",
"user_context": {
"name": "Ramon",
"language": "pt",
"entry_point": "monthly_review",
"goal_progress": {
"target_amount_cents": 500000,
"total_contributed_cents": 125000,
"percentage": 25
}
}
}
Resposta:
{
"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 — chegou pelo lembrete de passo do WhatsApp
Requisição:
{
"message": "",
"user_context": {
"name": "Ramon",
"language": "pt",
"entry_point": "move_reminder",
"next_move": {
"date": "2026-05-20",
"amount_cents": 20000
}
}
}
Resposta:
{
"object": "chat_completion",
"data": {
"content": null,
"entry_point_opener": null,
"context": "move_reminder"
}
}
entry_point_opener é null para move_reminder porque o canal (WhatsApp ou o app) é responsável por renderizar o card de confirmação do passo. O Ozzie não gera um texto de abertura para esse fluxo.
Erros
| Código | HTTP | Quando |
|---|---|---|
UNAUTHORIZED | 401 | Credenciais ausentes ou inválidas |
NOT_FOUND | 404 | Usuário não existe |
VALIDATION_ERROR | 400 | message ausente ou acima de 2000 caracteres |
RATE_LIMIT_EXCEEDED | 429 | Muitas requisições de chat |
Coaching adaptado à personalidade
O coach de IA adapta suas respostas com base no personality_type passado. Exemplos:
STOCKPILER perguntando sobre progresso de poupança:
"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 perguntando sobre o mesmo:
"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 perguntando sobre gastos com família:
"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
Retorna o histórico completo de conversa de um usuário. É um alias para o log de chat armazenado pelo canal — as mesmas mensagens que o canal injeta em history a cada chamada de POST /chat/completion.
curl https://channel.ozzieapp.com/v1/users/external:usr_8821/chat/messages \
-H "Authorization: Bearer YOUR_TOKEN"
Resposta (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"
}
]
}
}
Erros:
| Código | HTTP | Quando |
|---|---|---|
UNAUTHORIZED | 401 | Credenciais ausentes ou inválidas |
NOT_FOUND | 404 | Usuário não existe |