a plataformaDesenvolvedores API v1

Documentação

API de a plataforma

Consulte saldo, leia o extrato e faça transferências direto do seu sistema. Autenticação por chave, respostas em JSON, valores em decimal.

Como começar

  1. 1

    Gere sua chave

    No app, em Mais → Credenciais de API. A chave aparece uma única vez: guarde na hora.

  2. 2

    Teste com valores pequenos

    Não há sandbox: sk_test_ e sk_live_ movem dinheiro real na sua conta. O prefixo é só um rótulo para organizar as chaves. Para experimentar, use valores baixos.

  3. 3

    Confira com GET /v1/me

    Antes de qualquer integração, veja se a chave responde e quais escopos ela carrega.

Integrar usando IA

Esta documentação existe também em um arquivo de texto feito para assistentes de programação. Mande o endereço para a sua IA, ou abra e cole o conteúdo — ela terá os endpoints, os formatos e os erros exatos, sem precisar adivinhar.

Abrir o arquivo

Peça algo como: “integre esta API de pagamento no meu sistema seguindo esta documentação”, com o arquivo junto.

Autenticação

Envie a chave no header Authorization. Ela identifica a conta: não há parâmetro de conta em nenhuma rota, e uma chave nunca alcança dados de outra.

curl /v1/me \
  -H "Authorization: Bearer sk_test_sua_chave_aqui"

A chave é uma senha

Guarde no servidor, nunca no código do navegador nem no app. Quem tem a chave move o dinheiro da conta. Se vazar, revogue no painel — a revogação vale na hora.

Tentativas de autenticação com chave inválida são limitadas por IP de origem. A resposta não muda por causa disso: sempre 401, nunca um código diferente.

Toda chave pode restringir por IP, em Credenciais. Sem lista configurada (o padrão), não há restrição nenhuma.

Endpoints

GET/v1/me

Verificar a chave

Devolve o ambiente, os escopos e a conta associada. Use para conferir a integração antes de qualquer outra chamada.

Resposta

{
  "environment": "test",
  "scopes": ["balance:read", "transactions:read"],
  "account": { "id": "8d1e6211-..." },
  "tenant": { "slug": "sua-marca" },
  "permissions": {
    "balance": true,
    "transactions": true,
    "transfers": false
  }
}
GET/v1/balancebalance:read

Consultar saldo

O saldo disponível, o retido e o que pode ser gasto agora. Valores em decimal com duas casas.

Resposta

{
  "available": "8589.10",
  "held": "0.00",
  "spendable": "8589.10"
}
GET/v1/transactions?limit=25&offset=0transactions:read

Listar movimentações

Extrato paginado. Aceita limit (até 100) e offset. Ordenado da mais recente para a mais antiga.

Resposta

{
  "items": [
    {
      "id": "6b346bc2-...",
      "type": "INTERNAL_TRANSFER",
      "direction": "OUT",
      "amount": "150.00",
      "description": "Pagamento de fornecedor",
      "createdAt": "2026-09-06T04:12:00.000Z"
    }
  ],
  "total": 42
}
GET/v1/transactions/{id}transactions:read

Detalhe de uma movimentação

O comprovante completo, com contraparte e taxas. É o que você mostra ao seu usuário como recibo.

Resposta

{
  "id": "6b346bc2-...",
  "status": "SETTLED",
  "amount": "150.00",
  "fee": "0.50",
  "counterparty": { "name": "Padaria Central" },
  "settledAt": "2026-09-06T04:12:00.000Z"
}
POST/v1/payment-linkspix:write

Criar link de pagamento

Uma página hospedada que fica aberta e recebe de várias pessoas, até ser cancelada ou expirar. Diferente da cobrança avulsa, que é um QR para um pagamento só. Use link quando o valor for divulgado: uma vaquinha, uma mensalidade, um catálogo.

Corpo

{
  "description": "Mensalidade de setembro",
  "amount": "99.90",
  "singleUse": false,
  "expiresInHours": 720,
  "requirePayerName": true
}

Resposta

{
  "id": "4f21c8de-...",
  "slug": "k3n8vq2p",
  "url": "https://seu-banco.com/pagar/k3n8vq2p",
  "description": "Mensalidade de setembro",
  "amount": "99.90",
  "amountOpen": false,
  "singleUse": false,
  "status": "open"
}
GET/v1/payment-linkspix:read

Listar links

Os links da conta, com quanto cada um já recebeu e quantos pagamentos teve.

Resposta

{
  "items": [
    {
      "id": "4f21c8de-...",
      "slug": "k3n8vq2p",
      "url": "https://seu-banco.com/pagar/k3n8vq2p",
      "description": "Mensalidade de setembro",
      "amount": "99.90",
      "singleUse": false,
      "uses": 12,
      "status": "open",
      "received": "1198.80",
      "payments": 12
    }
  ]
}
POST/v1/payment-links/{id}/cancelpix:write

Cancelar link

Fecha o link. Quem abrir depois vê que não está mais disponível; os pagamentos já recebidos continuam na conta.

Resposta

{
  "id": "4f21c8de-...",
  "status": "cancelled"
}
POST/v1/transferstransfers:writeidempotente

Transferir

Move dinheiro da sua conta para outra da mesma plataforma. O destino pode ser o apelido (@loja ou loja) ou o id da conta.

Corpo

{
  "to": "padaria",
  "amount": "150.00",
  "description": "Pagamento do pedido 8842"
}

Resposta

{
  "id": "6b346bc2-...",
  "status": "SETTLED",
  "amount": "150.00",
  "fee": "0.50",
  "to": { "id": "c24b7e31-...", "name": "Padaria Central" },
  "replayed": false
}
POST/v1/pix/chargespix:writeidempotente

Cobrar por Pix

Cobrança avulsa: um QR para um pagamento. Devolve o código copia-e-cola, que também serve para gerar o QR. Não cria link nem página pública — use quando o pedido já existe no seu sistema e só falta receber. O pagamento cai direto na sua conta e você é avisado pelo webhook charge.paid. Opcional `split`: a cobrança já pode nascer dividida entre até 5 contas destino (CPF, CNPJ ou e-mail) — a fatia de cada uma é creditada automaticamente no instante em que é paga, sem chamada extra.

Corpo

{
  "amount": "49.90",
  "description": "Pedido #1234",
  "expiresIn": 3600,
  "payer": {
    "name": "Maria Silva",
    "email": "maria@exemplo.com",
    "document": "12345678901"
  },
  "externalReference": "pedido-1234",
  "split": [
    { "destination": "anunciante@exemplo.com", "percentage": "10" }
  ]
}

Resposta

{
  "id": "e636775c-...",
  "status": "open",
  "amount": "49.90",
  "description": "Pedido #1234",
  "qrCode": "00020101021226830014br.gov.bcb.pix...",
  "copyPaste": "00020101021226830014br.gov.bcb.pix...",
  "expiresAt": "2026-09-10T00:35:19.836Z",
  "externalReference": "pedido-1234",
  "split": [
    { "destinationSellerId": "7ec3...", "percentage": "10" }
  ]
}
Este campo `split` é avulso: vale só para esta cobrança, definido na criação. Para uma regra que passa a valer automaticamente sobre tudo que a conta recebe a partir de agora — Pix, boleto pago e transferência interna recebida, não só cobranças feitas com este campo — use PUT /v1/split.
GET/v1/pix/charges/{id}pix:read

Consultar cobrança

Estado atual da cobrança. Use para conferir um pagamento pontual — para acompanhar em tempo real, prefira o webhook: consultar em laço gasta requisição e chega depois.

Resposta

{
  "id": "e636775c-...",
  "status": "paid",
  "amount": "49.90",
  "description": "Pedido #1234",
  "paidAt": "2026-09-09T21:14:02.000Z",
  "expiresAt": "2026-09-10T00:35:19.836Z"
}
POST/v1/pix/payoutspix:sendidempotente

Enviar Pix

Envia Pix da sua conta para uma chave externa de qualquer banco (Pix de saída). Diferente de Transferir, que move entre contas desta plataforma. Sai dinheiro da conta — por isso pede o escopo próprio pix:send e Idempotency-Key obrigatória.

Corpo

{
  "amount": "150.00",
  "pixKey": "maria@exemplo.com",
  "pixKeyType": "EMAIL",
  "description": "Pagamento fornecedor"
}

Resposta

{
  "id": "8f1a...",
  "status": "processing",
  "amount": "150.00",
  "fee": "1.20",
  "total": "151.20",
  "pixKey": "ma****@exemplo.com",
  "providerReference": "E1890...",
  "endToEndId": "E1890..."
}
GET/v1/splitsplit:read

Consultar split

Estado atual do split da conta: quanto o administrador do white-label já reservou (só o percentual — o destino nunca é mostrado à conta), quanto ainda está livre, e as regras da própria conta. A mesma leitura que a tela de split da conta usa.

Resposta

{
  "adminConfigured": false,
  "adminPercentage": "0.000000",
  "availablePercentage": "90.000000",
  "rules": [
    { "id": "1e04...", "destination": "Maria Fornecedora", "percentage": "10.000000" }
  ]
}
PUT/v1/splitsplit:write

Configurar split

Configura a regra PERMANENTE de split da conta: toda cobrança futura (Pix, boleto pago, transferência interna recebida) já sai dividida automaticamente, sem precisar mandar o campo split em cada chamada. Substitui a lista inteira — não soma à anterior. Uma lista vazia remove todas as regras desta conta, sem mexer no que o administrador do white-label configurou.

Corpo

{
  "lines": [
    { "destination": "maria@exemplo.com", "percentage": "10" }
  ]
}

Resposta

{
  "rules": [
    { "id": "1e04...", "destination": "Maria Fornecedora", "percentage": "10.000000" }
  ]
}
Esta é a regra permanente — continua valendo em todo crédito futuro até ser alterada de novo. Para um split que vale só para uma cobrança específica, use o campo split em POST /v1/pix/charges.
GET/v1/split/lookup?query=maria@exemplo.comsplit:read

Confirmar destino do split

Resolve um CPF, CNPJ ou e-mail para a conta que ele pertence, antes de salvar uma regra — a mesma confirmação que a tela da própria conta mostra ("vai enviar para fulano?"). Use para evitar salvar uma regra apontando para o destino errado.

Resposta

{
  "sellerId": "8d6d608e-...",
  "name": "Maria Fornecedora"
}

Idempotência

Toda transferência exige o header Idempotency-Key. Reenviar a mesma requisição com a mesma chave devolve a operação original com replayed: true, em vez de transferir de novo.

Isso existe porque um timeout de rede não diz se a operação aconteceu. Gere um identificador por intenção de pagamento — não por tentativa — e reenvie o mesmo em cada retry.

curl -X POST /v1/transfers \
  -H "Authorization: Bearer sk_test_sua_chave" \
  -H "Idempotency-Key: pedido-8842" \
  -H "Content-Type: application/json" \
  -d '{"to":"padaria","amount":"150.00"}'

Erros

Todo erro traz error (código estável) e message (texto para humano). Trate pelo código, não pelo texto.

HTTPCódigoQuando acontece
401missing_credentialsFaltou o header Authorization.
401invalid_credentialsChave inexistente, revogada ou de outro ambiente.
403insufficient_scopeA chave não tem o escopo exigido pela rota.
400missing_idempotency_keyPOST /v1/transfers exige Idempotency-Key.
400provider_failedO provedor de Pix recusou a cobrança. Nenhuma cobrança foi criada — pode tentar de novo.
404charge_not_foundCobrança inexistente ou de outra conta.
400invalid_requestCorpo malformado. `details` diz qual campo.
404not_foundO recurso não existe ou não é desta conta.
400invalid_documentO `destination` não parece um CPF, CNPJ ou e-mail válido.
400recipient_not_foundO CPF, CNPJ ou e-mail em `destination` não corresponde a nenhuma conta deste white-label.
400recipient_inactiveA conta destino existe, mas está encerrada ou suspensa.
400exceeds_available_percentageA soma das linhas passa de 100%, ou do que o administrador deixou livre.
400too_many_destinationsMais de 5 linhas na mesma chamada.
400duplicate_destinationO mesmo destino aparece duas vezes em `lines`.
400self_splitUma linha aponta para a própria conta.
400invalid_percentageUm `percentage` não é um número válido entre 0 e 100.

Estados de uma cobrança Pix

Só paid significa dinheiro na conta. Libere o pedido nesse estado, nunca antes.

openCriada, aguardando pagamento.
paidPaga e creditada na sua conta. É o único estado que move saldo.
expiredPassou da validade sem pagamento. Crie outra cobrança.
cancelledCancelada antes do pagamento.
refundedDevolvida ao pagador depois de paga.

Webhooks

Em vez de perguntar de tempos em tempos se a cobrança foi paga, cadastre uma URL no painel e receba o aviso no momento em que acontece. Cada envio é assinado — confira a assinatura antes de confiar no conteúdo.

Eventos

charge.paidA cobrança foi paga e o valor entrou na sua conta. É este que autoriza liberar o pedido.
charge.expiredA cobrança venceu sem pagamento. Serve para cancelar o pedido em aberto.
transfer.completedUma transferência que você enviou chegou ao destino.
credit.drawnAlguém usou o limite de crédito da conta.
loan.approvedUm empréstimo pedido pela conta foi aprovado.
investment.appliedUm aporte em investimento foi aplicado.
consortium.quota.approvedUma cota de consórcio foi aprovada.
consortium.contemplatedUma cota de consórcio foi contemplada.

O que chega

POST https://seu-sistema.com/webhooks
content-type: application/json
x-webhook-id: 9f2c1a44-...
x-webhook-event: charge.paid
x-webhook-timestamp: 1789002842
x-webhook-signature: 7b52009b64fd0a2a49e6d8a939753077792b0554...

{
  "id": "9f2c1a44-...",
  "type": "charge.paid",
  "createdAt": "2026-09-09T21:14:02.000Z",
  "data": {
    "chargeId": "e636775c-...",
    "sellerId": "c34b87db-...",
    "amount": "4990"
  }
}

O valor em data.amount vem em centavos. O identificador da cobrança é data.chargeId — o mesmo id devolvido ao criar.

Conferindo a assinatura

A assinatura é o HMAC-SHA256 de {timestamp}.{corpo}, em hexadecimal, com o segredo do destino, mostrado ao cadastrar a URL e recuperável depois em Credenciais, no botão Ver segredo ao lado do destino. O timestamp entra no cálculo para que uma entrega capturada não possa ser reenviada depois — recuse o que chegar com mais de 5 minutos.

import { createHmac, timingSafeEqual } from "node:crypto";

// corpo CRU, exatamente como chegou — reserializar muda os bytes
// e a assinatura deixa de bater.
function confere(corpoBruto, headers, segredo) {
  const assinatura = headers["x-webhook-signature"];
  const timestamp = Number(headers["x-webhook-timestamp"]);

  // Entrega velha é entrega repetida: recuse.
  if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;

  const esperado = createHmac("sha256", segredo)
    .update(`${timestamp}.${corpoBruto}`)
    .digest("hex");

  const a = Buffer.from(assinatura);
  const b = Buffer.from(esperado);
  // Comparação em tempo constante: "===" vaza, pelo tempo, quantos
  // caracteres iniciais estavam certos.
  return a.length === b.length && timingSafeEqual(a, b);
}

Boas práticas

  • Responda 200 rápido. Processe depois, em fila. Demorar faz o envio ser considerado falho e reenviado.
  • Espere repetição. O mesmo evento pode chegar duas vezes — uma reentrega após falha de rede, por exemplo. Guarde o x-webhook-id já processado e ignore repetidos, ou o pedido é liberado duas vezes.
  • Não confie no valor recebido para creditar. Antes de liberar o pedido, confirme com GET /v1/pix/charges/{id}. O webhook diz o que olhar; a consulta diz o que é verdade.
  • Use HTTPS. URLs em HTTP não são aceitas.

Valores e datas

  • Dinheiro vai e volta como string decimal com duas casas: "150.00". Nunca como número — ponto flutuante perde centavo, e centavo perdido em dinheiro é erro contábil.
  • Datas em ISO 8601, UTC: 2026-09-06T04:12:00.000Z.
  • Identificadores são UUID. Não presuma ordem nem sequência entre eles.