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 no sandbox

    Crie uma chave com o ambiente “Sandbox” (sk_sbx_…): mesmos endpoints, dinheiro de mentira, pagamentos simulados. Veja “Homologação e sandbox” logo abaixo. As chaves sk_test_ e sk_live_ operam na conta REAL e movem dinheiro de verdade.

  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 que pode ser gasto agora (available), o retido, o saldo bruto e o que ainda está dentro do prazo de recebimento (pending — boleto/cartão já pago e ainda não liberado; "0.00" quando o white-label não usa prazo). Valores em decimal com duas casas.

Resposta

{
  "available": "8589.10",
  "held": "0.00",
  "gross": "8589.10",
  "pending": "0.00",
  "currency": "BRL"
}
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. O desfecho final chega pelos webhooks pix.payout.completed e pix.payout.failed (só para quem os assina pelo nome) e pode ser conferido com GET /v1/transactions/{id} — o status vai de PENDING para SETTLED (enviado) ou FAILED (o valor e a tarifa voltam à conta sozinhos).

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..."
}
POST/v1/pix/qr/quotepix:send

Ler um QR Code Pix

Lê um Pix copia e cola (o texto que está por trás do QR Code) e diz o que ele pede, antes de mexer em dinheiro: quem recebe, o valor, a validade, a tarifa e se o saldo cobre. Mostre isso ao seu usuário e só então chame /v1/pix/qr/pay.

Disponibilidade
Só em contas cuja provedora de pagamento paga QR Code (hoje a Efí). Nas demais responde qr_not_supported.
QR estático sem valor
Devolve amount: null e amountEditable: true. Envie em `amount` o valor que quer pagar e a tarifa, o total e a conferência de saldo são calculados para ele.
QR dinâmico
A plataforma consulta o endereço que vem dentro do código (só HTTPS; endereços internos são recusados). Código já pago, vencido ou que não está mais ativo é recusado com qr_not_active ou qr_expired.
Não suportado
Código que permite o pagador alterar o valor é recusado com qr_amount_editable.

Corpo

{
  "brCode": "00020101021226830014BR.GOV.BCB.PIX2561qrcodespix.sejaefi.com.br/v2/267e5552...6304CE83"
}

Resposta

{
  "kind": "DYNAMIC",
  "amount": "137.50",
  "amountEditable": false,
  "receiverName": "LOJA EXEMPLO LTDA",
  "receiverDocument": "**********0190",
  "city": "SAO PAULO",
  "expiresAt": "2026-10-01T18:30:00.000Z",
  "fee": "1.20",
  "total": "138.70",
  "spendable": "500.00",
  "suficiente": true
}
POST/v1/pix/qr/paypix:sendidempotente

Pagar um QR Code Pix

Paga um Pix copia e cola da sua conta: "ler o QR e pagar". Envie em `amount` o valor que você mostrou ao seu usuário — o servidor lê o código de novo e RECUSA (qr_amount_changed) se mudou desde a consulta, então ninguém paga um valor diferente do que viu. Sai dinheiro da conta: escopo próprio pix:send e Idempotency-Key obrigatória.

Desfecho
status volta como processing. O desfecho final chega pelos webhooks pix.payout.completed e pix.payout.failed (só para quem os assina pelo nome) e pode ser conferido com GET /v1/transactions/{id} — o status vai de PENDING para SETTLED (pago) ou FAILED (o valor e a tarifa voltam à conta sozinhos).
Timeout
Se receber pending_reconciliation, o pagamento pode ter saído. NÃO envie de novo: consulte GET /v1/transactions/{id}. Repetir a mesma Idempotency-Key é sempre seguro.
Conta bloqueada
Conta com saídas bloqueadas responde outbound_blocked.
Erros
brcode_invalid / brcode_crc (código não copiado inteiro), qr_expired, qr_not_active, qr_amount_changed, qr_amount_editable, qr_not_supported, insufficient_funds, limit_exceeded, daily_limit_exceeded, outbound_blocked, provider_rejected (nada foi debitado), pending_reconciliation.

Corpo

{
  "brCode": "00020101021226830014BR.GOV.BCB.PIX2561qrcodespix.sejaefi.com.br/v2/267e5552...6304CE83",
  "amount": "137.50",
  "description": "Pagamento fornecedor"
}

Resposta

{
  "id": "8f1a...",
  "status": "processing",
  "amount": "137.50",
  "fee": "1.20",
  "total": "138.70",
  "receiver": "LOJA EXEMPLO LTDA",
  "providerReference": "8f1a...",
  "endToEndId": "E1890..."
}
POST/v1/boleto/chargesboleto:writeidempotente

Cobrar por boleto

Cobrança avulsa por boleto: devolve a linha digitável do pagamento e, quando o provedor suporta, um link para o PDF. Não cria link nem página pública — use quando o pedido já existe no seu sistema.

Documento de quem paga
Boleto exige nome e documento de quem paga. Atenção: a API só valida o tamanho do documento, não o dígito verificador de CPF/CNPJ, então valide isso também do seu lado.
Confirmação não é instantânea
A confirmação do pagamento chega pelo webhook charge.paid, normalmente em até um dia útil depois do pagamento.
Idempotency-Key
Opcional aqui mas recomendado: sem ele, um retry de rede gera um segundo boleto pro mesmo pedido.
Split
Funciona exatamente como em pix/charges.

Corpo

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

Resposta

{
  "id": "e636775c-...",
  "status": "open",
  "amount": "49.90",
  "description": "Pedido #1234",
  "digitableLine": "34191.79001 01043.510047 91020.150008 8 96590000004990",
  "bankSlipUrl": "https://provedor.com/boletos/abc123.pdf",
  "expiresAt": "2026-09-13T00:00:00.000Z",
  "externalReference": "pedido-1234",
  "split": [
    { "destinationSellerId": "7ec3...", "percentage": "10" }
  ]
}
GET/v1/boleto/charges/{id}boleto:write

Consultar cobrança de boleto

Estado atual do boleto. Mesmo formato de GET /v1/pix/charges/{id} — prefira o webhook charge.paid para acompanhar o pagamento em tempo real.

Resposta

{
  "id": "e636775c-...",
  "status": "open",
  "amount": "49.90",
  "description": "Pedido #1234",
  "paidAt": null,
  "expiresAt": "2026-09-13T00:00:00.000Z"
}
POST/v1/card/chargescard:writeidempotente

Cobrar no cartão de crédito

Cobrança server-to-server: você já tem os dados do portador em mãos e cobra direto, sem página de checkout hospedada no meio. A resposta já diz se foi aprovado — não existe instrumento para o pagador copiar depois, como acontece com Pix e boleto.

PCI-DSS
Número, validade e CVV do cartão chegam SÓ como parâmetro desta chamada — a plataforma nunca grava nem loga esses dados; eles vão direto para o provedor e saem de escopo assim que a resposta volta. Lidar com dados de cartão desse jeito coloca SUA integração sob escopo de PCI-DSS: cuide do TLS de ponta a ponta e não persista esses campos do seu lado sem o cuidado equivalente.
Idempotency-Key
Opcional, mas FORTEMENTE recomendado aqui — mais do que em Pix ou boleto. Sem ele, um retry de rede pode cobrar o cartão do cliente duas vezes de verdade, não só criar uma cobrança pendente duplicada.
Validação
Se a validação falhar, a resposta reporta só o primeiro campo inválido, não a lista completa.
Split
Funciona exatamente como em pix/charges — resolvido antes de cobrar no cartão, para que um destino inválido nunca deixe um cartão já cobrado sem o split aplicado.

Corpo

{
  "amount": "49.90",
  "description": "Pedido #1234",
  "installmentCount": 1,
  "payer": {
    "name": "Maria Silva",
    "document": "12345678901",
    "email": "maria@exemplo.com",
    "ip": "203.0.113.42"
  },
  "card": {
    "holderName": "MARIA SILVA",
    "number": "4111111111111111",
    "expiryMonth": "12",
    "expiryYear": "2029",
    "cvv": "123"
  },
  "externalReference": "pedido-1234",
  "split": [
    { "destination": "anunciante@exemplo.com", "percentage": "10" }
  ]
}

Resposta

{
  "id": "e636775c-...",
  "status": "paid",
  "amount": "49.90",
  "cardLast4": "1111",
  "cardBrand": "visa",
  "externalReference": "pedido-1234",
  "split": [
    { "destinationSellerId": "7ec3...", "percentage": "10" }
  ]
}

// status tambem pode vir "awaiting_risk_analysis": o provedor
// reteve para analise manual. Nao libere o pedido ainda -- espere
// o webhook charge.paid (aprovado) ou charge.expired (recusado).
// Atencao: enquanto pendente, o GET desta charge devolve "open",
// nunca "awaiting_risk_analysis" -- so o POST mostra esse valor.

// cartao recusado na hora (sincrono): HTTP 400, error
// "provider_rejected". O mesmo slug cobre tanto recusa da
// operadora quanto falha tecnica do provedor -- so o texto em
// "message" muda. Nada foi cobrado nos dois casos.

// sem resposta do provedor a tempo: HTTP 400, error
// "timeout_ambiguous". Diferente de provider_rejected -- aqui NAO
// se sabe se o cartao foi cobrado do outro lado, entao a cobranca
// fica "open" (nao "cancelled"), de proposito. Nao tente cobrar de
// novo sozinho: confirme com o suporte antes, ou o cliente final
// pode ser cobrado duas vezes se o provedor tiver processado a
// primeira tentativa depois do seu timeout.
GET/v1/card/charges/{id}card:write

Consultar cobrança de cartão

Estado atual da cobrança de cartão. Mesmo formato de GET /v1/pix/charges/{id}. Como a cobrança de cartão é síncrona na maioria dos casos, a resposta de POST /v1/card/charges já diz o desfecho — use este endpoint mais para conciliar depois do que para consultar logo em seguida da cobrança. Importante: enquanto a cobrança está em análise de risco, este endpoint mostra status "open", nunca "awaiting_risk_analysis" — esse valor só aparece na resposta do POST. Um cartão recusado na hora aparece aqui como "cancelled".

Resposta

{
  "id": "e636775c-...",
  "status": "paid",
  "amount": "49.90",
  "description": "Pedido #1234",
  "paidAt": "2026-09-09T21:14:02.000Z",
  "expiresAt": null
}
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": "80.000000",
  "rules": [
    { "id": "1e04...", "destination": "Maria Fornecedora", "percentage": "10.000000" }
  ],
  "pixRules": [
    { "id": "9c2b...", "label": "Fornecedor Pix", "keyType": "CNPJ", "keyMasked": "**********0138", "percentage": "10.000000", "feePayer": "SHARED" }
  ],
  "pix": { "enabled": true, "ready": true, "randomKey": true, "minimum": "1.00" }
}
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"
}
PUT/v1/split/pixsplit:write

Configurar split para chave Pix

Regra PERMANENTE de split em que o dinheiro sai por Pix para uma chave FORA da plataforma (fornecedor, sócio, outro banco). Substitui a lista inteira de linhas Pix (até 5, que somadas às linhas de conta e ao que o administrador do white-label reservou nunca passam de 100%). Mande a chave completa numa linha NOVA, ou só o `ruleId` para manter uma chave que já existe (a chave inteira nunca volta nas leituras). `feePayer` diz quem arca com a tarifa do Pix: SOURCE (você), DESTINATION (quem recebe) ou SHARED (padrão). O Pix só sai quando a venda liquida (boleto e cartão respeitam o prazo) e fatia abaixo de `pix.minimum` fica com a conta. Só funciona se o white-label liberou o recurso: confira `pix.enabled` e `pix.ready` em GET /v1/split, senão a chamada falha com erro claro.

Corpo

{
  "lines": [
    { "label": "Fornecedor Pix", "keyType": "CNPJ", "key": "63473778000138", "percentage": "10", "feePayer": "SHARED" },
    { "ruleId": "9c2b...", "label": "Sócio", "percentage": "5" }
  ]
}

Resposta

{
  "pixRules": [
    { "id": "9c2b...", "label": "Fornecedor Pix", "keyType": "CNPJ", "keyMasked": "**********0138", "percentage": "10.000000", "feePayer": "SHARED" }
  ]
}
GET/v1/split/history?kind=PIX&limit=20&offset=0split:read

Extrato do split

O que já saiu desta conta por split (conta e Pix juntos), com os totais do filtro. `kind` é opcional: ACCOUNT ou PIX. `limit` até 100. `status` do item: SENT, WAITING_RELEASE (esperando o prazo de liquidação), QUEUED, SENDING, FAILED, CANCELLED. `summary` conta só o que de fato saiu (SENT).

Resposta

{
  "items": [
    { "id": "5a1c...", "kind": "PIX", "createdAt": "2026-10-05T14:02:11.000Z", "amount": "10.00", "fee": "0.40", "total": "10.40",
      "destination": "Fornecedor Pix", "keyMasked": "**********0138", "status": "SENT" }
  ],
  "total": 1, "limit": 20, "offset": 0,
  "summary": { "sent": "10.00", "fees": "0.40", "pending": 0 }
}
GET/v1/payroll/overviewpayroll:read

Resumo da folha

Se a folha está ligada para a conta (`availability.enabled` — o white-label liga o serviço e define a tarifa por pagamento), quantos funcionários ativos, o total da folha mensal e as próximas folhas. Valem as mesmas regras, limites e tarifas do Pix de saída do portal: a folha é paga pelo Pix de saída da conta.

Resposta

{
  "availability": { "enabled": true, "reason": null, "feePerPayment": "0.80" },
  "employees": { "active": 12, "monthlyPayroll": "30000.00" },
  "upcoming": [
    { "id": "b7e1...", "kind": "SALARY", "kindLabel": "Salário", "reference": "2026-11", "title": "Salário 11/2026", "scheduledFor": "2026-11-05",
      "status": "SCHEDULED", "totalAmount": "30000.00", "totalFee": "0.00", "paidCount": 0, "failedCount": 0, "daysUntil": 31 }
  ],
  "thisMonth": { "paid": "30000.00", "payments": 12 }
}
GET/v1/payroll/employees?status=ACTIVE&q=mariapayroll:read

Listar funcionários

Seus funcionários (`status` ACTIVE ou INACTIVE, `q` busca por nome). A chave Pix vem mascarada (`pixKeyMasked`); a chave completa nunca é devolvida por esta API.

Resposta

{
  "items": [
    { "id": "3f0a...", "name": "Maria Souza", "document": null, "pixKeyType": "EMAIL", "pixKeyMasked": "ma****@exemplo.com", "salary": "2500.00",
      "payDay": 5, "businessDayRule": "PREVIOUS", "advanceEnabled": true, "advanceDay": 20, "advancePercent": "40.00", "autoPay": true,
      "taxMode": "NET", "dependents": 0, "status": "ACTIVE", "terminatedAt": null, "nextPayment": "2026-11-05" }
  ]
}
POST/v1/payroll/employeespayroll:write

Cadastrar funcionário

Cadastra um funcionário. ATENÇÃO: com `autoPay: true` (padrão) o funcionário é pago SOZINHO no `payDay`, sem nenhuma chamada a mais — então esta chave move dinheiro. `salary` é o valor LÍQUIDO a pagar (taxMode NET) ou o salário BRUTO (taxMode CLT: INSS/IRRF vêm calculados pelas tabelas do ano, FGTS é informativo). `businessDayRule`: PREVIOUS, NEXT ou EXACT (quando `payDay` não é dia útil). Devolve `{ "id": "..." }`. Atualize com PUT /v1/payroll/employees/{id} (mesmo corpo); chave Pix trocada ou salário aumentado valem também para os itens pendentes.

Corpo

{
  "name": "Maria Souza",
  "document": "12345678901",
  "pixKeyType": "CPF",
  "pixKey": "12345678901",
  "salary": "2500.00",
  "payDay": 5,
  "businessDayRule": "PREVIOUS",
  "advanceEnabled": true,
  "advanceDay": 20,
  "advancePercent": 40,
  "autoPay": true,
  "taxMode": "NET",
  "dependents": 0
}

Resposta

{ "id": "3f0a..." }
POST/v1/payroll/employees/{id}/terminatepayroll:write

Desligar, reativar e excluir

POST /v1/payroll/employees/{id}/terminate (corpo opcional: `{ "date": "2026-10-31", "reason": "..." }`) para os pagamentos futuros; POST .../reactivate traz o funcionário de volta; DELETE /v1/payroll/employees/{id} remove quem nunca recebeu pagamento. Todos devolvem `{ "ok": true }`.

Resposta

{ "ok": true }
GET/v1/payroll/runs/suggest?kind=SALARY&reference=2026-11-05payroll:read

Valores sugeridos

O que pagar a cada funcionário ativo num tipo de folha: SALARY, ADVANCE, THIRTEENTH_FIRST, THIRTEENTH_SECOND, VACATION, BONUS ou OTHER. Para CLT a resposta já traz as linhas de desconto (INSS, IRRF) e o FGTS informativo. Use para montar o `items` de POST /v1/payroll/runs.

Resposta

{
  "items": [
    { "employeeId": "3f0a...", "name": "Maria Souza", "salary": "2500.00", "base": "1500.00", "suggested": "1500.00", "lines": [],
      "taxMode": "NET", "fgts": null, "note": "Salário menos o adiantamento de 40%" }
  ]
}
POST/v1/payroll/runspayroll:write

Criar folha

Cria uma folha (até 500 itens) para uma data de hoje em diante. ATENÇÃO: folha agendada é PAGA SOZINHA em `scheduledFor` — você não precisa chamar o pagar. O mesmo funcionário não é pago duas vezes no mesmo período e tipo (erro `DUPLICATE_PERIOD`). `lines` são ajustes opcionais (negativo = desconto, positivo = acréscimo). Devolve `{ "id": "..." }`. Edite com PATCH /v1/payroll/runs/{id} (`scheduledFor`, `title`, `note`), PUT /v1/payroll/runs/{id}/items/{itemId} (`amount`, `lines`, `remove`), POST /v1/payroll/runs/{id}/items (`employeeId`) e cancele com POST /v1/payroll/runs/{id}/cancel — tudo só enquanto a folha não começou a pagar (senão `NOT_EDITABLE`).

Corpo

{
  "kind": "SALARY",
  "title": "Salário 11/2026",
  "scheduledFor": "2026-11-05",
  "items": [
    { "employeeId": "3f0a...", "amount": "1500.00", "lines": [ { "label": "Bônus", "amount": "100.00" } ] }
  ]
}

Resposta

{ "id": "b7e1..." }
GET/v1/payroll/runs/{id}payroll:read

Consultar folha

A folha com cada item e um `preview` (total a pagar, tarifas estimadas, saldo e o que falta). `status` da folha: SCHEDULED, AWAITING_FUNDS (saldo insuficiente: tenta de novo quando entrar saldo), PROCESSING, COMPLETED, PARTIAL, FAILED, CANCELLED. `status` do item: PENDING, SENT (Pix enviado, aguardando o banco), PAID, FAILED (o banco confirmou que não saiu; valor e tarifa já voltaram), SKIPPED. Liste com GET /v1/payroll/runs?status=…

Resposta

{
  "id": "b7e1...", "kind": "SALARY", "kindLabel": "Salário", "reference": "2026-11", "title": "Salário 11/2026", "scheduledFor": "2026-11-05",
  "status": "SCHEDULED", "totalAmount": "1600.00", "totalFee": "0.00", "paidCount": 0, "failedCount": 0, "lastError": null, "editable": true,
  "items": [
    { "id": "d41c...", "employeeId": "3f0a...", "employeeName": "Maria Souza", "pixKeyType": "EMAIL", "pixKeyMasked": "ma****@exemplo.com",
      "baseAmount": "1500.00", "lines": [ { "label": "Bônus", "amount": "100.00" } ], "amount": "1600.00", "status": "PENDING",
      "fee": "0.00", "transactionId": null, "failureReason": null, "paidAt": null }
  ],
  "preview": { "toPay": "1600.00", "feeEstimated": "0.80", "totalDebit": "1600.80", "balance": "5000.00", "shortfall": null, "feeError": null }
}
POST/v1/payroll/runs/{id}/paypayroll:write

Pagar a folha agora

Paga agora uma folha SCHEDULED ou AWAITING_FUNDS, sem esperar a data. O dinheiro sai por Pix de saída com os limites e tarifas da conta; se o saldo não bastar, a folha vai para AWAITING_FUNDS e nada é enviado. Chamar duas vezes é seguro: só um processo pega a folha. Depois, acompanhe em `GET /v1/payroll/runs/{id}`; Pix que não sai volta para a conta. `POST /v1/payroll/runs/{id}/retry` repete SÓ os itens que o banco confirmou que não saíram (nunca repete um Pix que pode ter saído). Comprovante por item: GET /v1/payroll/runs/{id}/items/{itemId}/receipt. Extrato de tudo que foi pago: GET /v1/payroll/history?from=&to=&status=SENT|PAID|FAILED&employeeId=&limit=&offset= (devolve `items`, `totals` e `page`).

Resposta

{
  "id": "b7e1...", "title": "Salário 11/2026", "scheduledFor": "2026-11-05", "status": "AWAITING_FUNDS",
  "lastError": "Saldo insuficiente: faltam 900101.00 para pagar a folha.",
  "items": [ { "id": "d41c...", "status": "PENDING", "amount": "1600.00" } ],
  "preview": { "toPay": "1600.00", "feeEstimated": "0.80", "totalDebit": "1600.80", "balance": "100.00", "shortfall": "1500.80", "feeError": null }
}
// com saldo: status "COMPLETED" (ou "PARTIAL"/"FAILED") e itens "SENT" -> "PAID"

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.

Testes

Homologação e sandbox

Teste a integração inteira sem mexer em um centavo. O sandbox é a mesma API, atendida por um simulador: dinheiro de mentira, pagamentos simulados e webhooks que chegam exatamente como os de verdade.

SandboxProdução
Chavesk_sbx_…sk_live_…
URL basea mesmaa mesma
Endpointsos mesmosos mesmos
DinheiroDe mentira, R$ 10.000,00 por contaReal
Provedora de pagamentoNenhuma — simuladorReal
Pagar uma cobrançaVocê dispara: POST /v1/sandbox/…/payO cliente paga
WebhooksSó para destinos “sandbox”Só para destinos comuns

Uma chave de sandbox nunca toca dinheiro real

A API real recusa chave sk_sbx_ e o simulador não tem caminho até o ledger nem até nenhuma provedora. Um pagamento de teste não libera pedido de verdade: eventos de sandbox só vão para destinos que você marcou como sandbox.

Configure em 4 passos

  1. 1

    Crie uma chave de sandbox

    No app: Mais → Credenciais de API → Nova chave → Ambiente “Sandbox”. Dê os escopos que você vai testar (card:write só existe em sandbox).

  2. 2

    Cadastre um destino de webhook de sandbox

    Na mesma tela: Novo destino, marque “Destino de sandbox” e escolha os eventos. Use uma URL de testes do seu sistema.

  3. 3

    Aponte seu código para a mesma URL com a nova chave

    Nada mais muda. O servidor reconhece o prefixo sk_sbx_ e responde pelo simulador.

  4. 4

    Percorra o roteiro abaixo

    Marque cada caso ao passar. O progresso fica guardado neste navegador.

curl https://SEU-BANCO/api/v1/me \
  -H "Authorization: Bearer sk_sbx_sua_chave"

# { "environment": "sandbox", "scopes": [...], ... }

Comandos de simulação

Em produção o mundo de fora faz isso sozinho (o cliente paga, o boleto vence, o banco responde). No sandbox, você dispara. Exigem chave de sandbox — com chave real devolvem 403. Envie um corpo, mesmo vazio: -d '{}'.

POST /v1/sandbox/charges/{id}/payConfirma uma cobrança Pix, boleto ou cartão em análise → charge.paid.
POST /v1/sandbox/charges/{id}/expireVence a cobrança → charge.expired.
POST /v1/sandbox/payouts/{id}/completeConclui um envio de Pix na hora → pix.payout.completed.
POST /v1/sandbox/payouts/{id}/failFaz o envio falhar e devolve valor e tarifa → pix.payout.failed.
POST /v1/sandbox/balance/topupSoma saldo de mentira: {"amount":"500.00"}.
GET /v1/sandbox/test-dataDevolve esta tabela de valores de teste, em JSON.

Dados de teste

Saldo inicialR$ 10.000,00 de mentira, por conta.
Tarifa do Pix enviadoR$ 1,00 fixos (para o total ser diferente do valor).
4111 1111 1111 1111Cartão aprovado na hora.
4000 0000 0000 0002Cartão recusado — 400 provider_rejected.
4000 0000 0000 9995Cartão em análise — awaiting_risk_analysis.
falha@sandbox.testChave Pix (EMAIL): o envio é aceito e falha em ~4 s.
recusa@sandbox.testChave Pix (EMAIL): recusado na hora, nada debitado.
Qualquer outra chave válidaEnvio aceito; conclui sozinho em ~4 s.
CPF 010.959.023-69CPF válido para testar boleto e cartão (qualquer CPF/CNPJ válido serve).

Roteiro de homologação

Cada caso diz como provocar e o que precisa acontecer. Marque ao passar — o progresso fica guardado neste navegador.

0 / 37 casos aprovados0%

1. Conexão e autenticação

A chave chega, é reconhecida, e os erros de credencial são tratados.

0/3
  • A chave de sandbox respondedetalhes
    curl https://SEU-BANCO/api/v1/me -H "Authorization: Bearer sk_sbx_sua_chave"

    Esperado: Resposta 200 com "environment": "sandbox" e os escopos da chave.

  • Chave inválida vira erro tratadodetalhes
    curl -i https://SEU-BANCO/api/v1/me -H "Authorization: Bearer sk_sbx_chave_errada_000000000000"

    Esperado: 401 com error: invalid_key. Seu sistema não deve tentar de novo em loop.

  • Escopo insuficiente é tratadodetalhes
    # crie uma chave só com balance:read e tente cobrar:
    curl -i https://SEU-BANCO/api/v1/pix/charges -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -d '{"amount":"10.00"}'

    Esperado: 403 com error: insufficient_scope.

2. Cobrança Pix (receber)

O fluxo que sustenta loja e cardápio: cobrar, mostrar o QR, confirmar o pagamento.

0/6
  • Criar a cobrança e mostrar o QRdetalhes
    curl https://SEU-BANCO/api/v1/pix/charges -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" \
      -H "Idempotency-Key: pedido-1001" \
      -d '{"amount":"150.00","description":"Pedido #1001","externalReference":"1001"}'

    Esperado: Resposta 201, "status": "open" e o campo copyPaste. Guarde o id junto do pedido.

  • Confirmar o pagamento pelo webhookdetalhes
    # simula o cliente pagando:
    curl https://SEU-BANCO/api/v1/sandbox/charges/ID_DA_COBRANCA/pay -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -d '{}'

    Esperado: Seu destino de sandbox recebe charge.paid (amount em centavos). Confira a assinatura e só então libere o pedido.

  • Confirmar também pela consultadetalhes
    curl https://SEU-BANCO/api/v1/pix/charges/ID_DA_COBRANCA -H "Authorization: Bearer sk_sbx_sua_chave"

    Esperado: "status": "paid" e paidAt preenchido. É a rede de segurança para um webhook perdido.

  • Cobrança que vencedetalhes
    curl https://SEU-BANCO/api/v1/sandbox/charges/OUTRO_ID/expire -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -d '{}'

    Esperado: charge.expired chega e seu sistema cancela o pedido em aberto.

  • Repetir a criação não duplicadetalhes
    # mesma Idempotency-Key duas vezes:
    curl https://SEU-BANCO/api/v1/pix/charges -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -H "Idempotency-Key: pedido-1001" -d '{"amount":"150.00"}'

    Esperado: A segunda chamada devolve a MESMA cobrança (mesmo id), sem criar outra.

  • O saldo reflete o recebimentodetalhes
    curl https://SEU-BANCO/api/v1/balance -H "Authorization: Bearer sk_sbx_sua_chave"

    Esperado: available aumentou no valor pago.

3. Boleto

Emissão com dados do pagador, validação de documento e desfecho.

0/4
  • Emitir o boletodetalhes
    curl https://SEU-BANCO/api/v1/boleto/charges -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" \
      -d '{"amount":"80.00","payer":{"name":"Maria Teste","document":"01095902369"}}'

    Esperado: 201 com digitableLine. Mostre a linha digitável ao pagador.

  • CPF/CNPJ inválido é recusadodetalhes
    curl https://SEU-BANCO/api/v1/boleto/charges -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" \
      -d '{"amount":"80.00","payer":{"name":"Maria Teste","document":"11111111111"}}'

    Esperado: 400 com error: payer_document_invalid. Seu formulário deve validar antes de enviar.

  • Boleto pagodetalhes
    curl https://SEU-BANCO/api/v1/sandbox/charges/ID_DO_BOLETO/pay -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -d '{}'

    Esperado: charge.paid com "method": "BOLETO".

  • Boleto vencidodetalhes
    curl https://SEU-BANCO/api/v1/sandbox/charges/ID_DO_BOLETO/expire -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -d '{}'

    Esperado: charge.expired. Em produção o boleto vence em 3 dias.

4. Cartão

Aprovado, recusado e em análise — os três desfechos que sua tela precisa tratar.

0/3
  • Cartão aprovadodetalhes
    # number: 4111111111111111
    curl https://SEU-BANCO/api/v1/card/charges -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -d '{"amount":"40.00","payer":{"name":"João Teste","document":"01095902369","ip":"203.0.113.9"},"card":{"holderName":"JOAO TESTE","number":"4111111111111111","expiryMonth":"12","expiryYear":"2030","cvv":"123"}}'

    Esperado: "status": "paid" na própria resposta, com cardLast4 e cardBrand.

  • Cartão recusadodetalhes
    # mesmo corpo, number: 4000000000000002

    Esperado: 400 com error: provider_rejected. Mostre uma mensagem neutra e deixe tentar outro cartão.

  • Cartão em análisedetalhes
    # mesmo corpo, number: 4000000000009995
    # depois aprove por simulação:
    curl https://SEU-BANCO/api/v1/sandbox/charges/ID/pay -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -d '{}'

    Esperado: "status": "awaiting_risk_analysis"; não libere o pedido. O desfecho vem por charge.paid.

5. Pix enviado (pagar)

Saída de dinheiro: a parte onde um erro custa caro. Testa idempotência, falha e saldo.

0/7
  • Enviar um Pixdetalhes
    curl https://SEU-BANCO/api/v1/pix/payouts -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -H "Idempotency-Key: saque-7001" \
      -d '{"amount":"20.00","pixKey":"fornecedor@exemplo.com","pixKeyType":"EMAIL"}'

    Esperado: 201 com "status": "processing" e total = valor + tarifa (no sandbox a tarifa é R$ 1,00).

  • Desfecho: concluídodetalhes
    # o envio conclui sozinho em ~4 s

    Esperado: pix.payout.completed chega ao destino (assine o evento pelo nome). GET /v1/transactions/{id} mostra SETTLED.

  • Desfecho: falhou e o dinheiro voltadetalhes
    curl https://SEU-BANCO/api/v1/pix/payouts -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -H "Idempotency-Key: saque-7002" \
      -d '{"amount":"30.00","pixKey":"falha@sandbox.test","pixKeyType":"EMAIL"}'

    Esperado: pix.payout.failed em ~4 s; valor e tarifa voltam ao saldo. Seu sistema marca o pagamento como não feito.

  • Recusa imediatadetalhes
    # pixKey: recusa@sandbox.test

    Esperado: 400 com error: provider_rejected e NADA debitado.

  • Saldo insuficientedetalhes
    # amount: "999999.00"

    Esperado: 400 com error: insufficient_funds.

  • Idempotency-Key é obrigatóriadetalhes
    # chame sem o header

    Esperado: 400 com error: missing_idempotency_key.

  • Repetir com a mesma chave não paga duas vezesdetalhes
    # repita o saque-7001 exatamente igual

    Esperado: A resposta traz o MESMO id e o saldo não muda. É o que protege contra timeout e clique duplo.

6. Pagar Pix por QR Code

Consultar o código, confirmar o valor e pagar — com a trava de valor alterado.

0/3
  • Consultar antes de pagardetalhes
    # use o copyPaste de uma cobrança Pix do sandbox
    curl https://SEU-BANCO/api/v1/pix/qr/quote -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -d '{"brCode":"COPIA_E_COLA"}'

    Esperado: 200 com amount, receiverName, fee, total e suficiente. Mostre ao usuário antes de confirmar.

  • Valor que mudou é recusadodetalhes
    curl https://SEU-BANCO/api/v1/pix/qr/pay -X POST -H "Authorization: Bearer sk_sbx_sua_chave" -H "content-type: application/json" -H "Idempotency-Key: qr-1" -d '{"brCode":"COPIA_E_COLA","amount":"99.00"}'

    Esperado: 400 com error: qr_amount_changed. Nada foi debitado.

  • Pagar o QRdetalhes
    # mesmo pedido com o valor confirmado

    Esperado: 201 e, como o código era de uma cobrança do sandbox, a cobrança vira paga (charge.paid).

7. Webhooks

Onde mais se erra: assinatura, repetição e lentidão.

0/4
  • Assinatura conferidadetalhes
    # recalcule HMAC-SHA256 de {timestamp}.{corpo} com o segredo do destino

    Esperado: Um aviso com assinatura errada é REJEITADO (401/403) e não altera nada no seu sistema.

  • Responde 2xx rápidodetalhes
    # processe em segundo plano; responda antes

    Esperado: Seu endpoint responde 2xx em poucos segundos. Falhas seguidas desligam o destino.

  • Evento repetido não repete o efeitodetalhes
    # reenvie o mesmo evento pelo painel (Avisos automáticos)

    Esperado: Seu sistema usa o id do evento (ou do pedido) para ignorar a segunda entrega.

  • Só os eventos assinadosdetalhes
    # cadastre o destino com charge.paid e pix.payout.completed

    Esperado: pix.payout.* só chega a quem assina o nome. O destino de sandbox nunca recebe evento real.

8. Saldo e extrato

Conferência: o que você vê bate com o que aconteceu.

0/2
  • Listar e paginardetalhes
    curl "https://SEU-BANCO/api/v1/transactions?limit=5&offset=0" -H "Authorization: Bearer sk_sbx_sua_chave"

    Esperado: items, total, limit e offset. Há próxima página enquanto offset + items.length < total.

  • Comprovante de uma movimentaçãodetalhes
    curl https://SEU-BANCO/api/v1/transactions/ID -H "Authorization: Bearer sk_sbx_sua_chave"

    Esperado: status PENDING → SETTLED/FAILED e a timeline. É por aqui que se acompanha um Pix que você pagou.

9. Antes de ir para produção

O que fecha a homologação. Com tudo marcado, você está pronto.

0/5
  • Só a chave mudadetalhes
    # troque sk_sbx_… por sk_live_… (a URL base é a mesma)

    Esperado: Nenhuma linha de código muda entre homologação e produção — a chave vem de variável de ambiente.

  • Destino de webhook de produção cadastradodetalhes
    # Credenciais → Novo destino, SEM marcar “Destino de sandbox”

    Esperado: URL HTTPS de produção, com os eventos que você usa, e o segredo guardado no servidor.

  • Erros tratados pelo campo errordetalhes
    # nunca pelo texto de message

    Esperado: Seu código decide pelo error (minúsculo e estável), não pela mensagem.

  • Valores como string decimaldetalhes
    # "150.00", nunca 150.0

    Esperado: Nenhum valor passa por ponto flutuante no seu sistema.

  • Uma transação real de valor baixodetalhes
    # com a chave sk_live_, cobre R$ 1,00 no seu próprio Pix

    Esperado: O sandbox prova a integração; uma cobrança real prova a conta. Faça as duas antes de divulgar.

O que o sandbox não simula

  • Links de pagamento (/v1/payment-links) e split (/v1/split): valide em produção com valores baixos.
  • QR Code Pix dinâmico (só códigos estáticos, como os que uma cobrança Pix do sandbox gera).
  • Prazo de recebimento de boleto e cartão (saldo a liberar) e a tabela de tarifas de cada white-label: o sandbox cobra R$ 1,00 fixos no Pix enviado e nada no resto.
  • A demora bancária real: um envio conclui em segundos, não no tempo da provedora.
  • Os dados ficam guardados por 30 dias e depois são apagados.

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.
pix.payout.completedUm Pix que você enviou (por chave ou QR Code) chegou ao destino. Só é entregue a quem assina este nome.
pix.payout.failedUm Pix que você enviou não saiu; valor e tarifa já voltaram à conta. Só é entregue a quem assina este nome.
receivable.releasedO prazo de um boleto/cartão venceu e o valor passou a ficar disponível. Só é entregue a quem assina este nome.
receivable.anticipatedRecebíveis foram antecipados antes da data de liberação. Só é entregue a quem assina este nome.
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",
    "method": "PIX"
  }
}

O valor em data.amount vem em centavos. O identificador da cobrança é data.chargeId — o mesmo id devolvido ao criar. data.method diz como foi pago — PIX, BOLETO ou CARD — sem precisar de uma chamada extra só pra saber isso.

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.