Visão Geral da API
URL Base: https://channel.ozzieapp.com/v1
A Channel API é o único ponto de integração para todos os aplicativos para consumidores. Ela é stateful — gerencia usuários, autenticação OTP, onboarding, histórico de chat e transações.
A camada de inteligência está disponível em api.ozzieapp.com, mas é um serviço interno. Aplicativos para consumidores — incluindo o Lovable — não a chamam diretamente. Todas as requisições passam por channel.ozzieapp.com.
Endpoints
| Método | Caminho | Descrição |
|---|---|---|
POST | /v1/auth/otp/request | Solicitar um código OTP de 6 dígitos (WhatsApp ou e-mail) |
POST | /v1/auth/otp/verify | Verificar código OTP — retorna user_id + onboarding_stage |
POST | /v1/users | Criar identidade de usuário |
GET | /v1/users/:user_id | Obter usuário |
GET | /v1/users/:user_id/profile | Obter perfil de usuário do canal (onboarding_stage, plan_speed, etc.) |
PATCH | /v1/users/:user_id/onboarding/complete | Avançar onboarding de plan → active |
POST | /v1/users/:user_id/financial-intake | Enviar intake financeiro |
GET | /v1/users/:user_id/financial-intake | Obter intake |
POST | /v1/users/:user_id/plan/generate | Gerar plano — aceita personality_type no corpo |
GET | /v1/users/:user_id/plan | Obter plano |
GET | /v1/users/:user_id/financial-profile | Alocações de envelopes — aceita ?personality_type= |
POST | /v1/users/:user_id/chat/completion | Inferência de chat com IA sem estado |
GET | /v1/users/:user_id/chat/messages | Recuperar histórico de chat |
POST | /v1/transactions/parse | Análise de transação com IA sem estado |
GET | /v1/personality/questions | Catálogo de perguntas do quiz (sem user_id obrigatório) |
POST | /v1/personality/score | Pontuar respostas do quiz e retornar tipo de personalidade |
POST | /v1/money-moves/generate | Gerar recomendações semanais de movimentos financeiros |
Autenticação
HTTP Bearer com token client_id:client_secret codificado em base64.
Formato do token:
base64(client_id + ":" + client_secret)
Header:
Authorization: Bearer <base64_encoded_credentials>
Gerando o 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 exponha seu client_secret em código client-side, aplicativos móveis ou repositórios públicos. Todas as chamadas à API devem originar do seu backend.
Convenções de requisição e resposta
Headers de requisição
| Header | Obrigatório | Valor |
|---|---|---|
Authorization | Sim | Bearer <token> |
Content-Type | Sim (POST/PATCH) | application/json |
Idempotency-Key | Não | UUID v4 — para requisições POST idempotentes |
Envelope de resposta
{
"object": "object_type_name",
"data": { ... }
}
Códigos de status HTTP
| Status | Significado |
|---|---|
200 OK | Requisição bem-sucedida |
201 Created | Recurso criado |
400 Bad Request | JSON malformado ou erro de validação |
401 Unauthorized | Credenciais ausentes ou inválidas |
403 Forbidden | Credenciais válidas, permissões insuficientes |
404 Not Found | Recurso não existe |
409 Conflict | Recurso já existe |
422 Unprocessable Entity | Erro de lógica de negócio (ex.: intake ausente) |
429 Too Many Requests | Limite de taxa excedido |
500 Internal Server Error | Erro no servidor |
Códigos de erro
Todos os erros seguem este formato:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable explanation."
}
}
| Código | HTTP | Descrição |
|---|---|---|
INVALID_JSON | 400 | O corpo da requisição não é JSON válido |
VALIDATION_ERROR | 400 | Campo falhou na validação |
INVALID_CODE | 400 | Código OTP incorreto ou já utilizado |
CODE_EXPIRED | 400 | Código OTP ultrapassou o TTL de 10 minutos |
UNAUTHORIZED | 401 | Credenciais ausentes ou inválidas |
FORBIDDEN | 403 | Credenciais válidas, mas acesso negado |
NOT_FOUND | 404 | Recurso não existe |
CONFLICT | 409 | Conflito de constraint única (ex.: external_user_id duplicado) |
INTAKE_REQUIRED | 422 | O intake financeiro deve ser enviado primeiro |
PLAN_REQUIRED | 422 | O plano deve ser gerado primeiro |
RATE_LIMIT_EXCEEDED | 429 | Limite de taxa excedido — veja o header Retry-After |
INTERNAL_ERROR | 500 | Erro inesperado no servidor |
Rate limiting
Os limites de taxa são aplicados por client_id. Quando excedidos, a API retorna 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 | Requisições por minuto |
|---|---|
| Standard | 120 |
| Growth | 600 |
| Enterprise | Personalizado |
Sempre implemente backoff exponencial ao lidar com respostas 429.