Pular para o conteúdo principal

Autenticação

A API Ozzie utiliza autenticação HTTP Bearer. Toda requisição deve incluir um header Authorization com um token codificado em base64 derivado do seu client_id e client_secret.


Obtendo suas credenciais​

Para obter credenciais de API, você pode:

  • Entrar em contato com o time Ozzie em commercial@ozzieapp.com para discutir seu caso de uso e obter acesso
  • Acessar o painel Ozzie e navegar até Configurações → Chaves de API para gerar um par de client_id e client_secret

Você receberá dois valores:

ValorExemploDescrição
client_idozz_client_a1b2c3d4Um identificador estável para seu cliente de API. Seguro para registrar em logs.
client_secretsk_live_xK9mP2qR7tL...Uma chave secreta. Trate-a como uma senha. Nunca a exponha.
aviso

Seu client_secret é exibido apenas uma vez no momento da geração. Armazene-o com segurança imediatamente — se você perdê-lo, precisará rotacionar suas credenciais.


Como a autenticação funciona​

O Ozzie usa HTTP Basic Auth codificado como token Bearer. O token é a codificação base64 da string client_id:client_secret (separados por dois pontos, sem espaços).

token = base64("ozz_client_a1b2c3d4:sk_live_xK9mP2qR7tL...")
Authorization: Bearer <token>

Este é um token único e estático que você gera uma vez e reutiliza em todas as requisições. Não é necessário trocá-lo por um token de sessão nem renová-lo periodicamente — ele é válido até que você rotacione suas credenciais.


Codificando seu token​

# Encode your credentials
CLIENT_ID="ozz_client_a1b2c3d4"
CLIENT_SECRET="sk_live_xK9mP2qR7tL..."

TOKEN=$(echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64)
echo $TOKEN
# ozp_Y2xpZW50X2ExYjJjM2Q0OnNrX2xpdmVfeEs5bVAycVI3dEwu...

Fazendo requisições autenticadas​

Com o token em mãos, inclua-o em todas as requisições no header Authorization:

curl https://api.ozzieapp.com/v1/api/v1/users \
-H "Authorization: Bearer ozp_Y2xpZW50X2ExYjJjM2Q0OnNrX2xpdmVfeEs5bVAycVI3dEwu..." \
-H "Content-Type: application/json" \
-d '{
"external_user_id": "user_123",
"name": "Alex Johnson",
"language": "en"
}'
dica

Construa o token uma única vez na inicialização da aplicação e reutilize-o em todas as requisições. Não há expiração — você não precisa regenerá-lo a cada requisição.


Rate limiting​

Toda resposta da API inclui headers de limite de taxa para que você possa acompanhar seu uso:

HeaderDescrição
X-RateLimit-LimitO número máximo de requisições permitidas na janela atual
X-RateLimit-RemainingQuantas requisições restam na janela atual
X-RateLimit-ResetTimestamp Unix (segundos) de quando a janela redefine e seu limite é reabastecido

Exemplo de headers de resposta:

HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1746489600

Quando você atinge o limite de taxa, a API retorna status 429. Aguarde e tente novamente após o timestamp em X-RateLimit-Reset.

{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "You have exceeded the rate limit for this window. Please retry after the reset time.",
"details": [
{
"reset_at": 1746489600,
"limit": 1000,
"window": "1 minute"
}
]
}
}
informação

Os limites de taxa variam por tier. Clientes do tier gratuito têm limites menores do que clientes Pro ou Enterprise. Entre em contato com commercial@ozzieapp.com se precisar de maior capacidade.


Códigos de erro de autenticação​

Status HTTPCódigo de ErroQuando ocorre
401 UnauthorizedUNAUTHORIZEDO header Authorization está ausente, malformado ou contém credenciais inválidas
429 Too Many RequestsRATE_LIMIT_EXCEEDEDSeu cliente enviou mais requisições do que o permitido na janela atual

Exemplo de resposta 401:

{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing authorization credentials.",
"details": []
}
}

Causas comuns de um 401:

  • Esqueceu de incluir o header Authorization
  • Codificou client_id:client_secret com espaços ou caracteres extras
  • Usando um client_secret que foi rotacionado ou revogado
  • Enviando a string bruta client_id:client_secret em vez da versão codificada em base64

Autenticação do usuário final (OTP)​

Aplicativos para consumidores autenticam seus usuários finais por meio de um código OTP de 6 dígitos entregue via WhatsApp ou e-mail. Esse fluxo é gerenciado inteiramente pela Channel API — seu servidor chama channel.ozzieapp.com em nome do usuário.

informação

O fluxo OTP é separado da autenticação de cliente de API. Seu client_id / client_secret são credenciais servidor a servidor. O OTP é para autenticar o usuário humano dentro do seu aplicativo.

O fluxo OTP completo​

1. Registrar o usuário (apenas uma vez)
│
▼
POST /v1/users → recebe o user_id do Ozzie
│
▼
2. Solicitar um código OTP
│
▼
POST /v1/auth/otp/request → código enviado ao usuário via WhatsApp ou e-mail
│
▼
3. Usuário digita o código na sua interface
│
▼
POST /v1/auth/otp/verify → retorna user_id + onboarding_stage
│
▼
4. Seu app cria uma sessão para o usuário
(SESSION_SECRET e gerenciamento de sessão são de responsabilidade do seu app)

Detalhes do OTP​

PropriedadeValor
Comprimento do código6 dígitos
TTL10 minutos
Uso únicoSim — o código é invalidado na primeira verificação bem-sucedida
ArmazenamentoHash bcrypt no banco de dados
identifierTelefone no formato E.164 (ex.: +5511999990000) ou endereço de e-mail
channel"whatsapp" ou "email" — detectado automaticamente a partir do identifier se omitido

Exemplo em TypeScript​

const BASE = 'https://channel.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',
};

// Step 1 — Register the user (skip if already registered; handle 409 gracefully)
const registerRes = await fetch(`${BASE}/users`, {
method: 'POST',
headers,
body: JSON.stringify({
external_user_id: 'usr_8821', // your own user ID — do NOT include "external:" prefix
name: 'Maria Santos',
phone: '+5511999990000', // E.164 format
language: 'pt',
}),
});
if (!registerRes.ok && registerRes.status !== 409) {
throw new Error('User registration failed');
}

// Step 2 — Request OTP
const otpRes = await fetch(`${BASE}/auth/otp/request`, {
method: 'POST',
headers,
body: JSON.stringify({
identifier: '+5511999990000',
language: 'pt',
// channel: 'whatsapp' // optional — auto-detected from E.164 phone
}),
});
const { data: otpData } = await otpRes.json();
// otpData = { channel: "whatsapp", masked: "+55119****0000", expires_at: "2026-05-16T..." }

// Step 3 — Verify OTP (called after the user submits the code in your UI)
async function verifyOtp(code: string) {
const verifyRes = await fetch(`${BASE}/auth/otp/verify`, {
method: 'POST',
headers,
body: JSON.stringify({
identifier: '+5511999990000',
code,
}),
});

if (!verifyRes.ok) {
const { error } = await verifyRes.json();
// error.code === 'INVALID_CODE' or 'CODE_EXPIRED'
throw new Error(error.code);
}

const { data } = await verifyRes.json();
// data = { user_id: "external:usr_8821", core_user_id: "uuid", onboarding_stage: "financial_intake" }

// Step 4 — Create a session (SESSION_SECRET is your app's own concern, not Ozzie's)
return data;
}
dica

SESSION_SECRET e o gerenciamento de cookies de sessão são responsabilidade do seu próprio backend (ex.: Lovable). O Ozzie não emite tokens de sessão — ele apenas valida o OTP e retorna o user_id e o onboarding_stage que seu app precisa para inicializar a sessão.

Para uma referência completa sobre os parâmetros e códigos de erro de requisição/verificação de OTP, consulte a referência de Auth.


Multi-tenancy e escopo de cliente​

Seu client_id é a raiz do seu namespace de tenant. Todo usuário criado com POST /users pertence ao seu cliente, e suas credenciais de API só podem acessar usuários que você criou. Você não pode ler ou modificar usuários criados por outros clientes de API.

Isso significa que:

  • Você gerencia todos os seus usuários finais por meio de um único conjunto de credenciais
  • Os usuários são identificados pelo seu próprio external_user_id — você é responsável pelo mapeamento entre os registros de usuário do Ozzie e seu banco de dados
  • Toda atividade (intake financeiro, transações, planos, chat) tem escopo para os usuários do seu client_id
informação

Não há autenticação por usuário. Seu backend no lado do servidor se autentica no Ozzie usando suas credenciais de cliente e age em nome dos seus usuários. Nunca envie suas credenciais de API para um cliente frontend.


Boas práticas de segurança​

Nunca exponha credenciais no lado do cliente. Seu client_id e client_secret devem existir somente no ambiente do lado do servidor. Um navegador ou aplicativo mobile que chame a API Ozzie diretamente exporia suas credenciais a qualquer pessoa que inspecione o tráfego de rede.

Use variáveis de ambiente. Armazene as credenciais em variáveis de ambiente, não hardcoded nos arquivos de código-fonte. Isso previne commits acidentais no controle de versão.

# .env (never commit this file)
OZZIE_CLIENT_ID=ozz_client_a1b2c3d4
OZZIE_CLIENT_SECRET=sk_live_xK9mP2qR7tL...

Rotacione os secrets periodicamente. Gere um novo client_secret no painel Ozzie em uma programação regular (ex.: a cada 90 dias), ou imediatamente se suspeitar que um secret foi comprometido. Atualize suas variáveis de ambiente e faça o deploy antes de revogar o secret antigo.

Use credenciais separadas por ambiente. Crie clientes de API distintos para seus ambientes de desenvolvimento, staging e produção, para que o tráfego de teste nunca toque dados reais de usuários, e um secret de desenvolvimento comprometido não possa afetar a produção.

Limite o acesso de saída do seu servidor. Se sua infraestrutura suportar, restrinja chamadas HTTPS de saída para api.ozzieapp.com apenas aos serviços que precisam disso — não a todos os servidores do seu stack.