> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Reaja aos eventos do Bank Transfer em tempo real com webhooks de conclusão, falha, chargeback e conciliação, sem polling.

Os webhooks deixam o seu sistema reagir aos eventos de transferência em tempo real, sem polling. O plugin envia uma notificação ao seu endpoint quando uma transferência é concluída, falha ou precisa de atenção.

## Eventos disponíveis

***

Cada evento lista os tipos de transferência a que se aplica (entre parênteses), quando dispara e a ação recomendada. A devolução de um TED IN ou de um P2P envia apenas os próprios eventos de devolução, nunca um evento `transfer.*`. Os mesmos eventos chegam ao fluxo de eventos: veja [Eventos do TED JD](https://docs.lerian.studio/pt/reference/events/ted-jd.md).

### Ciclo de vida da transferência (TED OUT, P2P, TED entre cores)

#### `transfer.initiated` (TED OUT, TED entre cores)

* **Gatilho**: o plugin criou o registro da transferência TED OUT ou [TED entre cores](https://docs.lerian.studio/pt/interfaces/ted-jd/ted-cross-core.md) depois de confirmar a iniciação.
* **Ação**: atualize o status da transferência no seu sistema. Mostre "transferência em andamento" ao cliente.

#### `transfer.processing_started` (TED OUT)

* **Gatilho**: a transferência TED OUT entrou em processamento (caminho de status CREATED para PENDING para PROCESSING).
* **Ação**: mostre ao cliente que a transferência está em andamento.

#### `transfer.rejected` (TED OUT, TED entre cores)

* **Gatilho**: o JD SPB rejeitou a requisição de transferência no envio, ou o STR recusou a liquidação. Para um TED entre cores, o outro core recusou o crédito, ou o JD Courier não alcançou nenhum destinatário.
* **Ação**: avise o cliente sobre a rejeição. O plugin já cancelou a retenção dos fundos.

#### `transfer.completed` (TED OUT, P2P, TED entre cores)

* **Gatilho**: a transferência liquidou. Para um TED OUT, o STR liquidou a transferência, ou um operador a liquidou manualmente. Para um TED entre cores, o outro core creditou o destinatário.
* **Ação**: avise o cliente. Gere um comprovante. Atualize o saldo mostrado.

### Conciliação (TED OUT, TED IN)

#### `transfer.reconciliation_required`

* **Gatilho**: uma transferência com resultado desconhecido foi para a conciliação.
* **Ação**: acompanhe a transferência como pendente. Não suponha sucesso nem falha.

#### `transfer.reconciliation_resolved`

* **Gatilho**: a conciliação terminou e a transferência chegou a um resultado final.
* **Ação**: atualize a transferência para o status final.

#### `transfer.reconciliation_exhausted`

* **Gatilho**: a conciliação parou depois do número máximo de tentativas.
* **Ação**: escale a transferência para revisão manual do operador.

#### `transfer.reconciliation_failed`

* **Gatilho**: uma tentativa de conciliação encontrou um erro determinístico, que fez a transferência falhar.
* **Ação**: trate a transferência como falha e investigue.

#### `transfer.reconciliation_manual_retry_requested`

* **Gatilho**: um operador devolveu uma transferência à fila de conciliação para mais uma tentativa.
* **Ação**: registre a intervenção manual e o motivo dela. A mudança de estado e este fato não são acoplados atomicamente. Se o evento não chegar, confirme o estado da transferência pela API.

#### `transfer.scope_repaired`

* **Gatilho**: um operador corrigiu o ledger Midaz em que uma transferência está registrada, com [Repair Transfer Ledger Scope](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/repair-transfer-ledger-scope.md). Nenhum dinheiro foi movimentado.
* **Ação**: atualize a referência de ledger que você guarda para a transferência.

### Transferências de entrada (TED IN)

#### `transfer_incoming.completed`

* **Gatilho**: o plugin recebeu um TED de entrada, achou o destinatário e aplicou o crédito. Ele também dispara para um crédito ou uma devolução entre cores recebidos do outro core da sua instituição.
* **Ação**: avise o destinatário de que os fundos chegaram. Atualize o saldo mostrado.

#### `transfer_incoming.chargeback`

* **Gatilho**: o banco remetente aplicou um chargeback a um TED IN concluído (STR0010R2), e o plugin retirou o valor creditado da conta do destinatário. Status: `FAILED`.
* **Ação**: avise o destinatário. Comece uma revisão com o seu time de compliance se a sua política exigir.

#### `transfer_incoming.return_requested`

* **Gatilho**: uma [devolução de um TED IN](https://docs.lerian.studio/pt/interfaces/ted-jd/ted-in.md#return-a-received-transfer) entrou em processamento. A retenção está ativa, e o STR0010 está para ser enviado.
* **Ação**: mostre ao destinatário que os fundos estão voltando ao banco pagador.

#### `transfer_incoming.returned`

* **Gatilho**: o STR liquidou a devolução de um TED IN.
* **Ação**: atualize o saldo mostrado e registre a devolução.

#### `transfer_incoming.return_rejected`

* **Gatilho**: a devolução de um TED IN foi recusada, e o plugin cancelou a retenção dela.
* **Ação**: avise a pessoa que pediu a devolução.

#### `transfer_incoming.return_manual_review`

* **Gatilho**: a devolução de um TED IN aguarda um operador.
* **Ação**: resolva-a com [Resolver a conciliação da transferência](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/resolve-transfer-reconciliation.md).

#### `transfer_incoming.undeliverable`

* **Gatilho**: o plugin não conseguiu creditar um TED de entrada (por exemplo, não achou a conta do destinatário).
* **Ação**: investigue a transferência. O plugin a devolve ao banco de origem, ou a retém para um operador quando o destinatário não é encontrado e as devoluções automáticas estão desligadas. Veja [Receber (TED IN)](https://docs.lerian.studio/pt/interfaces/ted-jd/ted-in.md#what-happens-when-a-recipient-isnt-found).

### Devoluções e iniciação

#### `transfer_outgoing.devolution_notified` (TED OUT)

* **Gatilho**: chegou uma devolução para uma transferência de saída. `feeRefunded` diz se o plugin decidiu devolver a tarifa ao remetente, e `feeRefundedAmount` traz a tarifa quando decidiu. A transferência de reembolso registra o que o ledger lançou.
* **Ação**: concilie os fundos devolvidos com a transferência original.

#### `transfer_internal.returned` (P2P)

* **Gatilho**: o ledger estornou um P2P por meio de uma [devolução de P2P](https://docs.lerian.studio/pt/interfaces/ted-jd/ted-p2p.md#return-a-p2p-transfer).
* **Ação**: atualize o saldo mostrado das duas contas.

#### `transfer_internal.return_failed` (P2P)

* **Gatilho**: o ledger recusou uma devolução de P2P. Nada se moveu, e o P2P pode ser devolvido de novo.
* **Ação**: avise a pessoa que pediu a devolução.

#### `payment_initiation.created` (TED OUT, P2P)

* **Gatilho**: o plugin criou uma iniciação de pagamento (a etapa anterior à transferência).
* **Ação**: opcional. Acompanhe as iniciações que aguardam confirmação.

## Configurar webhooks

***

Os webhooks funcionam por tenant. Você registra um destino de uma destas duas formas.

**API self-service (recomendada).** Registre um ou mais endpoints HTTPS pela API de registro de webhooks. O servidor gera um `signingSecret` na criação e o retorna **uma vez**. Guarde-o com segurança. Use-o para verificar a assinatura de cada evento entregue. Você também pode listar, atualizar, desabilitar e excluir registros, rotacionar o segredo de assinatura e consultar os tipos de evento aceitos. O plugin deriva o tenant dono a partir do bearer token, nunca de um header de requisição.

* [Criar um registro de webhook](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/create-webhook.md): `POST /v1/webhooks`
* [Listar os registros de webhook](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/list-webhooks.md): `GET /v1/webhooks`
* [Obter](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/get-webhook.md), [atualizar](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/update-webhook.md) e [excluir](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/delete-webhook.md) um registro
* [Rotacionar o segredo de assinatura](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/rotate-webhook-signing-secret.md): `POST /v1/webhooks/{webhookId}/signing-secret/rotate`
* [Listar os tipos de evento aceitos](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/list-webhook-event-types.md): `GET /v1/webhooks/event-types`

**Habilitar a entrega (operador/ambiente).** Defina `WEBHOOK_ENABLED=true` para ligar a entrega de saída. A entrega também exige RabbitMQ e o outbox de streaming (`STREAMING_ENABLED=true`). Os destinos vêm dos registros acima. Não existe uma única variável de ambiente estática de endpoint. Você ajusta o comportamento por entrega (timeout e máximo de novas tentativas) em tempo de execução pelo systemplane, não por variáveis de ambiente. Veja [Configuração do Bank Transfer](https://docs.lerian.studio/pt/interfaces/ted-jd/ted-configuration.md).

## Estrutura do payload

***

O plugin entrega cada evento como um POST HTTPS. O corpo da requisição é o payload do evento em JSON. O tipo do evento e a assinatura viajam em headers HTTP, não no corpo.

| Header | Valor |
| - | - |
| `Content-Type` | `application/json`. |
| `X-Webhook-Event` | O tipo do evento, por exemplo `transfer.completed`. |
| `X-Webhook-Timestamp` | Horário da entrega como timestamp Unix (em segundos). A assinatura cobre esse valor. |
| `X-Webhook-Signature` | Assinatura HMAC-SHA256 sobre o timestamp e o corpo, com a chave `signingSecret` do registro. Formato: `v1,sha256=<hex>`. |

Os campos do corpo dependem do tipo do evento. Cada payload carrega `tenantId`, e os eventos com escopo de transferência também carregam `transferId`. Os valores são strings decimais na moeda da conta, não em centavos (por exemplo, `100.00`).

Este é um exemplo de corpo para `transfer.completed` em uma transferência P2P:

```json theme={null}
{
  "transferId": "019c96a0-ab10-7cde-f1a2-0e1f2a3b4c5d",
  "initiationId": "019c96a0-9a01-7bcd-e0f1-2a3b4c5d6e7f",
  "tenantId": "019c96a0-0a98-7287-9a31-786e0809c769",
  "ledgerId": "019c96a0-1b20-7def-a1b2-c3d4e5f60718",
  "senderAccountId": "019c96a0-2c30-7ef0-b2c3-d4e5f6071829",
  "recipientAccountId": "019c96a0-3d40-7f01-c3d4-e5f60718293a",
  "midazTransactionId": "019c96a0-cd10-7eee-bbbb-3333bbbb4444",
  "confirmationNumber": "20260121001",
  "status": "COMPLETED",
  "transferType": "P2P",
  "amount": "100.00",
  "feeAmount": "0.00",
  "totalAmount": "100.00",
  "completedAt": "2026-01-21T17:35:00Z"
}
```

O payload de `transfer.completed` carrega os valores, as contas e o `midazTransactionId`. Para eventos com um payload menor, ou para ler o registro completo da transferência, busque a transferência em [Get Transfer](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/retrieve-transfer.md) com o `transferId` dela.

> [!NOTE]
>
> Os campos do payload variam por tipo de evento. Para ler todos os campos de uma transferência, use o endpoint [Get Transfer](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/retrieve-transfer.md).

## Tratar falhas de entrega

***

O seu endpoint deve responder com um status 2xx em até 5 segundos (o padrão de `webhook.timeout_ms`). Se não responder, o plugin repete a entrega com backoff exponencial e full jitter. Uma resposta `4xx` diferente de `429` interrompe as novas tentativas de imediato, e o plugin não segue redirecionamentos. Depois da primeira tentativa, o plugin faz até 3 tentativas a mais (o padrão de `webhook.max_retries`), o que dá 4 tentativas de entrega no total. A base do backoff é 1 segundo e dobra a cada tentativa. O full jitter se aplica a cada atraso:

| Tentativa | Atraso antes desta tentativa |
| - | - |
| 1 (inicial) | Imediato |
| 2 | Aleatório em `[0, 1000 ms]` |
| 3 | Aleatório em `[0, 2000 ms]` |
| 4 | Aleatório em `[0, 4000 ms]` |

Depois que todas as tentativas falham (4 por padrão), o evento vai para uma fila de dead-letter (DLQ). Configure alertas na DLQ para pegar cedo as falhas de entrega persistentes. [List DLQ Messages](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/list-webhook-dlq-messages.md) lê a fila, e [Retry DLQ Message](https://docs.lerian.studio/pt/reference/interfaces/ted-jd/retry-webhook-dlq-message.md) envia uma mensagem de novo. Essas duas rotas existem apenas quando a autenticação está ligada. Ajuste `webhook.max_retries` pelo systemplane se o seu endpoint precisar de um orçamento maior ou menor de novas tentativas. O ajuste `webhook.retry_backoff_ms` controla o backoff de reconexão com o broker, não a agenda de novas tentativas HTTP por entrega descrita acima.

Para uma entrega confiável, siga estas regras:

* Responda em até 5 segundos.
* Use HTTPS com um certificado válido.
* Retorne 200 mesmo para os eventos que você ignora.
* Mova o processamento pesado para uma fila em segundo plano. Mantenha o handler do webhook rápido.

## Idempotência

***

> [!NOTE]
>
> O seu endpoint pode receber o mesmo evento mais de uma vez. Use o `transferId` do corpo e o header `X-Webhook-Event` para deduplicar. Para os eventos de devolução de um TED IN, adicione `status` e `reconciliationReasonCode` do corpo. Se você já processou essa combinação, retorne 200 e não faça mais nada.

## Para desenvolvedores

***

Para o código de validação de assinatura (JavaScript, Python, Go), a implementação das novas tentativas e o checklist completo de integração, veja o [guia do desenvolvedor do Bank Transfer](https://docs.lerian.studio/pt/interfaces/ted-jd/ted-developer-guide.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.