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.