Pular para o conteúdo principal

Webhooks

Webhooks são notificações enviadas pela nossa API para a URL cadastrada sempre que um evento relevante ocorre (por exemplo, um PIX é recebido ou um pagamento é concluído).

Configuração de Webhooks

Os webhooks devem ser configurados através do Portal do Integrador.

Listar Eventos Disponíveis

curl -X GET "https://api.corpxapi.com/v1/webhooks/events" \
-H "Authorization: Bearer YOUR_TOKEN"

Resposta:

{
"eventTypes": [
"pix.in.completed",
"pix.out.completed",
"pix.out.failed",
"qrcode.paid",
"pix.refund.completed",
"pix.refund.failed",
"pix.med.opened",
"pix.med.updated",
"transfer.internal.in",
"transfer.internal.out",
"account.balance_updated",
"account.lock_created",
"account.lock_released",
"accreditation.pf.created",
"accreditation.pj.created",
"edi.batch",
"ted.payment"
]
}

Fluxo de Recebimento

  1. Um evento ocorre na nossa plataforma.
  2. Enviamos uma requisição POST para as URLs cadastradas.
  3. Sua aplicação deve processar a notificação e retornar um status 2xx.

Flexibilidade de Configuração

Nossa infraestrutura de webhooks suporta diversos métodos de entrega:

  • Agrupamento: Você pode receber múltiplos tipos de evento (por exemplo, pix.in.completed e pix.out.completed) na mesma URL.
  • Segregação: Você pode configurar URLs diferentes para cada tipo de evento.
  • Redundância: Podemos enviar o mesmo evento para múltiplas URLs independentes simultaneamente.

Segurança (Autenticação de Destino)

Ao criar ou atualizar uma assinatura de webhook, você pode escolher como nossa infraestrutura de entrega autentica as requisições enviadas ao seu endpoint. O método de autenticação é configurado por assinatura via API ou dashboard.

Métodos de Autenticação Disponíveis

MétodoValor de authTypeDescrição
Assinatura HMACHMACAssina o corpo de cada requisição com seu segredo usando HMAC-SHA256. A assinatura é enviada no header X-Signature. Recomendado.
API KeyAPI_KEYEnvia uma API key estática em um header HTTP configurável (padrão: X-API-Key).
Basic AuthBASICEnvia username:password no header padrão Authorization: Basic ....
Bearer TokenBEAREREnvia um token no header Authorization: Bearer ....
NenhumNONESem autenticação. Não recomendado para produção.

Você configura o método de autenticação ao criar ou atualizar uma assinatura de webhook no Portal do Integrador. Acesse Webhooks > Editar Assinatura e selecione o método de autenticação desejado no menu suspenso. Será solicitado que você forneça as credenciais necessárias (por exemplo, seu segredo HMAC, API key, ou usuário/senha) dependendo do método escolhido.


Verificação de Assinatura HMAC

Quando authType está definido como HMAC, cada requisição inclui um header X-Signature contendo o hash HMAC-SHA256 codificado em Base64 do corpo bruto da requisição, calculado usando seu secret como chave.

Fórmula:

expected = base64(HMAC_SHA256(your_secret, raw_request_body))

Compare o valor calculado com o header X-Signature. Se forem iguais, a requisição é autêntica.

cuidado

Sempre utilize os bytes brutos do corpo da requisição para verificação, não uma versão re-parseada/re-serializada. Re-serializar JSON pode alterar a ordem dos campos ou espaços em branco, o que invalidará a assinatura.

Exemplos de Verificação

Node.js:

const crypto = require("crypto");

function verifySignature(secret, rawBody, signatureHeader) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("base64");
return expected === signatureHeader;
}

// In your Express handler:
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.headers["x-signature"];
if (!verifySignature(WEBHOOK_SECRET, req.body, signature)) {
return res.status(403).send("Invalid signature");
}
const event = JSON.parse(req.body);
// Process event...
res.sendStatus(200);
});

Python:

import hmac, hashlib, base64

def verify_signature(secret: str, raw_body: bytes, signature_header: str) -> bool:
expected = base64.b64encode(
hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
).decode()
return hmac.compare_digest(expected, signature_header)

Go:

func verifySignature(secret string, rawBody []byte, signatureHeader string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(rawBody)
expected := base64.StdEncoding.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(signatureHeader))
}

Autenticação por API Key

Quando authType está definido como API_KEY, enviamos sua API key configurada em um header HTTP em todas as requisições. O nome padrão do header é X-API-Key, mas você pode personalizá-lo via authConfig.header.

# Creating a subscription with API Key auth:
curl -X POST "https://api.corpxapi.com/v1/webhooks" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Tenant-Id: your-tenant-id" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhook",
"authType": "API_KEY",
"authConfig": {
"key": "your-api-key-value",
"header": "X-API-Key"
},
"eventTypes": ["pix.in.completed"]
}'

Seu servidor deve validar que o valor do header corresponde à chave esperada.


Basic Auth

Quando authType está definido como BASIC, enviamos o header Authorization: Basic <base64(username:password)> em todas as requisições.

{
"authType": "BASIC",
"authConfig": {
"username": "your-username",
"password": "your-password"
}
}

Bearer Token

Quando authType está definido como BEARER, enviamos o header Authorization: Bearer <token> em todas as requisições.

{
"authType": "BEARER",
"authConfig": {
"token": "your-bearer-token"
}
}

Headers Informativos

Além dos headers de autenticação acima, nossa infraestrutura de entrega adiciona os seguintes headers informativos em todas as requisições:

HeaderDescrição
x-hookdeck-event-idID do evento de entrega (útil para depuração e solicitações de suporte).
x-hookdeck-request-idID da requisição original.
x-hookdeck-attempt-countNúmero da tentativa de entrega (1 para a primeira tentativa).

Esses headers são informativos e não precisam ser validados.

IP Whitelist

Para aumentar a segurança da sua integração, recomendamos que seu servidor de destino valide o endereço IP de origem das requisições. Aceite notificações apenas dos seguintes IPs da nossa infraestrutura:

  • 34.138.140.223
  • 34.138.161.100
  • 35.231.250.193
  • 35.196.71.29
  • 34.138.56.192

Sugerimos adicionar esses endereços a uma whitelist no seu firewall ou servidor web.

Retentativas

Se sua aplicação retornar um erro (status diferente de 2xx) ou ocorrer um timeout, nosso sistema tentará reenviar a notificação seguindo uma estratégia de backoff exponencial:

  • Tentativas: Até 6 vezes.
  • Intervalos: Progressivamente crescentes.

Após esgotar todas as tentativas, o evento será marcado como falho. Você pode solicitar um reenvio manual usando o endpoint de Replay na nossa API.

Reenvio de Eventos (Replay)

Se você precisar reenviar um evento (devido a falha no processamento ou notificação perdida), utilize o endpoint /v1/webhooks/replay.

Exemplo de Requisição:

curl -X POST "https://api.corpxapi.com/v1/webhooks/replay" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Tenant-Id: your-tenant-id" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"eventId": "evt_abc_123",
"tenantId": "your-tenant-id"
}'

A API retornará um status 202 Accepted e o evento será enfileirado para uma nova tentativa de entrega.

Formato das Notificações

Todas as notificações seguem um formato de envelope padrão. O conteúdo específico de cada evento está no objeto data.

Envelope Padrão

{
"id": "evt_123456789",
"type": "pix.in.completed",
"occurredAt": "2025-12-29T21:14:33.912Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "acc_123456",
"data": { }
}

Campos comuns dentro de data

Alguns campos aparecem em todos os tipos de evento que representam um lançamento no extrato (PIX IN/OUT, refund, QR paid, transferência interna, tarifa). Eles são a forma recomendada de amarrar o webhook com outros endpoints da API:

CampoDescrição
transactionIdIdentificador da transação no formato usado pela nossa API. Bate com o que aparece no GET /v1/accounts/{accountId}/statement e com a resposta síncrona do endpoint que originou a transação. Use para buscar a transação nas nossas APIs.
coreIdIdentificador (UUID) da linha no core bancário do parceiro. É o mesmo valor exposto no campo coreId do extrato e permanece estável entre o webhook e o sync assíncrono. Use para reconciliar com exports do parceiro.
endToEnd / endToEndIdID E2E do PIX no Banco Central (somente para eventos PIX).
statusEstado da transação. Vocabulário padronizado (ver tabela abaixo).

Os três primeiros campos podem coexistir no mesmo payload. Se só um estiver presente, é porque o outro não existe para aquele tipo de evento (por exemplo: transferências internas têm transactionId + coreId mas não têm endToEnd).

Valores de data.status

O campo status usa um vocabulário padronizado em todos os eventos:

StatusSignificadoEventos em que aparece
SUCCESSOperação concluída com sucesso, saldo debitado/creditado.pix.in.completed, pix.out.completed, pix.refund.completed, qrcode.paid, transfer.internal.in, transfer.internal.out, fee.charged, fee.refunded
FAILEDOperação falhou. Saldo não foi alterado (ou foi devolvido). Verifique data.error para detalhes.pix.out.failed, pix.refund.failed
REVERSEDPIX IN que tinha sido concluído mas foi revertido (ex.: devolução total). Aparece se a reconciliação tardia alterar o status de um PIX IN já entregue.pix.in.completed (raro, pós-reconciliação)

Para eventos de MED (disputa), status usa um vocabulário próprio:

StatusSignificado
OPENDisputa aberta pelo reclamante, aguardando resposta.
PENDING_DECISIONResposta enviada, aguardando decisão do regulador/banco central.
ACCEPTEDDisputa aceita — valor devolvido (total ou parcialmente).
REJECTEDDisputa rejeitada — valor permanece com o recebedor.
CANCELEDDisputa cancelada pelo reclamante ou regulador.

Eventos em que aparece: pix.med.opened, pix.med.updated.

Garantia do status

O status é sempre presente em eventos que representam lançamento de extrato. Se você recebeu um webhook que não tem o campo (ou está vazio), é porque é um evento puramente informativo (ex.: account.balance_updated) — nesses casos use o próprio type para determinar a semântica.

Formato de datas e horários

Todos os campos de data/hora retornados pela API e pelos webhooks seguem o padrão ISO 8601 / RFC 3339 em UTC, com o sufixo Z. Isso vale para o envelope (occurredAt) e para todos os campos dentro de data (receivedAt, completedAt, initiatedAt, chargedAt, openedAt, etc.) — bem como para os campos createdAt/updatedAt retornados pelos endpoints REST (/statement, /balance, /payments, etc.).

Exemplos:

2026-04-29T23:53:55.001Z         ← com milissegundos
2026-04-29T23:53:49.328720Z ← com microssegundos
2026-04-30T18:04:36Z ← sem fração de segundo

Nunca emitimos timestamps no fuso local brasileiro (BRT) nem timestamps "naive" (sem indicador de fuso). Caso você receba um campo de data sem o Z no final, considere bug e nos avise — converteremos sempre que detectarmos a fonte.


Tipos de Eventos e Conteúdos (data)

1. pix.in.completed

Enviado quando um PIX é recebido com sucesso (entrada) na conta.

Estrutura do data:

  • endToEnd: ID único da transação no Banco Central.
  • amount: Valor da transação.
  • currency: Moeda (ex.: "BRL").
  • payer: Dados do pagador (nome, documento, banco, agência, conta).
  • payee: Dados do recebedor (nome, documento, banco, agência, conta).
  • reconciliationId: Identificador de reconciliação do parceiro bancário (quando disponível).
  • receivedAt: Timestamp do recebimento.

Exemplo Completo:

{
"id": "evt_123456789",
"type": "pix.in.completed",
"occurredAt": "2025-12-29T21:14:33.912Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "acc_123456",
"data": {
"endToEnd": "E0000000020251229211433912",
"amount": 150.50,
"currency": "BRL",
"reconciliationId": "FAlGf89fN0ol41Wyc5zVQ0k5KD",
"payer": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"payee": {
"name": "Test Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"receivedAt": "2025-12-29T21:14:33.900Z"
}
}

2. qrcode.paid

Enviado quando um QR Code gerado por você é pago.

Estrutura do data:

  • endToEnd: ID único da transação no Banco Central.
  • type: Tipo do QR Code (static ou dynamic).
  • identifier: txid (identificador) do QR Code.
  • qrcodeId: ID interno do QR Code.
  • amount: Valor pago.
  • currency: Moeda.
  • payer: Dados do pagador.
  • payee: Dados do recebedor.
  • reconciliationId: Identificador de reconciliação do parceiro bancário (quando disponível).
  • receivedAt: Timestamp do recebimento.

Exemplo Completo:

{
"id": "evt_987654321",
"type": "qrcode.paid",
"occurredAt": "2025-12-29T21:15:00.000Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "acc_123456",
"data": {
"endToEnd": "E0000000020251229211500000",
"type": "dynamic",
"identifier": "txid-qr-123",
"qrcodeId": "qr_abc123",
"amount": 250.00,
"currency": "BRL",
"reconciliationId": "FAlGf89fN0ol41Wyc5zVQ0k5KD",
"payer": {
"name": "Maria Oliveira",
"document": "98765432100",
"bankCode": "033",
"branch": "0001",
"accountNumber": "54321-0"
},
"payee": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"receivedAt": "2025-12-29T21:14:33.900Z"
}
}

3. pix.out.completed

Enviado quando uma transferência PIX de saída é concluída com sucesso.

Estrutura do data:

  • endToEnd: ID end-to-end.
  • key: Chave de destino utilizada.
  • identifier: Identificador da transação.
  • amount: Valor transferido.
  • payer: Dados da sua conta.
  • payee: Dados do destinatário.
  • reconciliationId: Identificador de reconciliação do parceiro bancário (quando disponível).
  • initiatedAt: Quando a transferência foi iniciada.
  • completedAt: Quando foi confirmada.

Exemplo Completo:

{
"id": "evt_out_123",
"type": "pix.out.completed",
"occurredAt": "2025-12-29T21:14:53.900Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "acc_123456",
"data": {
"endToEnd": "E9999999920251229211433900",
"key": {
"type": "CPF",
"key": "12345678900"
},
"identifier": "transfer-001",
"amount": 50.00,
"currency": "BRL",
"reconciliationId": "FAlGf89fN0ol41Wyc5zVQ0k5KD",
"payer": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"payee": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"initiatedAt": "2025-12-29T21:14:33.900Z",
"completedAt": "2025-12-29T21:14:53.900Z"
}
}

4. pix.out.failed

Enviado quando uma transferência PIX de saída falha.

Estrutura do data:

  • endToEnd: ID end-to-end (se disponível).
  • error: Descrição do erro/motivo da falha.
  • key: Chave de destino.
  • identifier: Identificador da transação.
  • amount: Valor.
  • payer: Dados da sua conta.
  • payee: Dados do destinatário.
  • reconciliationId: Identificador de reconciliação do parceiro bancário (quando disponível).
  • initiatedAt: Timestamp de início.

Exemplo Completo:

{
"id": "evt_out_err_123",
"type": "pix.out.failed",
"occurredAt": "2025-12-29T21:14:35.000Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "acc_123456",
"data": {
"endToEnd": "E9999999920251229211433900",
"error": "Insufficient balance in destination account or invalid key",
"key": {
"type": "EMAIL",
"key": "teste@exemplo.com"
},
"identifier": "transfer-002",
"amount": 1000.00,
"currency": "BRL",
"payer": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"payee": {
"name": "Failed Recipient",
"document": "00000000000",
"bankCode": "001",
"branch": "0001",
"accountNumber": "00000-0"
},
"initiatedAt": "2025-12-29T21:14:33.900Z"
}
}

5. payment.sent (removido)

Removido em v1.28.0 (2026-04-17)

Este evento foi marcado como deprecated na v1.15.0 (2026-02-20) e foi permanentemente desativado na v1.28.0 (2026-04-17). Use pix.out.completed com o campo method (PAYMENT) e o objeto payment no payload.

6. payment.refunded (removido)

Removido em v1.28.0 (2026-04-17)

Este evento foi marcado como deprecated na v1.15.0 (2026-02-20) e foi permanentemente desativado na v1.28.0 (2026-04-17). Use pix.refund.completed que inclui originalEndToEnd, refundEndToEnd e detalhes das partes.

7. pix.refund.completed

Enviado quando uma devolução PIX é concluída.

Estrutura do data:

  • originalEndToEnd: ID da transação original sendo devolvida.
  • refundEndToEnd: ID do novo PIX de devolução.
  • identifier: Identificador da devolução.
  • amount: Valor devolvido.
  • payer: Dados da sua conta (quem está emitindo a devolução).
  • payee: Dados do destinatário (quem está recebendo a devolução).
  • reconciliationId: Identificador de reconciliação do parceiro bancário (quando disponível).
  • initiatedAt: Timestamp de início.
  • completedAt: Timestamp de conclusão.

Exemplo Completo:

{
"id": "evt_ref_123",
"type": "pix.refund.completed",
"occurredAt": "2025-12-29T21:14:53.900Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "acc_123456",
"data": {
"originalEndToEnd": "E0000000020251229211433912",
"refundEndToEnd": "D0000000020251229211453900",
"identifier": "refund-999",
"amount": 150.50,
"currency": "BRL",
"payer": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"payee": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"initiatedAt": "2025-12-29T21:14:33.900Z",
"completedAt": "2025-12-29T21:14:53.900Z"
}
}

8. pix.refund.failed

Enviado quando uma solicitação de devolução falha.

Estrutura do data:

  • originalEndToEnd: ID da transação original.
  • error: Motivo da falha.
  • identifier: Identificador.
  • amount: Valor.
  • payer: Dados da sua conta.
  • payee: Dados do destinatário.
  • initiatedAt: Timestamp de início.

Exemplo Completo:

{
"id": "evt_ref_err_123",
"type": "pix.refund.failed",
"occurredAt": "2025-12-29T21:14:35.000Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "acc_123456",
"data": {
"originalEndToEnd": "E0000000020251229211433912",
"error": "Original transaction has already been refunded",
"identifier": "refund-998",
"amount": 150.50,
"currency": "BRL",
"payer": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"payee": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"initiatedAt": "2025-12-29T21:14:33.900Z"
}
}

9. fee.charged

Enviado quando uma tarifa bancária é cobrada na conta (por exemplo, tarifa por transação PIX).

Estrutura do data:

  • amount: Valor da tarifa cobrada.
  • currency: Moeda.
  • feeServiceType: Tipo de operação que gerou a tarifa (ex: PIX_OUT, PIX_IN).
  • description: Descrição da tarifa.
  • chargedAt: Timestamp da cobrança.

Exemplo Completo:

{
"id": "evt_fee_123",
"type": "fee.charged",
"occurredAt": "2026-02-14T20:30:43.000Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "acc_123456",
"data": {
"amount": 2.99,
"currency": "BRL",
"feeServiceType": "PIX_OUT",
"description": "Tarifa Bancária",
"chargedAt": "2026-02-14T20:30:43.000Z"
}
}

10. pix.med.opened

Enviado quando uma nova disputa MED (Mecanismo Especial de Devolução) é aberta contra uma transação.

Estrutura do data:

  • endToEndId: ID da transação em disputa.
  • identifier: Identificador associado.
  • qrcodeId: ID do QR Code (se aplicável).
  • amount: Valor disputado.
  • currency: Moeda.
  • claimant: Dados de quem abriu a reclamação (nome, documento, banco, agência, conta).
  • openedAt: Data de abertura do MED.
  • deadlineAt: Data limite para resposta.

Exemplo Completo:

{
"id": "evt_med_123",
"type": "pix.med.opened",
"occurredAt": "2025-12-29T21:14:33.912Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "acc_123456",
"data": {
"endToEndId": "E0000000020251229211433912",
"identifier": "tx-med-001",
"qrcodeId": "qr_abc123",
"amount": 150.50,
"currency": "BRL",
"claimant": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"openedAt": "2025-12-29T21:14:33.900Z",
"deadlineAt": "2026-01-05T21:14:33.900Z"
}
}

10. pix.med.updated

Enviado quando uma disputa MED (Mecanismo Especial de Devolução) é atualizada (mudança de status, nova informação, resolução).

Estrutura do data:

  • endToEndId: ID da transação em disputa.
  • identifier: Identificador associado.
  • qrcodeId: ID do QR Code (se aplicável).
  • amount: Valor disputado.
  • currency: Moeda.
  • status: Status atual do MED (OPEN, CLOSED, AGREED, DISAGREED).
  • result: Resultado da disputa (se resolvida).
  • claimant: Dados de quem abriu a reclamação.
  • openedAt: Data de abertura do MED.
  • updatedAt: Data da última atualização.

Exemplo Completo:

{
"id": "evt_med_456",
"type": "pix.med.updated",
"occurredAt": "2025-12-30T15:20:00.000Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "acc_123456",
"data": {
"endToEndId": "E0000000020251229211433912",
"identifier": "tx-med-001",
"qrcodeId": "qr_abc123",
"amount": 150.50,
"currency": "BRL",
"status": "CLOSED",
"result": "AGREED",
"claimant": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"openedAt": "2025-12-29T21:14:33.900Z",
"updatedAt": "2025-12-30T15:20:00.000Z"
}
}

11. transfer.internal.in

Enviado à conta que recebe uma transferência interna entre contas do mesmo ecossistema bancário. Transferências internas são instantâneas e liquidadas no mesmo banco — não trafegam pelo SPI do PIX, portanto não possuem endToEndId.

Estrutura do data:

  • transactionId: ID da transação no nosso sistema (formato internal-{uuid}). Use no GET /v1/accounts/{accountId}/statement.
  • amount: Valor recebido.
  • currency: Moeda.
  • status: Sempre SUCCESS (transferências internas são atômicas).
  • completedAt: Data/hora da liquidação.
  • identifier: Identificador fornecido pelo pagador no POST /transfers/internal* (se informado) — presente apenas na notificação enviada à conta que originou a transferência (transfer.internal.out). Na conta recebedora normalmente vem vazio.
  • payerDescription / description: Descrição informada pelo pagador.
  • source: Dados do pagador (nome, CPF/CNPJ, providerAccountId, accountId).
  • destination: Dados do recebedor.

Exemplo Completo:

{
"id": "evt_int_in_001",
"type": "transfer.internal.in",
"occurredAt": "2026-04-23T14:21:05.000Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "773107de-139e-48d1-9462-f4e88f251891",
"data": {
"transactionId": "internal-9d4a5b7c-1234-4abc-9876-abc123456789",
"amount": 500.00,
"currency": "BRL",
"status": "SUCCESS",
"completedAt": "2026-04-23T14:21:05.000Z",
"payerDescription": "Pagamento salário",
"source": {
"providerAccountId": "a1b2c3d4-...",
"accountId": "e5f6g7h8-...",
"name": "EMPRESA ORIGEM LTDA",
"taxId": "12345678000199"
},
"destination": {
"providerAccountId": "b2c3d4e5-...",
"accountId": "773107de-139e-48d1-9462-f4e88f251891",
"name": "MARIA SILVA",
"taxId": "12345678900"
}
}
}

12. transfer.internal.out

Enviado à conta que envia uma transferência interna. Mesmo formato do transfer.internal.in, com duas diferenças:

  • O campo identifier é preenchido quando o integrador passou identifier no corpo da requisição original (POST /v1/accounts/{accountId}/transfers/internal*). Use-o para reconciliar a transferência no seu lado.
  • description — se o integrador passou description na requisição, esse mesmo texto volta aqui (e não o texto padrão Transferência Interna).

Exemplo:

{
"id": "evt_int_out_001",
"type": "transfer.internal.out",
"occurredAt": "2026-04-23T14:21:05.000Z",
"schemaVersion": "1.0",
"environment": "production",
"accountId": "a1b2c3d4-aaaa-bbbb-cccc-111122223333",
"data": {
"transactionId": "internal-9d4a5b7c-1234-4abc-9876-abc123456789",
"amount": 500.00,
"currency": "BRL",
"status": "SUCCESS",
"completedAt": "2026-04-23T14:21:05.000Z",
"identifier": "int-transfer-12345",
"description": "Pagamento salário",
"source": {
"providerAccountId": "a1b2c3d4-...",
"accountId": "a1b2c3d4-aaaa-bbbb-cccc-111122223333",
"name": "EMPRESA ORIGEM LTDA",
"taxId": "12345678000199"
},
"destination": {
"providerAccountId": "b2c3d4e5-...",
"accountId": "773107de-139e-48d1-9462-f4e88f251891",
"name": "MARIA SILVA",
"taxId": "12345678900"
}
}
}
Como reconciliar a transferência interna

Ao chamar POST /v1/accounts/{accountId}/transfers/internal (ou as variantes by-document / by-bank-account), envie um identifier único seu. A resposta da API traz esse identifier junto com o transactionId. O webhook transfer.internal.out chega depois trazendo o mesmo identifier + transactionId, permitindo que você feche a transação no seu sistema sem consultar o extrato.

Boas Práticas

  • Idempotência: Sua aplicação deve estar preparada para receber o mesmo webhook mais de uma vez. Utilize o id do envelope para evitar processamento duplicado.
  • Resposta Rápida: Retorne um status 200 OK assim que receber o webhook e processe a lógica de negócio de forma assíncrona para evitar timeouts.
  • Validação de Timestamp: Verifique se o occurredAt não é muito antigo (recomendamos uma tolerância de 5 minutos) para prevenir ataques de replay.