> ## 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.

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

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

* **Gatilho**: o plugin criou o registro da transferência TED OUT 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)

* **Gatilho**: o JD SPB rejeitou a requisição de transferência antes da aceitação (dados inválidos ou violação de regra).
* **Ação**: avise o cliente sobre a rejeição. O plugin já cancelou a retenção dos fundos.

#### `transfer.completed` (P2P)

* **Gatilho**: a transferência P2P liquidou com sucesso.
* **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ê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.
* **Ação**: avise o destinatário de que os fundos chegaram. Atualize o saldo mostrado.

#### `transfer_incoming.chargeback`

* **Gatilho**: chegou uma mensagem de chargeback para um TED IN concluído (STR0010R2).
* **Ação**: congele o valor creditado. Comece uma revisão com o seu time de compliance.

#### `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 pode devolvê-la ao banco de origem.

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

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

* **Gatilho**: chegou uma devolução para uma transferência de saída.
* **Ação**: concilie os fundos devolvidos com a transferência original.

#### `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.

<Note>
  Para o TED OUT, o plugin ainda não emite `transfer.completed`. O SPB confirma a conclusão do TED OUT de forma assíncrona, e um release futuro vai adicionar esse evento. Até lá, consulte o status do TED OUT com o endpoint [Get Transfer](/pt/reference/interfaces/ted-jd/retrieve-transfer) ou com o endpoint de conciliação.
</Note>

## 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](/pt/reference/interfaces/ted-jd/create-webhook): `POST /v1/webhooks`
* [Listar os registros de webhook](/pt/reference/interfaces/ted-jd/list-webhooks): `GET /v1/webhooks`
* [Obter](/pt/reference/interfaces/ted-jd/get-webhook), [atualizar](/pt/reference/interfaces/ted-jd/update-webhook) e [excluir](/pt/reference/interfaces/ted-jd/delete-webhook) um registro
* [Rotacionar o segredo de assinatura](/pt/reference/interfaces/ted-jd/rotate-webhook-signing-secret): `POST /v1/webhooks/{webhookId}/signing-secret/rotate`
* [Listar os tipos de evento aceitos](/pt/reference/interfaces/ted-jd/list-webhook-event-types): `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](/pt/interfaces/ted-jd/ted-configuration).

## 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](/pt/reference/interfaces/ted-jd/retrieve-transfer) 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](/pt/reference/interfaces/ted-jd/retrieve-transfer).
</Note>

## 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. 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. 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. Se você já processou essa combinação, retorne 200 e não faça mais nada.
</Note>

## 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](/pt/interfaces/ted-jd/ted-developer-guide).
