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
- Um evento ocorre na nossa plataforma.
- Enviamos uma requisição
POSTpara as URLs cadastradas. - 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.completedepix.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étodo | Valor de authType | Descrição |
|---|---|---|
| Assinatura HMAC | HMAC | Assina o corpo de cada requisição com seu segredo usando HMAC-SHA256. A assinatura é enviada no header X-Signature. Recomendado. |
| API Key | API_KEY | Envia uma API key estática em um header HTTP configurável (padrão: X-API-Key). |
| Basic Auth | BASIC | Envia username:password no header padrão Authorization: Basic .... |
| Bearer Token | BEARER | Envia um token no header Authorization: Bearer .... |
| Nenhum | NONE | Sem 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.
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:
| Header | Descrição |
|---|---|
x-hookdeck-event-id | ID do evento de entrega (útil para depuração e solicitações de suporte). |
x-hookdeck-request-id | ID da requisição original. |
x-hookdeck-attempt-count | Nú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.22334.138.161.10035.231.250.19335.196.71.2934.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:
| Campo | Descrição |
|---|---|
transactionId | Identificador 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. |
coreId | Identificador (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 / endToEndId | ID E2E do PIX no Banco Central (somente para eventos PIX). |
status | Estado 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:
| Status | Significado | Eventos em que aparece |
|---|---|---|
SUCCESS | Operaçã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 |
FAILED | Operação falhou. Saldo não foi alterado (ou foi devolvido). Verifique data.error para detalhes. | pix.out.failed, pix.refund.failed |
REVERSED | PIX 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:
| Status | Significado |
|---|---|
OPEN | Disputa aberta pelo reclamante, aguardando resposta. |
PENDING_DECISION | Resposta enviada, aguardando decisão do regulador/banco central. |
ACCEPTED | Disputa aceita — valor devolvido (total ou parcialmente). |
REJECTED | Disputa rejeitada — valor permanece com o recebedor. |
CANCELED | Disputa cancelada pelo reclamante ou regulador. |
Eventos em que aparece: pix.med.opened, pix.med.updated.
statusO 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 (staticoudynamic).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)
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)
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 (formatointernal-{uuid}). Use noGET /v1/accounts/{accountId}/statement.amount: Valor recebido.currency: Moeda.status: SempreSUCCESS(transferências internas são atômicas).completedAt: Data/hora da liquidação.identifier: Identificador fornecido pelo pagador noPOST /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 passouidentifierno 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 passoudescriptionna requisição, esse mesmo texto volta aqui (e não o texto padrãoTransferê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"
}
}
}
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
iddo envelope para evitar processamento duplicado. - Resposta Rápida: Retorne um status
200 OKassim 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
occurredAtnão é muito antigo (recomendamos uma tolerância de 5 minutos) para prevenir ataques de replay.