> ## 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 a eventos de Bank Transfer em tempo real com webhooks — notificações de conclusão, falha, chargeback e reconciliação sem polling.

Webhooks permitem que seu sistema reaja a eventos de transferência em tempo real — sem necessidade de polling. Quando uma transferência é concluída, falha ou requer atenção, seu endpoint recebe uma notificação automaticamente.

## Eventos disponíveis

***

Cada evento lista os tipos de transferência a que se aplica (entre parênteses), quando é disparado e a ação recomendada.

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

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

* **Disparo**: registro de transferência criado após a confirmação da iniciação.
* **Ação**: atualize o status da transferência no seu sistema; exiba "transferência em andamento" ao cliente.

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

* **Disparo**: hold de transação no Midaz bem-sucedido; a transferência avança para a conclusão.
* **Ação**: exiba ao cliente que a transferência está sendo processada.

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

* **Disparo**: o JD SPB retornou uma rejeição 4xx (dados inválidos, violação de regra).
* **Ação**: notifique o cliente que a transferência foi rejeitada; os fundos já foram liberados.

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

* **Disparo**: transferência liquidada com sucesso.
* **Ação**: notifique o cliente; gere o recibo; atualize a exibição de saldo.

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

#### `transfer.reconciliation_required`

* **Disparo**: uma transferência com desfecho desconhecido foi marcada para reconciliação.
* **Ação**: acompanhe que a transferência está pendente de resolução; não presuma sucesso ou falha.

#### `transfer.reconciliation_resolved`

* **Disparo**: reconciliação concluída e a transferência atingiu um desfecho definitivo.
* **Ação**: atualize a transferência para seu status final.

#### `transfer.reconciliation_exhausted`

* **Disparo**: a reconciliação desistiu após o número máximo de tentativas.
* **Ação**: escale para revisão manual por um operador.

#### `transfer.reconciliation_failed`

* **Disparo**: uma tentativa de reconciliação em si falhou.
* **Ação**: monitore; o worker tentará novamente no próximo ciclo.

### Transferências recebidas (TED IN)

#### `transfer_incoming.completed`

* **Disparo**: TED de entrada recebida, destinatário encontrado, crédito aplicado.
* **Ação**: notifique o destinatário que os fundos chegaram; atualize a exibição de saldo.

#### `transfer_incoming.chargeback`

* **Disparo**: mensagem de estorno recebida para um TED IN previamente concluído (STR0010R2).
* **Ação**: bloqueie o valor creditado; inicie a revisão com sua equipe de compliance.

#### `transfer_incoming.undeliverable`

* **Disparo**: a TED de entrada não pôde ser creditada (por exemplo, conta do destinatário não encontrada).
* **Ação**: investigue; a transferência pode ser devolvida ao banco de origem.

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

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

* **Disparo**: uma devolução foi notificada para uma transferência de saída.
* **Ação**: reconcilie os fundos devolvidos com a transferência original.

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

* **Disparo**: uma iniciação de pagamento foi criada (etapa pré-transferência).
* **Ação**: opcional — acompanhe iniciações aguardando confirmação.

<Note>
  Para TED OUT, o evento `transfer.completed` ainda não é emitido. A conclusão do TED OUT é confirmada de forma assíncrona pelo SPB e será suportada em uma versão futura. Até lá, monitore o status do TED OUT pelo endpoint [Obter Transferência](/pt/reference/midaz/plugins/ted/retrieve-transfer) ou pelo endpoint de reconciliação.
</Note>

## Configuração de webhooks

***

Os webhooks têm escopo por tenant. Há duas formas de registrar um destino.

**API self-service (recomendada).** Registre um ou mais endpoints HTTPS através da API de registro de webhooks. Na criação, o servidor gera um `signingSecret` e o retorna **uma única vez** — armazene-o com segurança e use-o para verificar a assinatura em cada evento entregue. Você também pode listar, atualizar, desabilitar e excluir registros, rotacionar o signing secret e consultar os tipos de evento aceitos. O tenant dono de cada registro é derivado do bearer token, nunca de um cabeçalho de requisição.

* [Criar um registro de webhook](/pt/reference/midaz/plugins/ted/create-webhook) — `POST /v1/webhooks`
* [Listar registros de webhook](/pt/reference/midaz/plugins/ted/list-webhooks) — `GET /v1/webhooks`
* [Obter](/pt/reference/midaz/plugins/ted/get-webhook), [atualizar](/pt/reference/midaz/plugins/ted/update-webhook) e [excluir](/pt/reference/midaz/plugins/ted/delete-webhook) um registro
* [Rotacionar o signing secret](/pt/reference/midaz/plugins/ted/rotate-webhook-signing-secret) — `POST /v1/webhooks/{webhookId}/signing-secret/rotate`
* [Listar tipos de evento suportados](/pt/reference/midaz/plugins/ted/list-webhook-event-types) — `GET /v1/webhooks/event-types`

**Habilitando a entrega (operador/env).** A entrega de saída é ativada com `WEBHOOK_ENABLED=true`, que também requer RabbitMQ e a streaming outbox (`STREAMING_ENABLED=true`). Os destinos vêm dos registros acima — não há uma única variável de ambiente de endpoint estático. O ajuste por entrega (timeout, máximo de retentativas) é gerenciado em runtime via systemplane, não por variáveis de ambiente. Consulte [Configuração do Bank Transfer](/pt/rails/ted/jd/ted-configuration).

## Estrutura do payload

***

Todos os eventos de webhook compartilham o mesmo envelope. Os campos do envelope são estáveis entre tipos de evento; o payload específico de cada evento fica dentro de `payload`.

| Campo           | Tipo                  | Notas                                                                                                  |
| --------------- | --------------------- | ------------------------------------------------------------------------------------------------------ |
| `eventId`       | string (UUID)         | Identificador único desta emissão de evento. Use-o para deduplicar entregas at-least-once no seu lado. |
| `version`       | string                | Versão do schema do envelope. Atualmente `v1`.                                                         |
| `type`          | string                | Tipo de evento, ex: `transfer.completed`.                                                              |
| `tenantId`      | string (UUID)         | Organização dona da transferência.                                                                     |
| `transferId`    | string (UUID)         | Presente em eventos com escopo de transferência; omitido em eventos com escopo de tenant.              |
| `correlationId` | string                | Correlaciona a cadeia de eventos produzida por uma requisição originária.                              |
| `causationId`   | string                | Opcional. Id do evento que causou este (para fluxos encadeados).                                       |
| `occurredAt`    | string (RFC3339, UTC) | Quando o evento ocorreu no lado do plugin.                                                             |
| `payload`       | object                | Campos específicos do evento. O schema depende de `type` (veja abaixo).                                |
| `metadata`      | object                | Mapa opcional string-para-string que carrega hints de tracing e roteamento.                            |

A seguir, um exemplo de `transfer.completed` para uma transferência P2P:

```json theme={null}
{
  "eventId": "019c96a0-ee10-7fff-aaaa-1111aaaa2222",
  "version": "v1",
  "type": "transfer.completed",
  "tenantId": "019c96a0-0a98-7287-9a31-786e0809c769",
  "transferId": "019c96a0-ab10-7cde-f1a2-0e1f2a3b4c5d",
  "correlationId": "019c96a0-aa10-7abc-d1e2-8c9d0e1f2a3b",
  "occurredAt": "2026-01-21T17:35:00Z",
  "payload": {
    "status": "COMPLETED",
    "transferType": "P2P",
    "midazTransactionId": "019c96a0-cd10-7eee-bbbb-3333bbbb4444",
    "confirmationNumber": "20260121001"
  },
  "metadata": {}
}
```

A forma de `payload` depende do tipo de evento. Para `transfer.completed`, os campos são `status`, `transferType`, `midazTransactionId` e `confirmationNumber` (cada um emitido apenas quando definido). Para obter valores, tarifas, dados do destinatário ou timestamps, recupere a transferência via [Obter Transferência](/pt/reference/midaz/plugins/ted/retrieve-transfer) usando o `transferId` do envelope.

<Note>
  Consulte a Referência da API para os schemas completos de payload de cada tipo de evento.
</Note>

## Tratamento de falhas na entrega

***

Se o seu endpoint não responder com status 2xx dentro de 5 segundos (`WEBHOOK_TIMEOUT_MS=5000`), o evento é reenviado automaticamente com backoff exponencial e full jitter. Após a tentativa inicial, o plugin faz até `WEBHOOK_MAX_RETRIES` retentativas (padrão `3`) — até **4 tentativas de entrega** no total. A base do backoff é **1 segundo**, dobrada a cada retry, com full jitter aplicado a cada delay:

| Tentativa   | Intervalo 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]`     |

Após todas as tentativas falharem (4 por padrão), o evento é movido para uma dead-letter queue (DLQ). Configure alertas na DLQ para identificar falhas persistentes de entrega antes que afetem suas operações. Ajuste `WEBHOOK_MAX_RETRIES` se o seu endpoint precisar de um orçamento de retry mais longo ou mais curto. (`WEBHOOK_RETRY_BACKOFF_MS` controla o backoff de reconexão ao broker, não o cronograma de retry HTTP por entrega acima.)

Para garantir entrega confiável: responda dentro de 5 segundos, use HTTPS com certificado válido e retorne 200 mesmo para eventos que você optar por ignorar. Delegue qualquer processamento pesado para uma fila em segundo plano — mantenha seu handler de webhook rápido.

## Idempotência

***

<Note>
  Seu endpoint pode receber o mesmo evento mais de uma vez. Use o `transferId` (e o nome do evento) para deduplicar: se já tiver processado essa combinação, retorne 200 e não execute nenhuma ação adicional.
</Note>

## Para desenvolvedores

***

Para código de validação de assinatura (JavaScript, Python, Go), implementação de retry e o checklist completo de integração, consulte o [guia do desenvolvedor TED](/pt/rails/ted/jd/ted-developer-guide).
