Contas Bancárias
Todos os endpoints de conta bancária exigem
Authorization: Bearer <token>e o headerx-client-id: <Client_ID>— o tenant id é o mesmo valor doClient_IDdo OAuth (veja Autenticação → Tenant ID). Sem ele, as chamadas falham com400 MISSING_CLIENT_ID.
Visão geral
A API de Contas Bancárias cria contas para PF (pessoa física) e PJ (pessoa jurídica) com verificação de KYC automatizada. A criação de conta é assíncrona:
- POST
/v1/bank-accounts/createretorna imediatamente com statusPROCESSING - A verificação de KYC roda em background (tipicamente de 2 a 5 minutos no fast-track, até 24h em análise manual)
- Acompanhe por polling em GET
/v1/bank-accounts/checkOnboardingou configure um webhook (eventoonboarding-create)
Máquina de estados do onboarding
As contas transitam pelos seguintes estados:
┌───────────┐ ┌──────────────┐ ┌────────┐
│PROCESSING │──→ │ APPROVED │──→ │ ACTIVE │
└───────────┘ └──────────────┘ └────────┘
↓ ↓
└──→ PENDING_MANUAL └──→ REJECTED| Estado | Descrição | Ação do integrador |
|---|---|---|
| PROCESSING | KYC em andamento (análise de documentos + validação de selfie) | Consulte GET /checkOnboarding a cada 30s por 5 min, depois a cada 5 min |
| PENDING_MANUAL | Caso suspeito (match de PEP, documentos ilegíveis, risco de endereço) | Aguarde o e-mail da Axia (até 24h); o usuário pode reenviar documentos se solicitado |
| APPROVED | KYC aprovado, conta criada, pronta para transacionar | Siga para cadastrar chave PIX, emitir cartão ou habilitar transferências |
| REJECTED | KYC reprovado definitivamente (documento inválido, checagem de PEP reprovada) | Notifique o usuário; ofereça a opção de reenvio com documentos novos |
| ACTIVE | Conta ativa | Operações normais habilitadas |
POST /v1/bank-accounts/create
Cria uma nova conta para PF ou PJ. A chamada retorna imediatamente (< 100ms) com status PROCESSING.
Headers:
Authorization: Bearer <token>
x-client-id: <seu Client_ID (tenant id)>Pessoa física (PF)
person(o provider lêperson.email). Umperson.email, mas o aninhamento é a forma canônica.
{
"transactionPassword": "ABC@123def",
"person": {
"fullName": "João da Silva",
"socialName": "João",
"documentNumber": "48059890093",
"email": "[email protected]",
"birthDate": "15-03-1990",
"motherName": "Maria da Silva",
"phoneNumber": "+5511999999999",
"isPoliticallyExposedPerson": false,
"address": {
"postalCode": "01310100",
"street": "Avenida Paulista",
"number": "1578",
"neighborhood": "Bela Vista",
"city": "São Paulo",
"state": "SP"
}
},
"bankDocuments": {
"documentLink": "https://bucket.s3.amazonaws.com/doc-front.jpg",
"documentBackLink": "https://bucket.s3.amazonaws.com/doc-back.jpg",
"selfieLink": "https://bucket.s3.amazonaws.com/selfie.jpg"
},
"application": "27c0767f-0abe-40ce-81d9-c168a71354b5"
}Campos obrigatórios de person: fullName, documentNumber (CPF), email, birthDate (DD-MM-YYYY), motherName, phoneNumber (+55…), address. socialName e isPoliticallyExposedPerson são opcionais (padrão: fullName / false). application é o seu tenant id — o mesmo valor do Client_ID do OAuth / do header x-client-id (veja Tenant ID) — e é usado para resolver o provedor bancário.
Pessoa jurídica (PJ)
Os campos de contato da empresa ficam dentro de
legalPerson:businessEmailebusinessPhoneNumber(o provider lêlegalPerson.businessEmail). Os sócios vão no arrayowners— o primeiro é tratado comoREPRESENTANTE, os demais comoSOCIO.
{
"transactionPassword": "XYZ@456abc",
"legalPerson": {
"businessName": "Empresa XYZ Ltda",
"tradingName": "XYZ",
"documentNumber": "12345678000190",
"businessEmail": "[email protected]",
"businessPhoneNumber": "+5511999999999",
"businessAddress": {
"postalCode": "01310100",
"street": "Avenida Paulista",
"number": "1578",
"neighborhood": "Bela Vista",
"city": "São Paulo",
"state": "SP"
},
"owners": [
{
"fullName": "João da Silva",
"documentNumber": "48059890093",
"email": "[email protected]",
"phoneNumber": "+5511999999999",
"birthDate": "15-03-1990",
"motherName": "Maria da Silva",
"isPoliticallyExposedPerson": false,
"address": {
"postalCode": "01310100",
"street": "Avenida Paulista",
"number": "1578",
"neighborhood": "Bela Vista",
"city": "São Paulo",
"state": "SP"
}
}
]
},
"bankDocuments": {
"documentLink": "https://bucket.s3.amazonaws.com/doc-front.jpg",
"documentBackLink": "https://bucket.s3.amazonaws.com/doc-back.jpg",
"selfieLink": "https://bucket.s3.amazonaws.com/selfie.jpg",
"socialContractLink": "https://bucket.s3.amazonaws.com/contract.pdf"
},
"application": "27c0767f-0abe-40ce-81d9-c168a71354b5"
}Response 200 OK:
O endpoint retorna o envelope padrão do serviço. O id do onboarding está em data.body.onBoardingId:
{
"status": 0,
"httpCode": 200,
"data": {
"status": "PROCESSING",
"body": {
"onBoardingId": "550e8400-e29b-41d4-a716-446655440000"
}
}
}⚠️ O formato do
onBoardingIdvaria conforme o provedor bancário. Dependendo do provider configurado para o seu tenant, ele pode ser um UUID (como acima) ou outra string opaca — não valide nem presuma o formato. Para o polling de status você nem precisa dele: oGET /checkOnboardingtambém aceita o CPF/CNPJ do titular (documentNumber), que é a opção recomendada e sempre funciona.
Erros comuns:
As falhas retornam { "message": "..." } com o status HTTP correspondente (veja Tratamento de Erros):
| HTTP | Causa típica | Ação |
|---|---|---|
400 | Dígito verificador de CPF/CNPJ inválido, endereço incompleto ou ausência do aninhamento person/legalPerson | Valide o documento e os campos obrigatórios antes do envio |
400 | MISSING_CLIENT_ID — tenant não identificado | Envie o header x-client-id (ou o campo application no corpo) |
400 | owners vazio, ou sócio sem fullName/documentNumber | Envie ao menos um sócio; o primeiro é registrado como representante legal |
400 | owner name "..." looks like the company name | O fullName do sócio recebeu o nome da empresa. Envie o nome civil da pessoa física; a razão social vai em businessName |
409/412 | E-mail ou documento já cadastrado | Use um e-mail único; verifique se já existe uma conta |
GET /v1/bank-accounts/checkOnboarding
Consulta o status do onboarding. Retorna o estado atual e os dados da conta (quando aprovada).
Query params:
| Param | Tipo | Obrigatório | Descrição |
|---|---|---|---|
onBoardingId | string | Sim | O CPF/CNPJ do titular da conta (recomendado) ou o valor de onBoardingId retornado pelo POST /create. Atenção ao case exato: onBoardingId (com B maiúsculo). |
Qual valor devo passar? Os dois funcionam — a busca casa tanto com o id de onboarding armazenado quanto com o documento do titular. Como o formato do id retornado pelo
/createvaria por provedor bancário (UUID em alguns, outros formatos em outros), a escolha mais segura é o CPF/CNPJ usado para criar a conta.Um
404(Banking account not found for the given onboardingId) significa que nenhuma conta corresponde àquele valor — verifique erros de digitação/formatação (apenas dígitos, sem pontos ou traços) e confirme que a conta foi criada por esta API.
Exemplo (consultando por CPF):
curl "https://baas-gtw.axiadigitalsolutions.com/v1/bank-accounts/checkOnboarding?onBoardingId=48059890093" \
-H "Authorization: Bearer eyJhbGci..." \
-H "x-client-id: 27c0767f-0abe-40ce-81d9-c168a71354b5"Response 200 OK (CONFIRMED):
{
"status": 0,
"httpCode": 200,
"when": 1710498645123,
"data": {
"status": "CONFIRMED",
"body": {
"clientCode": "tenant_xyz",
"account": {
"accountId": "30054029183",
"branch": "0001",
"account": "123456",
"documentNumber": "48059890093"
},
"traceId": "a1b2c3d4-...",
"biometricUrl": null
}
}
}Response 200 OK (PROCESSING, etapa de biometria pendente):
{
"status": 0,
"httpCode": 200,
"when": 1710498645123,
"data": {
"status": "PROCESSING",
"body": {
"clientCode": "tenant_xyz",
"account": {
"accountId": null,
"branch": "",
"account": "",
"documentNumber": "48059890093"
},
"traceId": "a1b2c3d4-...",
"biometricUrl": "https://kyc.provider.com/biometrics/abc123"
}
}
}Response 200 OK (ERROR, proposta reprovada):
{
"status": 0,
"httpCode": 200,
"when": 1710498645123,
"data": {
"status": "ERROR",
"body": {
"clientCode": "tenant_xyz",
"account": {
"accountId": null,
"branch": "",
"account": "",
"documentNumber": "29480535000199"
},
"traceId": "a1b2c3d4-...",
"biometricUrl": null,
"messages": [
{
"id": "onboarding-backgroundcheck",
"date": "2026-07-14T01:22:00.000Z",
"message": "Não conseguimos confirmar algumas das informações da sua proposta, para mais informações entre em contato com o SAC!",
"status": "proposal-reproved",
"actionRequired": false
}
]
}
}
}Uma reprovação pode chegar muito depois de o
POST /createter tido sucesso. Os background checks rodam de forma assíncrona — uma proposta aceita na criação pode ser reprovada horas depois. Continue consultando (ou assine oonboarding-backgroundcheck) até chegar emCONFIRMEDouERROR; não trate oPROCESSINGretornado pelo/createcomo final.
Campos de data:
| Campo | Descrição |
|---|---|
status | PROCESSING | CONFIRMED | ERROR |
body.account | Dados da conta — preenchidos assim que ela é confirmada |
body.biometricUrl | URL de verificação biométrica, presente enquanto a etapa de selfie/liveness estiver pendente. Encaminhe-a ao titular da conta. Também é entregue por push no webhook onboarding-biometrics quando fica disponível ou muda. |
body.messages | Motivos reportados pelo provedor bancário. Presente quando a proposta foi reprovada (status: ERROR) ou quando há uma pendência. Também é entregue por push no webhook onboarding-backgroundcheck na reprovação. |
Campos de body.messages[]:
| Campo | Descrição |
|---|---|
id | Processo que produziu a mensagem (ex.: onboarding-backgroundcheck, onboarding-biometrics) |
date | Timestamp da mensagem (ISO-8601) |
message | Motivo legível para humanos — é este o texto a ser exibido ao titular da conta |
status | Status bruto do provider, para diagnóstico (ex.: proposal-reproved) |
actionRequired | true quando o titular precisa agir (reenviar um documento, refazer a biometria) |
url | Link de ação, quando o provider fornece um |
Polling vs. webhook
Polling (GET checkOnboarding)
- Prós: simples, síncrono, sem necessidade de infraestrutura
- Contras: desperdício (muitas requisições), latência (atraso de 30s a 5 min)
- Recomendado para: janelas curtas (ex.: redirect in-app logo após a criação)
Webhook (eventos onboarding-*)
- Prós: tempo real, eficiente, orientado a eventos
- Contras: exige endpoint público e validação de assinatura
- Recomendado para: integrações de longa duração, jobs em background
- Assine
onboarding-create(conta confirmada),onboarding-biometrics(URL de biometria disponível/alterada) eonboarding-backgroundcheck(proposta reprovada, traz o motivo emmessages[]) viaPOST /v1/webhooks
Boa prática: use os dois — webhook como caminho rápido, polling como fallback com timeout.
Fluxo completo
const CLIENT_ID = process.env.BAAS_CLIENT_ID!; // seu tenant id (o mesmo do Client_ID do OAuth)
const documentNumber = '48059890093'; // CPF/CNPJ do titular
// 1. Cria a conta (assíncrono)
const createRes = await fetch('/v1/bank-accounts/create', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'x-client-id': CLIENT_ID,
'Content-Type': 'application/json'
},
body: JSON.stringify({
transactionPassword: 'ABC@123def',
person: { documentNumber, email: '[email protected]', /* ... */ },
application: CLIENT_ID
})
});
// O id do onboarding fica em data.body.onBoardingId (o formato varia por provider)
const created = await createRes.json();
const onBoardingId = created.data?.body?.onBoardingId;
// 2. Consulta com backoff exponencial (timeout de 5 min).
// Consultar pelo CPF/CNPJ do titular funciona em todos os providers — não é preciso
// depender do formato do id retornado pelo /create.
const startTime = Date.now();
let iteration = 0;
while (Date.now() - startTime < 5 * 60 * 1000) {
const checkRes = await fetch(
`/v1/bank-accounts/checkOnboarding?onBoardingId=${documentNumber}`,
{ headers: { 'Authorization': `Bearer ${token}`, 'x-client-id': CLIENT_ID } }
);
const { data } = await checkRes.json();
if (data.status === 'CONFIRMED') {
console.log('✓ Account ready:', data.body.account.accountId);
return data.body.account;
} else if (data.status === 'ERROR') {
throw new Error(`KYC rejected: ${data.body.messages?.[0]?.message || 'unknown'}`);
} else if (data.body.biometricUrl) {
console.log('⏳ Biometric step pending — send URL to the holder:', data.body.biometricUrl);
}
// Backoff: 30s → 1m → 2m (máx.)
const delay = Math.min(30000 * Math.pow(1.5, iteration), 2 * 60 * 1000);
await new Promise(r => setTimeout(r, delay));
iteration++;
}
throw new Error('Onboarding timeout (5 min)');Requisitos de KYC
Documentos aceitos:
- RG, CNH, passaporte, RNE (carteira de identidade, habilitação, passaporte, registro nacional de estrangeiro)
Padrões para a selfie:
- Rosto totalmente visível, sem óculos escuros
- Iluminação natural, bom contraste
- Foto recente (não a foto antiga do documento)
Endereço:
- CEP válido (compatível com a consulta de CEP)
- Endereço completo obrigatório
- Deve corresponder ao documento de identidade
Idade e PEP:
- Mínimo de 18 anos
- PEP (pessoa exposta politicamente) é reprovado automaticamente conforme regulação do Bacen
- Rechecagem quando
isPoliticallyExposedPerson=true
Envio de documentos
Faça o upload dos documentos antes de chamar o POST /create (ou use a API de arquivos da plataforma).
- Acessibilidade: as URLs devem ser publicamente legíveis (S3 presigned, GCS, Cloudflare, etc.)
- Formatos: apenas JPG e PNG
- Tamanho: no máximo 5 MB por arquivo
- Recomendação: suba para um object storage, gere as URLs presigned e passe-as ao endpoint de criação
GET /v1/bank-accounts/balance
Consulta o saldo da conta.
Query params:
| Param | Tipo | Obrigatório |
|---|---|---|
accountId | string | Sim |
documentNumber | string | Sim |
GET /v1/bank-accounts/history
Lista as transações de um período.
Query params:
| Param | Tipo | Obrigatório | Descrição |
|---|---|---|---|
accountId | string | Sim | Número da conta |
documentNumber | string | Sim | CPF/CNPJ |
initialDate | string | Sim | yyyy-MM-dd |
endDate | string | Sim | yyyy-MM-dd |
limit | number | Não | Tamanho da página |
page | number | Não | Número da página |
POST /v1/bank-accounts/generateInternalTransferRequest
Transferência entre contas da mesma instituição.
Headers:
x-client-id: <seu Client_ID (tenant id)>
Idempotency-Key: <uuid> (recomendado)Request Body:
{
"accountIdFrom": "30054029183",
"accountIdTo": "30054029184",
"amount": 100.50,
"description": "Optional note"
}POST /v1/bank-accounts/generateExternalTransferRequest
Transferência para outro banco (TED — Transferência Eletrônica Disponível).
Headers:
x-client-id: <seu Client_ID (tenant id)>
Idempotency-Key: <uuid> (recomendado)Request Body:
{
"userId": "cfd11a01-293d-4573-9d28-2d7261d79aaf",
"onBoardingId": "48059890093",
"idAccount": "30054029183",
"document": "11122233344",
"accountCode": "123",
"digitCode": "2",
"branchCode": "371",
"institutionCode": 341,
"name": "Recipient Name",
"value": 67.90,
"bankAccountType": "CACC",
"institutionIspb": "30306294"
}POST /v1/bank-accounts/closeAccount
Encerra uma conta.
Request Body:
{
"account": "30054029183",
"reason": "User request"
}