Referência da API

API REST de recebimento por PIX. Você cria o PIX direto do seu site, sem produto nem checkout, consulta o status e recebe webhooks assinados quando ele é pago. O saque é feito pelo painel.

Visão geral

Todas as rotas ficam sob a URL base ao lado e trocam JSON em UTF-8. Valores sempre em centavos (BRL). Listagens são paginadas por cursor.

URL basehttps://bravoselect.com/api/v1
AutenticaçãoAuthorization: Bearer sk_live_...
Formatoapplication/json
IdempotênciaHeader Idempotency-Key no POST /transactions (24h)
WebhooksHMAC-SHA256 no header Webhook-Signature

Integração discreta

Chame a API sempre do seu servidor. Para o navegador do cliente devolva só o copia e cola do PIX: a chave, a URL da API e os webhooks ficam fora do código que o cliente vê. Chaves, headers e webhooks não levam marca nenhuma.
URL base
https://bravoselect.com/api/v1
Cabeçalhos
Authorization: Bearer sk_live_sua_chave
Content-Type: application/json

Autenticação

Gere a chave em API Keys. Ela aparece inteira uma única vez. Envie no header Authorization: Bearer(o header X-Api-Key também é aceito). Se vazar, revogue no painel e gere outra.

Exemplo
curl https://bravoselect.com/api/v1/me \
  -H "Authorization: Bearer sk_live_sua_chave"

Erros

Use error.code no seu código (é estável); error.message é texto para pessoas.

CódigoHTTPQuando
unauthorized401Chave ausente, inválida ou revogada.
transaction_not_found404O PIX não existe ou é de outra conta.

Se a geração do PIX falhar por instabilidade momentânea, a resposta vem com status 202 e "status": "retrying": repita a chamada com a mesma Idempotency-Key.

Corpo de erro
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid API key"
  }
}

Criar PIX

POST/transactions

Cria a cobrança PIX e devolve o copia e cola. Não precisa cadastrar produto. Mostre pix.copy_paste ao cliente (e gere o QR a partir dele).

Corpo

amount_centsintegerobrigatório
Valor em centavos. Mínimo 500 (R$ 5,00).
customer.namestringopcional
Nome do pagador.
customer.emailstringopcional
E-mail do pagador.
customer.cpfstringopcional
CPF ou CNPJ do pagador (só números).
customer.phonestringopcional
Telefone com DDD.
descriptionstringopcional
Descrição da cobrança (até 300 caracteres).
external_referencestringopcional
Seu id do pedido. Volta na consulta e nos webhooks.
metadataobjectopcional
Chave→valor livre (até 20 chaves). Volta intacto nos webhooks.
expires_inintegeropcional
Validade do PIX em segundos (60 a 86400).
utmobjectopcional
source, medium, campaign, content, term, fbclid, ttclid, gclid.
splitobject | arrayopcional
Repasse automático de parte da venda para outra conta (até 10 recebedores): recipient (e-mail ou id da conta), percent e/ou amount_cents.
POST /transactions
curl -X POST https://bravoselect.com/api/v1/transactions \
  -H "Authorization: Bearer sk_live_sua_chave" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-42" \
  -d '{
    "amount_cents": 19700,
    "customer": {
      "name": "Maria Souza",
      "email": "maria@email.com",
      "cpf": "12345678909",
      "phone": "11999999999"
    },
    "description": "Pedido #42",
    "external_reference": "pedido-42",
    "metadata": { "loja": "principal" },
    "utm": { "source": "fb", "campaign": "black" }
  }'
Resposta200
{
  "id": "cmabc123xyz",
  "object": "transaction",
  "status": "PENDING",
  "method": "PIX",
  "amount_cents": 19700,
  "fee_cents": 1576,
  "net_cents": 18124,
  "currency": "BRL",
  "pix": {
    "copy_paste": "00020126580014BR.GOV.BCB.PIX...",
    "expires_at": "2026-11-09T16:30:00.000Z"
  },
  "split": null,
  "splits": null,
  "created_at": "2026-11-09T15:30:00.000Z"
}

Consultar PIX

GET/transactions/{id}

Status possíveis: PENDING, PAID, EXPIRED, REFUNDED, FAILED. Prefira o webhook; consulte só como conferência.

GET /transactions/{id}
curl https://bravoselect.com/api/v1/transactions/cmabc123xyz \
  -H "Authorization: Bearer sk_live_sua_chave"
Resposta200
{
  "id": "cmabc123xyz",
  "object": "transaction",
  "customer": { "email": "...", "name": "...", "cpf": "...", "phone": "..." },
  "amount_cents": 19700,
  "fee_cents": 1576,
  "net_cents": 18124,
  "currency": "BRL",
  "method": "PIX",
  "status": "PAID",
  "pix": {
    "qr_code": null,
    "copy_paste": "00020126580014BR.GOV.BCB.PIX...",
    "expires_at": "2026-11-09T16:30:00.000Z"
  },
  "tracking": { "utm_source": "fb", "utm_campaign": "black", "...": "..." },
  "external_reference": "pedido-42",
  "metadata": { "loja": "principal" },
  "paid_at": "2026-11-09T15:31:40.000Z",
  "created_at": "2026-11-09T15:30:00.000Z"
}

Listar PIX

GET/transactions
limitintegeropcional
Itens por página (até 100). Padrão 20.
cursorstringopcional
next_cursor da página anterior.
statusstringopcional
Filtra por status.
external_referencestringopcional
Filtra pelo seu id do pedido.
created_at_from / created_at_toISO 8601opcional
Intervalo de criação.
GET /transactions
curl "https://bravoselect.com/api/v1/transactions?status=PAID&limit=50" \
  -H "Authorization: Bearer sk_live_sua_chave"
Resposta200
{
  "data": [ { "id": "cmabc123xyz", "object": "transaction", "status": "PAID", "...": "..." } ],
  "has_more": true,
  "next_cursor": "cmabc120aaa"
}

Saldo

GET/balance

available_cents é o que já pode ser sacado (o saque é feito no painel); pending_pix_cents são vendas pagas ainda em liberação.

GET /balance
curl https://bravoselect.com/api/v1/balance -H "Authorization: Bearer sk_live_sua_chave"
Resposta200
{
  "object": "balance",
  "currency": "BRL",
  "available_cents": 128450,
  "pending_pix_cents": 19700,
  "in_withdrawal_cents": 0,
  "upcoming_releases": []
}

Conta atual

GET/me

Útil para testar a chave.

GET /me
curl https://bravoselect.com/api/v1/me -H "Authorization: Bearer sk_live_sua_chave"
Resposta200
{
  "object": "account",
  "id": "cmusr123",
  "email": "voce@empresa.com",
  "name": "Sua Empresa",
  "balance_cents": 128450,
  "pending_balance_cents": 19700,
  "currency": "BRL"
}

Eventos

Cadastre a URL em Integrações → Webhooks. Cada evento chega como POST com o envelope ao lado. O id é o mesmo nas retentativas: use para não processar duas vezes.

transaction.createdPIX gerado.
transaction.paidPIX pago. É o evento para liberar o pedido.
transaction.expiredPIX venceu sem pagamento.
transaction.refundedPagamento devolvido (MED/estorno).
transaction.failedFalha na geração.
Envelope
{
  "id": "evt_cmdel123",
  "type": "transaction.paid",
  "created": 1794231100,
  "data": { /* objeto do PIX, ao lado */ }
}

Objeto do evento

O data traz o PIX com external_reference, metadata, cliente e UTMs, para você conciliar com o seu pedido.

data
{
  "id": "cmabc123xyz",
  "amount_cents": 19700,
  "fee_cents": 1576,
  "net_cents": 18124,
  "currency": "BRL",
  "method": "PIX",
  "status": "PAID",
  "external_reference": "pedido-42",
  "metadata": { "loja": "principal" },
  "customer": { "email": "...", "name": "...", "cpf": "...", "phone": "..." },
  "tracking": { "utm_source": "fb", "...": "..." },
  "receipt_url": null,
  "paid_at": "2026-11-09T15:31:40.000Z",
  "created_at": "2026-11-09T15:30:00.000Z"
}

Assinatura

O header Webhook-Signature (também enviado como X-Webhook-Signature) traz t (timestamp) e v1 = HMAC-SHA256 de `${t}.${corpo}` com o segredo whsec_... do webhook. Recuse se a assinatura não bater ou se o t tiver mais de 5 minutos.

Header
Webhook-Signature: t=1794231100,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
Verificação
import crypto from "node:crypto";

// rawBody = corpo EXATO recebido (string), antes de JSON.parse
function verificar(rawBody, header, secret, toleranciaSeg = 300) {
  const partes = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(partes.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > toleranciaSeg) return false;
  const esperado = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rawBody}`)
    .digest("hex");
  return crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(partes.v1 ?? ""));
}

Retentativas

Responda com qualquer status 2xx em até 10 segundos. Fora disso o evento é reenviado até 8 vezes: 30s, 2min, 10min, 30min, 1h, 3h, 6h e 24h.

Quickstart

O fluxo inteiro: o seu servidor cria o PIX, a sua página mostra o copia e cola e o webhook transaction.paid confirma o pagamento.

Node.js
// No SEU servidor (a chave nunca vai para o navegador)
const res = await fetch("https://bravoselect.com/api/v1/transactions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PIX_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": pedido.id,
  },
  body: JSON.stringify({
    amount_cents: pedido.totalCentavos,
    customer: { name: pedido.nome, email: pedido.email, cpf: pedido.cpf },
    external_reference: pedido.id,
  }),
});
const pix = await res.json();

// Devolva para a sua página só o copia e cola (e gere o QR a partir dele)
return { copiaECola: pix.pix.copy_paste, expiraEm: pix.pix.expires_at };

// Quando pagar, chega no seu webhook: type "transaction.paid"