Autenticação
Visão geral
A API BaaS usa o OAuth 2.0 Client Credentials Flow para autenticação server-to-server. Todos os endpoints (exceto /v1/authentication/oauth/access-token) exigem um Bearer token válido no header Authorization.
Pontos-chave:
- Os tokens são baseados em JWT, com validade padrão de 1 hora
- A renovação do token é automática quando ele está perto de expirar
- O que o seu client pode chamar é controlado por tenant, pelas famílias de produto habilitadas (BANKING, CRYPTO, KYC, …) — veja Permissões e produtos
Nota: Os endpoints de token (
access-token,introspect,revoke) não têm rate limit de billing por tenant. O único rate limiter do gateway se aplica às rotas de antifraude/financeiras (padrão ~200 requisições/minuto por IP de client, configurável viaANTIFRAUD_RATE_LIMIT).
Setup — obtendo as credenciais de client
Para integrar com a API BaaS, você precisa de Client_ID e Client_Secret.
Solicitando as credenciais
Contate o suporte: envie um e-mail para
[email protected]com os detalhes da sua integração:- Nome da empresa
- Objetivo da integração (ex.: "Plataforma de Folha de Pagamento", "Integração Contábil")
- Volume de transações esperado
- Lista dos produtos necessários (veja Permissões e produtos)
Setup pela Axia: o nosso time vai:
- Criar as credenciais no BackOffice
- Entregá-las por link seguro (válido por 24 horas)
- Documentar os produtos habilitados
Armazene com segurança: guarde as credenciais em variáveis de ambiente ou em um vault:
# .env (never commit this file)
BAAS_CLIENT_ID=axia_prod_abc123xyz
BAAS_CLIENT_SECRET=sk_live_super_secret_never_commit# Or use a vault (recommended for production)
vault kv put secret/baas \
client_id=axia_prod_abc123xyz \
client_secret=sk_live_super_secret_never_commit⚠️ Lembrete de segurança: nunca compartilhe nem commite o Client_Secret. Cada integrador tem credenciais únicas, atreladas ao contexto do seu tenant.
Tenant ID — um identificador, vários nomes
O seu Tenant ID é o mesmo valor do Client_ID do OAuth — o identificador que a Axia atribuiu à sua organização no setup (tipicamente um UUID, ex.: 27c0767f-0abe-40ce-81d9-c168a71354b5). Não existe um "tenant id" separado a ser solicitado: o Client_ID é o tenant id.
O mesmo identificador aparece com nomes diferentes ao longo da API. Todos são o mesmo valor:
| Onde aparece | Nome usado | Direção |
|---|---|---|
Credenciais OAuth (auth Basic nos endpoints de token) | Client_ID | você → API |
| Header HTTP nas chamadas de API | x-client-id | você → API |
Body do POST /v1/bank-accounts/create | application | você → API |
Respostas de checkOnboarding / de conta | clientCode | API → você |
| Payloads de cripto/OTC/webhook | clientId | API → você |
Quando enviá-lo — e por que às vezes você recebe MISSING_CLIENT_ID
Toda rota /v1/* exceto /v1/authentication/* passa pela validação de tenant do gateway. O gateway precisa resolver o seu tenant em toda requisição; quando não consegue, a requisição falha com:
{
"error": "MISSING_CLIENT_ID",
"message": "Client ID (x-client-id) is required"
}(HTTP 400)
Importante: o Bearer token sozinho não basta — a validação de tenant roda antes de o client do token ser resolvido. O gateway procura o seu tenant id nesta ordem:
- Campo
applicationno body da requisição — presente apenas se você o incluir explicitamente no seu payload JSON (como fazem os exemplos de criação de conta) - Header
client_id - Header
x-client-id
Regra prática: sempre envie o header x-client-id: <seu Client_ID> em toda chamada de API (exceto nos endpoints de token /v1/authentication/*, que usam auth Basic). Não dependa apenas do campo application no body — requisições GET não têm body, e esquecer o campo em um POST resulta no mesmo 400.
curl "https://baas-gtw.axiadigitalsolutions.com/v1/bank-accounts/balance?accountId=30054029183&documentNumber=48059890093" \
-H "Authorization: Bearer $TOKEN" \
-H "x-client-id: 27c0767f-0abe-40ce-81d9-c168a71354b5"Outros erros de tenant vindos da mesma validação
| HTTP | error | Significado |
|---|---|---|
400 | MISSING_CLIENT_ID | Tenant id não encontrado no body/headers — adicione o x-client-id |
402 | ACCOUNT_SUSPENDED / ACCOUNT_RESTRICTED | O status de billing do tenant bloqueia a operação |
403 | PRODUCT_NOT_ENABLED | Família de produto (BANKING / CRYPTO / KYC / …) não habilitada para o seu tenant |
403 | OPERATION_NOT_ALLOWED | Tenant restrito a um subconjunto de operações (ex.: apenas PIX) |
Consulte Tratamento de Erros para o catálogo completo.
POST /v1/authentication/oauth/access-token
Solicita um Bearer token de acesso à API usando Client Credentials.
Descrição
Este endpoint troca o seu Client_ID e Client_Secret por um token JWT assinado, válido por 1 hora. O token dá acesso às operações de API das famílias de produto habilitadas para o seu tenant (veja Permissões e produtos).
Headers
| Header | Valor |
|---|---|
Authorization | Basic <Base64(Client_ID:Client_Secret)> |
Content-Type | application/json |
Request
Não requer body.
Exemplo
Passo 1: codifique as credenciais em Base64
CREDS=$(echo -n "$BAAS_CLIENT_ID:$BAAS_CLIENT_SECRET" | base64)
echo $CREDS
# Output: YXhpYV9wcm9kX2FiYzEyM3h5ejo6c2tfbGl2ZV9zdXBlcl9zZWNyZXQ=Passo 2: solicite o token
curl -X POST https://baas-gtw.axiadigitalsolutions.com/v1/authentication/oauth/access-token \
-H "Authorization: Basic $CREDS" \
-H "Content-Type: application/json"Response 201 Created
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Im9hdXRoMjAyNDAzMTUifQ.eyJzdWIiOiJheGlhX3Byb2RfYWJjMTIzeHl6IiwiY2xpZW50X2lkIjoiYXhpYV9wcm9kX2FiYzEyM3h5eiIsImV4cCI6MTcxMDc4NjQwMCwiaWF0IjoxNzEwNzgyODAwLCJzY29wZSI6ImFjY291bnRzOnJlYWQgYWNjb3VudHM6d3JpdGUgcGl4OnNlbmQgd2ViaG9va3M6bWFuYWdlIn0.xyz...",
"token_type": "Bearer",
"expires_in": 3600,
"issued_at": "2024-03-15T10:00:00Z",
"scope": "accounts:read accounts:write pix:send webhooks:manage"
}Erros
Se o header Authorization estiver ausente, a requisição falha com a mensagem You must send an Authorization header. Se ele estiver presente mas não for um token Basic, falha com Expected a Basic token. Quando as credenciais são rejeitadas pelo identity provider, a falha é retornada pelo conversor de erro padrão como um status não-2xx, com um body JSON contendo um campo message.
Renovação e cache de token
Quando renovar
Os tokens expiram após 1 hora. Para evitar interrupções, renove 5 minutos antes da expiração em vez de esperar pelos erros de expiração.
Estratégia: renovação preventiva
Verifique o campo expires_in e agende uma renovação quando:
- Horário atual + 5 minutos >= horário de expiração do token
Exemplo em Node.js / TypeScript
class BaaSClient {
private token: string | null = null;
private expiresAt: number = 0;
private readonly clientId: string;
private readonly clientSecret: string;
private readonly baseUrl: string =
'https://baas-gtw.axiadigitalsolutions.com';
constructor(clientId: string, clientSecret: string) {
this.clientId = clientId;
this.clientSecret = clientSecret;
}
private getBasicAuth(): string {
const creds = `${this.clientId}:${this.clientSecret}`;
return Buffer.from(creds).toString('base64');
}
async getToken(): Promise<string> {
// Retorna o token em cache se ainda for válido (com margem de 5 min)
const bufferMs = 5 * 60 * 1000;
if (this.token && Date.now() < this.expiresAt - bufferMs) {
return this.token;
}
// Solicita um novo token
const response = await fetch(
`${this.baseUrl}/v1/authentication/oauth/access-token`,
{
method: 'POST',
headers: {
'Authorization': `Basic ${this.getBasicAuth()}`,
'Content-Type': 'application/json',
},
}
);
if (!response.ok) {
throw new Error(
`Token request failed: ${response.status} ${response.statusText}`
);
}
const data = await response.json();
this.token = data.access_token;
// Calcula o timestamp absoluto de expiração
this.expiresAt = Date.now() + data.expires_in * 1000;
return this.token;
}
async makeRequest<T>(
method: string,
path: string,
body?: unknown
): Promise<T> {
const token = await this.getToken();
const response = await fetch(`${this.baseUrl}${path}`, {
method,
headers: {
'Authorization': `Bearer ${token}`,
// Tenant id — mesmo valor do Client_ID do OAuth. Obrigatório em toda
// chamada de API; sem ele o gateway retorna 400 MISSING_CLIENT_ID.
'x-client-id': this.clientId,
'Content-Type': 'application/json',
},
body: body ? JSON.stringify(body) : undefined,
});
if (!response.ok) {
throw new Error(
`API request failed: ${response.status} ${response.statusText}`
);
}
return response.json() as Promise<T>;
}
}
// Uso
const client = new BaaSClient(
process.env.BAAS_CLIENT_ID!,
process.env.BAAS_CLIENT_SECRET!
);
// A primeira chamada busca o token
const balance = await client.makeRequest<Balance>(
'GET',
'/v1/bank-accounts/balance?accountId=30054029183&documentNumber=48059890093'
);
// A segunda chamada reaproveita o token (ainda válido)
const onboarding = await client.makeRequest<Onboarding>(
'GET',
'/v1/bank-accounts/checkOnboarding?onBoardingId=48059890093'
);
// Após 55 minutos, a próxima chamada renova automaticamenteExemplo em Python
import os
import base64
import time
import requests
from datetime import datetime
class BaaSClient:
def __init__(self, client_id: str, client_secret: str):
self.client_id = client_id
self.client_secret = client_secret
self.base_url = "https://baas-gtw.axiadigitalsolutions.com"
self.token = None
self.expires_at = 0
def get_basic_auth(self) -> str:
creds = f"{self.client_id}:{self.client_secret}"
encoded = base64.b64encode(creds.encode()).decode()
return encoded
def get_token(self) -> str:
# Verifica se o token em cache ainda é válido (margem de 5 min)
buffer_seconds = 5 * 60
if self.token and time.time() < self.expires_at - buffer_seconds:
return self.token
# Solicita um novo token
response = requests.post(
f"{self.base_url}/v1/authentication/oauth/access-token",
headers={
"Authorization": f"Basic {self.get_basic_auth()}",
"Content-Type": "application/json",
},
)
response.raise_for_status()
data = response.json()
self.token = data["access_token"]
self.expires_at = time.time() + data["expires_in"]
return self.token
def request(self, method: str, path: str, json=None):
token = self.get_token()
response = requests.request(
method,
f"{self.base_url}{path}",
headers={
"Authorization": f"Bearer {token}",
# Tenant id — mesmo valor do Client_ID do OAuth; obrigatório em
# toda chamada de API (caso contrário, 400 MISSING_CLIENT_ID)
"x-client-id": self.client_id,
"Content-Type": "application/json",
},
json=json,
)
response.raise_for_status()
return response.json()
# Uso
client = BaaSClient(
os.getenv("BAAS_CLIENT_ID"),
os.getenv("BAAS_CLIENT_SECRET"),
)
balance = client.request(
"GET",
"/v1/bank-accounts/balance?accountId=30054029183&documentNumber=48059890093",
)
print(balance)POST /v1/authentication/oauth/introspect
Valida um token e retorna os seus metadados (status ativo, expiração, scopes).
Descrição
Use este endpoint para verificar se um token ainda está ativo antes de fazer chamadas de API. Útil para debug ou para validar o estado do token em logs de auditoria.
Headers
| Header | Valor |
|---|---|
Authorization | Basic <Base64(Client_ID:Client_Secret)> |
token | Valor do Bearer token a inspecionar |
O token a inspecionar é lido do header
tokenda requisição, não de um query param. Enviá-lo como?token=falha comYou must send the bearer token on header.
Exemplo
CREDS=$(echo -n "$BAAS_CLIENT_ID:$BAAS_CLIENT_SECRET" | base64)
TOKEN="eyJhbGciOiJSUzI1NiIs..."
curl -X POST "https://baas-gtw.axiadigitalsolutions.com/v1/authentication/oauth/introspect" \
-H "Authorization: Basic $CREDS" \
-H "token: $TOKEN" \
-H "Content-Type: application/json"Response 201 Created (token ativo)
{
"active": true,
"client_id": "axia_prod_abc123xyz",
"token_type": "Bearer",
"exp": 1710786400,
"iat": 1710782800,
"issued_at": "2024-03-15T10:00:00Z",
"expires_at": "2024-03-15T11:00:00Z",
"scope": "accounts:read accounts:write pix:send webhooks:manage"
}Response 201 Created (token expirado)
{
"active": false,
"reason": "Token expired on 2024-03-15T11:00:00Z"
}Response 201 Created (token revogado)
{
"active": false,
"reason": "Token was revoked"
}POST /v1/authentication/oauth/revoke
Revoga um token e invalida imediatamente todos os grants associados.
Descrição
Use este endpoint para deslogar um client ou rotacionar credenciais. Tokens revogados não podem ser reutilizados, e a próxima chamada de API vai exigir um token novo.
Headers
| Header | Valor |
|---|---|
Authorization | Basic <Base64(Client_ID:Client_Secret)> |
token | Valor do Bearer token a revogar |
O token a revogar é lido do header
tokenda requisição, não de um query param. Enviá-lo como?token=falha comYou must send the bearer token on header.
Exemplo
CREDS=$(echo -n "$BAAS_CLIENT_ID:$BAAS_CLIENT_SECRET" | base64)
TOKEN="eyJhbGciOiJSUzI1NiIs..."
curl -X POST "https://baas-gtw.axiadigitalsolutions.com/v1/authentication/oauth/revoke" \
-H "Authorization: Basic $CREDS" \
-H "token: $TOKEN" \
-H "Content-Type: application/json"Response 200 OK
Em caso de sucesso, o endpoint retorna um envelope JSON confirmando a revogação:
{
"body": "Token revoked",
"when": 1710786400000
}Erros
Se o header Authorization estiver ausente, a requisição falha com You must send an Authorization header. Se o header token estiver ausente, falha com You must send the bearer token on header. Qualquer falha do identity provider é retornada pelo conversor de erro padrão como um status não-2xx, com um body JSON contendo um campo message.
Permissões e produtos
O controle de acesso é por tenant, configurado pela Axia no setup — não há negociação de scope em runtime na requisição de token. Dois mecanismos se aplicam em toda chamada:
1. Famílias de produto (enabledProducts): cada área da API pertence a uma família de produto que precisa estar habilitada para o seu tenant. Chamar uma rota de uma família desabilitada retorna 403 PRODUCT_NOT_ENABLED.
| Família de produto | Áreas da API |
|---|---|
BANKING | Contas bancárias, PIX, boletos, transferências |
CRYPTO | Carteiras cripto, trades de OTC |
CRYPTO_BRIDGE | Bridge cross-chain |
KYC | API standalone de verificação KYC |
SALARY_ADVANCE | Antecipação de salário (consignado) |
2. Restrições de operação (allowedOperations): um tenant pode, adicionalmente, ser restrito a um subconjunto de operações (ex.: apenas PIX). Chamadas bloqueadas retornam 403 OPERATION_NOT_ALLOWED.
Nota: ambos são atribuídos por tenant e não podem ser alterados em runtime. Contate o suporte para habilitar produtos adicionais ou remover restrições. A string scope que pode aparecer na resposta do token é informativa — o enforcement acontece pelos gates de produto/operação acima.
Tratamento de erros
Comportamento
Os endpoints de autenticação não emitem códigos de erro de aplicação estruturados. A validação dos headers da requisição lança um erro simples com uma mensagem descritiva, e as falhas do identity provider são repassadas pelo conversor de erro padrão do gateway.
| Situação | Mensagem |
|---|---|
Header Authorization ausente | You must send an Authorization header |
Authorization presente mas não é Basic | Expected a Basic token |
Header token ausente (introspect / revoke) | You must send the bearer token on header |
| Credenciais/token rejeitados pelo identity provider | Repassado pelo conversor de erro padrão (status não-2xx com um campo message) |
Exemplo de resposta de erro
{
"message": "Expected a Basic token"
}Boas práticas
Faça ✅
- Mantenha os tokens em cache em memória entre requisições (reduz carga e latência)
- Renove os tokens proativamente (5 minutos antes da expiração)
- Use variáveis de ambiente ou um vault para armazenar as credenciais
- Logue os erros de autenticação (401, 403) para debug
- Implemente exponential backoff nos retries (erros 500, 504)
- Armazene o timestamp de expiração do token e verifique antes de cada chamada de API
- Rotacione as credenciais periodicamente (ex.: trimestralmente) por segurança
Não faça ❌
- Nunca logue nem imprima tokens no console ou em arquivos
- Nunca commite credenciais no controle de versão (use .gitignore)
- Nunca compartilhe o Client_Secret entre times ou ambientes
- Nunca deixe credenciais hardcoded no código da aplicação
- Nunca confie no conteúdo do token sem validar a assinatura (use o introspect)
- Nunca faça retry imediato em erros 401 (provavelmente é um problema permanente de credencial)
- Nunca armazene tokens no localStorage ou em storage client-side (somente backend)
Arquitetura recomendada
┌─────────────────────┐
│ Sua aplicação │
│ (server-side) │
└──────────┬──────────┘
│
┌────▼─────────────────┐
│ BaaS Client Library │
│ (cache de token + │
│ refresh + retries) │
└────┬──────────────────┘
│
┌────▼─────────────────┐
│ BaaS API Gateway │
│ (validação + │
│ check de scope) │
└─────────────────────┘- Mantenha as credenciais em um vault seguro (HashiCorp Vault, AWS Secrets Manager, etc.)
- Use uma client library (exemplo em Node.js acima) para tratar a renovação do token automaticamente
- Nunca exponha credenciais em logs ou mensagens de erro
- Use somente HTTPS em todas as comunicações com a API