# Bravive Banking — API pública v1 (documentação completa para LLMs) Arquivo texto na raiz do site (`/llm.txt`). Espelha a documentação humana em `/documentation`. Em caso de divergência, prevalece o comportamento real da API. -------------------------------------------------------------------------------- ## Visão geral - Base path: `/api/v1` no mesmo host da aplicação. - Content-Type típico: `application/json` nos bodies POST. - Valores monetários: números inteiros em centavos. - Datas: ISO 8601 quando indicado (ex.: `2026-04-15`, `2026-04-01T12:00:00.000Z`). - Erros (formato típico): `{ error: string; code: string }`. - Campos `taxNumber` podem vir mascarados nas respostas. -------------------------------------------------------------------------------- ## Autenticação Todas as rotas exigem: Authorization: Bearer Onde `` é Base64 (RFC 4648, sem quebras de linha) da string literal: : Passos: 1. Concatenar `clientId`, dois-pontos `:` e `secret`. 2. Codificar em Base64. 3. Enviar no header acima. Credenciais: Developer Hub — rota `/user/api-keys`. -------------------------------------------------------------------------------- ## Convenção webhook inline Campo opcional no JSON de algumas operações: webhookUrl (string, opcional): URL HTTPS para receber o callback desta operação. Substitui temporariamente o webhook global cadastrado apenas para essa requisição. Endpoints que aceitam `webhookUrl`: POST `/pix/send`, POST `/pix/qrcode`, POST `/ted/send`, POST `/boleto/generate`. -------------------------------------------------------------------------------- # ENDPOINTS ================================================================================ ## POST /api/v1/pix/send Descrição: Envia um PIX para uma chave (CPF, CNPJ, email, telefone ou EVP). ### Entrada (JSON body) | Campo | Tipo | Obrigatório | Descrição | |----------------|---------|-------------|-----------| | key | string | sim | Chave PIX de destino. | | amount | number | sim | Valor em centavos. | | description | string | não | Descrição da transferência no extrato. | | webhookUrl | string | não | URL HTTPS para callback desta operação (inline). | | idempotencyKey | string | não | Chave de idempotência (máx. 64 chars). Retorna o registro já criado sem duplicar. | Tipo resumido: { key: string; amount: number; description?: string; webhookUrl?: string; idempotencyKey?: string } ### Exemplo de request { "key": "email@cliente.com", "amount": 15990, "description": "Pagamento de servico", "webhookUrl": "https://meusite.com/webhooks/pix" } ### Saída (HTTP 200, JSON) Tipo: { id: string; status: "pending" | "processing" } ### Exemplo de response { "id": "pix_01JABCDEF12345", "status": "pending" } ================================================================================ ## POST /api/v1/pix/qrcode Descrição: Gera cobrança PIX com payload EMV (`code`) e imagem QR em base64 PNG (`qrcode`). ### Entrada (JSON body) | Campo | Tipo | Obrigatório | Descrição | |----------------|---------------|-------------|-----------| | amount | number | sim | Valor em centavos. Use 0 para QR aberto. | | description | string | não | Descrição opcional da cobrança. | | split | SplitItem[] | não | Repasses automáticos ao confirmar pagamento. Máx 10 itens. A soma dos amounts não pode exceder o valor líquido (após taxa). | | webhookUrl | string | não | URL HTTPS para callback desta operação (inline). | | idempotencyKey | string | não | Chave de idempotência (máx. 64 chars). Retorna o registro já criado sem duplicar. | Estrutura do `SplitItem`: - `recipientId` (string, obrigatório): ID público do recebedor (prefixo `rec_`, gerado ao habilitar split na conta). - `amount` (number, obrigatório): Valor em centavos a ser repassado. - `description` (string, opcional): Descrição do repasse (máx. 140 chars). Tipo resumido: { amount: number; description?: string; split?: { recipientId: string; amount: number; description?: string }[]; webhookUrl?: string; idempotencyKey?: string } Notas: - amount: 0 = QR aberto. - code = EMV; qrcode = base64 PNG. - `id` = UUID do pagamento na Bravive (mesmo `id` no webhook `payment`). ### Exemplo de request { "amount": 19990, "description": "Cobranca de pedido #123", "split": [ { "recipientId": "rec_abc123def456", "amount": 5000, "description": "Comissao do vendedor" } ], "webhookUrl": "https://meusite.com/webhooks/pagamento" } ### Saída (HTTP 200, JSON) Tipo: { id: string; code: string; qrcode: string } ### Exemplo de response { "id": "f112f47f-bd7a-4801-af57-44a058f10864", "code": "00020126580014BR.GOV.BCB.PIX...", "qrcode": "iVBORw0KGgoAAAANSUhEUgAA..." } ================================================================================ ## GET /api/v1/pix/info/:key Descrição: Consulta dados do favorecido pela chave PIX informada. ### Entrada - Path parameter: `key` — chave PIX (URL-encoded quando necessário). Sem query obrigatória. Sem body. ### Saída (HTTP 200, JSON) Tipo: { name: string; taxNumber: string; bank: string; institution: string } ### Exemplo de response { "name": "Maria Santos", "taxNumber": "***.123.***-**", "bank": "033", "institution": "Banco Santander" } ================================================================================ ## POST /api/v1/ted/send Descrição: Cria saque TED pendente (valor em centavos). O envio à instituição segue o mesmo fluxo do PIX out (aprovação no admin ou `withdrawal_auto_approve` no tenant). ### Entrada (JSON body) | Campo | Tipo | Obrigatório | Descrição | |---------------------|------------------------------|-------------|-----------| | amount | number | sim | Valor em centavos. | | to.name | string | sim | Nome do favorecido. | | to.taxNumber | string | sim | CPF ou CNPJ do favorecido. | | to.bank | string | sim | Código COMPE do banco (3 dígitos, ex.: 033). | | to.branch | string | sim | Agência bancária. | | to.account | string | sim | Número da conta sem dígito. | | to.accountDigit | string | sim | Dígito da conta. | | to.accountType | "checking" \| "savings" | sim | Tipo da conta. | | description | string | não | Descrição da TED. | | scheduleDate | string | não | **Não suportado** — se enviado, a API retorna erro. Omita. | | webhookUrl | string | não | URL HTTPS para callback (inline). | | idempotencyKey | string | não | Chave de idempotência (máx. 64 chars). Retorna o registro já criado sem duplicar. | Tipo resumido: { amount: number; to: { name: string; taxNumber: string; bank: string; branch: string; account: string; accountDigit: string; accountType: "checking" | "savings"; }; description?: string; scheduleDate?: string; webhookUrl?: string; idempotencyKey?: string; } Notas: - `id` na resposta = UUID do saque na Bravive (mesmo `id` no webhook `withdrawal`). - Agendamento (`scheduleDate`) não é suportado nesta API. ### Exemplo de request { "amount": 289900, "to": { "name": "Fornecedor XPTO LTDA", "taxNumber": "12345678000199", "bank": "033", "branch": "0001", "account": "123456", "accountDigit": "7", "accountType": "checking" }, "webhookUrl": "https://meusite.com/webhooks/ted" } ### Saída (HTTP 200, JSON) Tipo: { id: string; status: "pending" } ### Exemplo de response { "id": "f112f47f-bd7a-4801-af57-44a058f10864", "status": "pending" } ================================================================================ ## POST /api/v1/boleto/generate Descrição: Gera boleto com pagador, vencimento e regras opcionais (multa/juros/desconto conforme produto). ### Entrada (JSON body) | Campo | Tipo | Obrigatório | Descrição | |---------------------------|---------|-------------|-----------| | amount | number | sim | Valor em centavos. | | dueDate | string | sim | Data de vencimento (ISO 8601). | | customer.name | string | sim | Nome do pagador. | | customer.taxNumber | string | sim | CPF ou CNPJ do pagador. | | customer.email | string | sim | E-mail para envio do boleto. | | customer.phone | string | não | Telefone do pagador. | | customer.address.street | string | sim | Logradouro. | | customer.address.city | string | sim | Cidade. | | customer.address.state | string | sim | UF com 2 letras. | | customer.address.zipCode | string | sim | CEP. | | description | string | não | Descrição da cobrança. | | webhookUrl | string | não | URL HTTPS para callback (inline). | | idempotencyKey | string | não | Chave de idempotência (máx. 64 chars). Retorna o registro já criado sem duplicar. | Tipo resumido: { amount: number; dueDate: string; customer: { name: string; taxNumber: string; email: string; phone?: string; address: { street: string; city: string; state: string; zipCode: string }; }; description?: string; webhookUrl?: string; idempotencyKey?: string; } ### Exemplo de request { "amount": 19990, "dueDate": "2026-04-15", "customer": { "name": "Joao Silva", "taxNumber": "12345678909", "email": "joao@cliente.com", "address": { "street": "Rua A, 123", "city": "Sao Paulo", "state": "SP", "zipCode": "01001000" } }, "webhookUrl": "https://meusite.com/webhooks/boleto" } ### Saída (HTTP 200, JSON) Tipo: { id: string; barcode: string; digitableLine: string; pdfUrl: string; dueDate: string; amount: number; } ### Exemplo de response { "id": "bol_01JABCDE123", "barcode": "23793381286000300004509000123456781234567890", "digitableLine": "23790.90001 23456.781234 56789.012345 6 00030000450000", "pdfUrl": "https://api.bravive.com/boletos/bol_01JABCDE123.pdf", "dueDate": "2026-04-15", "amount": 19990 } ================================================================================ ## GET /api/v1/boleto/:id Descrição: Retorna dados e status atual de um boleto pelo ID. ### Entrada - Path parameter: `id` — identificador do boleto. Sem query obrigatória. Sem body. ### Saída (HTTP 200, JSON) Tipo: { id: string; status: "pending" | "paid" | "expired" | "cancelled"; amount: number; paidAmount?: number; paidAt?: string; dueDate: string; barcode: string; pdfUrl: string; } ### Exemplo de response { "id": "bol_01JABCDE123", "status": "paid", "amount": 19990, "paidAmount": 19990, "paidAt": "2026-04-14T11:20:10.000Z", "dueDate": "2026-04-15", "barcode": "23793381286000300004509000123456781234567890", "pdfUrl": "https://api.bravive.com/boletos/bol_01JABCDE123.pdf" } ================================================================================ ## GET /api/v1/balance Descrição: Consulta saldo disponível e saldo bloqueado da conta. ### Entrada Sem body. Sem query obrigatória. ### Saída (HTTP 200, JSON) Tipo: { available: number; blocked: number } Ambos em centavos. ### Exemplo de response { "available": 1567430, "blocked": 50000 } ================================================================================ ## GET /api/v1/payments Descrição: Lista pagamentos com filtros por período/método/status e paginação por cursor. ### Entrada (query string) | Campo | Tipo | Obrigatório | Descrição | |--------|--------|-------------|-----------| | from | string | não | Data inicial YYYY-MM-DD. | | to | string | não | Data final YYYY-MM-DD. | | method | string | não | Método: pix, boleto. | | status | string | não | Status: pending, paid, failed, cancelled, expired, refunded. | | limit | number | não | Máximo de itens por página. | | cursor | string | não | Cursor de paginação (próxima página). | Exemplo de query: ?from=2024-01-01&to=2024-01-31&method=pix&status=paid&limit=50&cursor=xxx ### Saída (HTTP 200, JSON) Tipo: { data: Payment[]; nextCursor?: string } Onde `Payment` inclui: id: string; method: string; status: string; amount: number; fee: number; payerName?: string; payerDocument?: string; description?: string; pixCopyPaste?: string; digitableLine?: string; createdAt: string; ### Exemplo de response { "data": [ { "id": "pay_01JABCDE", "method": "pix", "status": "paid", "amount": 1200, "fee": 50, "payerName": "João Silva", "payerDocument": "12345678909", "description": "Pagamento de teste", "pixCopyPaste": "000201...", "createdAt": "2026-03-27T12:00:00.000Z" } ], "nextCursor": "pay_01JABCDE" } ================================================================================ ## GET /api/v1/payments/:id Descrição: Detalhe de um pagamento específico. ### Entrada - Path parameter: `id` — identificador do pagamento. ### Saída (HTTP 200, JSON) Tipo: objeto `Payment` (mesmo conceito da lista). ### Exemplo de response { "id": "pay_01JABCDE", "method": "pix", "status": "paid", "amount": 1200, "fee": 50, "payerName": "João Silva", "payerDocument": "12345678909", "description": "Pagamento de teste", "pixCopyPaste": "000201...", "createdAt": "2026-03-27T12:00:00.000Z" } ================================================================================ ## GET /api/v1/withdrawals Descrição: Lista saques (withdrawals) com filtros por período/método/status e paginação por cursor. ### Entrada (query string) | Campo | Tipo | Obrigatório | Descrição | |--------|--------|-------------|-----------| | from | string | não | Data inicial YYYY-MM-DD. | | to | string | não | Data final YYYY-MM-DD. | | method | string | não | Método: pix, ted. | | status | string | não | Status: pending, processing, completed, failed, cancelled. | | limit | number | não | Máximo de itens por página. | | cursor | string | não | Cursor de paginação (próxima página). | Exemplo de query: ?from=2024-01-01&to=2024-01-31&method=pix&status=completed&limit=50&cursor=xxx ### Saída (HTTP 200, JSON) Tipo: { data: Withdrawal[]; nextCursor?: string } Onde `Withdrawal` inclui: id: string; method: string; status: string; amount: number; fee: number; pixKey?: string; pixKeyType?: string; bankCode?: string; branch?: string; accountNumber?: string; accountDigit?: string; accountType?: string; accountHolderName?: string; document?: string; description?: string; createdAt: string; ### Exemplo de response { "data": [ { "id": "wth_01JABCDE", "method": "pix", "status": "completed", "amount": 10000, "fee": 100, "pixKey": "test@pix.com", "pixKeyType": "email", "accountHolderName": "Maria Souza", "document": "98765432100", "description": "Saque PIX", "createdAt": "2026-03-27T12:00:00.000Z" } ], "nextCursor": "wth_01JABCDE" } ================================================================================ ## GET /api/v1/withdrawals/:id Descrição: Detalhe de um saque específico. ### Entrada - Path parameter: `id` — identificador do saque. ### Saída (HTTP 200, JSON) Tipo: objeto `Withdrawal` (mesmo conceito da lista). ### Exemplo de response { "id": "wth_01JABCDE", "method": "pix", "status": "completed", "amount": 10000, "fee": 100, "pixKey": "test@pix.com", "pixKeyType": "email", "accountHolderName": "Maria Souza", "document": "98765432100", "description": "Saque PIX", "createdAt": "2026-03-27T12:00:00.000Z" } -------------------------------------------------------------------------------- # WEBHOOKS Cadastro global: rota `/user/webhook` no painel. Tipos de evento escolhidos no cadastro disparam para a URL configurada. Modos: 1. Webhook global — todos os eventos do tipo vão para a URL cadastrada. 2. Webhook inline — campo `webhookUrl` no body de operações suportadas; callback vai só para essa URL naquela operação. Validação de assinatura: - Header em todas as requisições (globais ou inline): `X-Webhook-Secret` com o segredo definido no cadastro. Exemplo de validação (Node.js): const secret = req.headers["x-webhook-secret"]; if (secret !== process.env.WEBHOOK_SECRET) { return res.status(401).end(); } ### Estrutura geral do payload (JSON) | Campo | Tipo | Descrição | |-------------|------------------------------|-----------| | event | "payment" \| "withdrawal" | Tipo do evento. | | id | string | ID único do disparo. | | created_at | string | ISO 8601 do momento do evento. | | data.id | string | ID do recurso. | | data.type | "payment" \| "withdrawal" | Origem do evento. | | data.method | string | pix, boleto ou ted. | | data.amount | number | Valor em centavos. | | data.status | string | Status atual do recurso. | Campos adicionais em `data` podem existir conforme o evento (ex.: payer_name, paid_at, fee, amount_net). Ao cadastrar webhook global, cada tipo dispara para todos os status daquele recurso. --- ## Evento: payment Descrição: Pagamentos recebidos (PIX in, boleto). Disparado para todos os status. ### Status (valor → descrição) | Status | Descrição | |-----------|------------------------| | pending | Aguardando pagamento | | paid | Pago e confirmado | | expired | Expirou sem pagamento | | canceled | Cancelado | | reversed | Estornado | | failed | Falhou | ### Exemplo de payload { "event": "payment", "id": "evt_01JABCDEF", "created_at": "2026-04-01T12:00:00.000Z", "data": { "id": "pay_01JABCDEF", "type": "payment", "method": "pix", "amount": 19990, "status": "paid", "payer_name": "João Silva", "payer_document": "***.123.***-**", "paid_at": "2026-04-01T12:00:00.000Z" } } --- ## Evento: withdrawal Descrição: Saques (PIX out, TED). Disparado para todos os status. ### Status (valor → descrição) | Status | Descrição | |-------------|--------------------------| | pending | Aguardando processamento | | processing | Em processamento | | completed | Concluído com sucesso | | failed | Falhou | | canceled | Cancelado | ### Exemplo de payload { "event": "withdrawal", "id": "evt_01JABCDEF", "created_at": "2026-04-01T14:00:00.000Z", "data": { "id": "wth_01JABCDEF", "type": "withdrawal", "method": "pix", "amount": 50000, "amount_net": 49950, "fee": 50, "status": "completed", "processed_at": "2026-04-01T14:00:00.000Z" } } ### Boas práticas do receptor - Retorne HTTP 200 rapidamente e processe o payload de forma assíncrona. - Use o campo `id` do evento para idempotência / evitar reprocessamento em reenvios. - Apenas URLs HTTPS são aceitas (cadastro global e inline). - Timeout de entrega ~10s; acima disso pode haver reenvio. -------------------------------------------------------------------------------- ## Splits de Pagamento (Marketplace) O split permite que parte do valor de um pagamento PIX recebido seja automaticamente repassado para uma ou mais contas cadastradas sob o mesmo tenant (plataforma/marketplace). ### Funcionamento e Regras: 1. **Destinatário ativo**: A conta de destino deve ter habilitado "Recebimento de Split" no painel (`/user/api-keys`), obtendo um ID público de recebedor com o prefixo `rec_`. 2. **Criação**: No endpoint `POST /pix/qrcode`, envia-se a lista de splits no parâmetro `split[]`. 3. **Limites**: Máximo de 10 splits por pagamento. A soma de todos os splits não pode exceder o valor líquido do pagamento (após dedução da taxa do PIX in). 4. **Liquidação**: O repasse é executado automaticamente via transferência interna P2P após a confirmação do pagamento (Status `paid`). O saldo é creditado na conta receptora assim que confirmado. -------------------------------------------------------------------------------- ## Exemplo mínimo de chamada autenticada (Node.js) const token = Buffer.from(`${clientId}:${secret}`).toString("base64"); await fetch(`${origin}/api/v1/balance`, { headers: { Authorization: `Bearer ${token}` }, }); -------------------------------------------------------------------------------- Documentação HTML detalhada: /documentation Credenciais: /user/api-keys Webhooks (painel): /user/webhook