Pular para o conteúdo principal

Integração em App Fintech

Este guia explica como embutir o Ozzie em um aplicativo fintech ou bancário existente. Ao final, seu app fará o onboarding de usuários no Ozzie automaticamente, sincronizará transações, exibirá o plano financeiro e apresentará um coach de IA — tudo alimentado pela API Ozzie.


Visão geral da arquitetura

Seu App (Frontend)
|
| Chamadas de API
v
Seu Servidor Backend
|
|── POST /users (criação de usuário)
|── POST /users/{id}/intake (intake financeiro)
|── POST /users/{id}/plan (geração do plano)
|── POST /users/{id}/goals (definição de metas)
|── POST /users/{id}/money-moves/generate
|── POST /users/{id}/chat/messages
v
API Ozzie (api.ozzieapp.com/v1)

Princípio fundamental: seu frontend nunca chama o Ozzie diretamente. Todas as chamadas à API Ozzie são feitas no servidor, onde suas credenciais estão seguras. Seu frontend fala com seu backend, que orquestra as chamadas ao Ozzie.


Pré-requisitos

  • Um client_id e client_secret da API Ozzie (obtenha no dashboard Ozzie ou por email commercial@ozzieapp.com)
  • Um servidor backend (exemplos em Node.js abaixo, mas o padrão se aplica a qualquer stack)
  • Um mecanismo para vincular seus IDs de usuário internos aos IDs de usuário do Ozzie

Passo 1: Criar usuário Ozzie no cadastro

Quando um novo usuário completa o cadastro no seu app, crie o perfil Ozzie dele na mesma transação (ou como passo assíncrono imediato).

// lib/ozzie.js — cliente Ozzie compartilhado
const BASE_URL = 'https://api.ozzieapp.com/v1';
const token = Buffer.from(
`${process.env.OZZIE_CLIENT_ID}:${process.env.OZZIE_CLIENT_SECRET}`
).toString('base64');
const headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
};

export async function ozzieRequest(method, path, body = null) {
const response = await fetch(`${BASE_URL}${path}`, {
method,
headers,
body: body ? JSON.stringify(body) : undefined,
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Erro API Ozzie: ${error.error?.code}${error.error?.message}`);
}
return response.json();
}
// routes/auth.js — chamado durante o cadastro
export async function handleSignup(req, res) {
const { email, name, language, phone } = req.body;
const internalUser = await db.users.create({ email, name, language, phone });

const { data: ozzieUser } = await ozzieRequest('POST', '/users', {
external_user_id: internalUser.id,
name: internalUser.name,
language: internalUser.language || 'pt',
phone_e164: internalUser.phone,
});

await db.users.update(internalUser.id, { ozzie_user_id: ozzieUser.id });
res.json({ user: internalUser });
}
dica

Armazene ozzie_user_id na sua tabela de usuários ao lado do seu próprio ID. Toda chamada Ozzie subsequente requer ele.


Passo 2: Coletar intake financeiro

Após o cadastro, solicite ao usuário que complete seu perfil financeiro. Você pode coletar isso em um fluxo de onboarding em múltiplas etapas ou em um único formulário.


Passo 3: Gerar o plano

Assim que o intake for enviado, gere o plano financeiro do usuário. Você pode fazer isso inline com o envio do intake ou acionar como um job em background.


Passo 4: Exibir dados do Ozzie na sua UI

Seu frontend busca dados do seu backend, que faz proxy do Ozzie. Aqui está um padrão para mostrar o plano em uma tela de dashboard:

// Rota backend — faz proxy dos dados do plano para seu frontend
app.get('/api/dashboard', requireAuth, async (req, res) => {
const user = await db.users.findById(req.user.id);
const ozId = user.ozzie_user_id;

const [planRes, goalRes, movesRes] = await Promise.all([
ozzieRequest('POST', `/users/${ozId}/plan`),
ozzieRequest('GET', `/users/${ozId}/goals`),
ozzieRequest('GET', `/users/${ozId}/money-moves?status=available&limit=1`),
]);

res.json({
plan: planRes.data,
goal: goalRes.data,
currentMove: movesRes.data[0] ?? null,
});
});

Passo 5: Embutir o coach de IA

Adicione uma interface de chat que encaminha mensagens do usuário ao coach do Ozzie:

app.post('/api/chat', requireAuth, async (req, res) => {
const user = await db.users.findById(req.user.id);
const { message } = req.body;

const { data } = await ozzieRequest(
'POST',
`/users/${user.ozzie_user_id}/chat/messages`,
{ message }
);

res.json(data);
});

Dicas e boas práticas

Detecção de idioma

const language = req.headers['accept-language']?.split(',')[0]?.split('-')[0] ?? 'pt';
const ozzieLanguage = ['en', 'pt', 'es'].includes(language) ? language : 'pt';

Tratamento de erros

try {
const { data } = await ozzieRequest('POST', `/users/${ozId}/plan`);
return data;
} catch (err) {
if (err.message.includes('INTAKE_REQUIRED')) {
return { redirect: '/onboarding/intake' };
}
if (err.message.includes('RATE_LIMIT_EXCEEDED')) {
await delay(5000);
return ozzieRequest('POST', `/users/${ozId}/plan`);
}
throw err;
}

Estados offline

Armazene em cache as respostas do Ozzie no seu banco de dados para que os usuários vejam dados mesmo quando a API estiver temporariamente indisponível.

aviso

Dados de plano em cache podem ficar desatualizados se o usuário enviar novas transações ou atualizar o intake. Invalide e atualize o cache sempre que enviar novos dados ao Ozzie.