> ## 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 e callbacks

> Envie eventos do Matcher para ferramentas externas e receba callbacks de resolução para manter seus fluxos de conciliação sempre sincronizados.

Webhooks permitem comunicação em tempo real entre o Matcher e sistemas externos. Este guia aborda notificações de eventos de saída e callbacks de resolução de entrada.

## Visão geral

***

O Matcher suporta comunicação bidirecional via webhook, mantendo suas ferramentas operacionais sincronizadas com cada evento de conciliação em tempo real. Isso reduz a intervenção manual, ajuda a manter o cumprimento de SLAs e garante uma trilha de auditoria contínua em todos os sistemas conectados.

* **Webhooks de saída**: o Matcher notifica sistemas externos quando eventos ocorrem
* **Callbacks de entrada**: sistemas externos notificam o Matcher quando ações são tomadas

Quando algo acontece no Matcher, como uma nova exceção ou uma correspondência concluída, ele envia um evento para os seus endpoints configurados. Sistemas externos como JIRA ou ServiceNow podem então enviar callbacks para atualizar o status da exceção ou fechar itens automaticamente. Esse fluxo bidirecional mantém suas ferramentas sincronizadas sem intervenção manual.

<Frame caption="Fluxo bidirecional entre o Matcher e sistemas externos.">
  <img src="https://mintcdn.com/lerian-49cb71fc/dIivJl2jpQJ0JZcX/images/pt/d2/matcher-webhooks-callbacks.svg?fit=max&auto=format&n=dIivJl2jpQJ0JZcX&q=85&s=0c31d2367b9a68d4b31b5538ff04f20f" alt="Matcher Webhooks Callbacks" width="839" height="520" data-path="images/pt/d2/matcher-webhooks-callbacks.svg" />
</Frame>

## Eventos de saída

***

O Matcher emite eventos quando ações significativas ocorrem no processo de conciliação.

### Eventos disponíveis

O catálogo de eventos do Matcher é definido de forma centralizada (46 eventos na v4.1.0). Os eventos mais comumente consumidos estão agrupados por domínio abaixo.

**Configuração**

| Evento                           | Gatilho                                   | Uso típico                               |
| -------------------------------- | ----------------------------------------- | ---------------------------------------- |
| `reconciliation_context.created` | Contexto de conciliação criado            | Sincronização de provisionamento         |
| `reconciliation_context.updated` | Metadados ou status do contexto alterados | Rastreamento de mudanças de configuração |
| `reconciliation_context.deleted` | Contexto excluído                         | Desmontagem downstream                   |
| `reconciliation_source.created`  | Fonte criada dentro de um contexto        | Onboarding de fontes                     |
| `match_rule.created`             | Regra de correspondência criada           | Auditoria de mudanças de regras          |
| `match_rule.reordered`           | Prioridades de regras reordenadas         | Auditoria de mudanças de regras          |

**Descoberta (Fetcher)**

| Evento                             | Gatilho                                    | Uso típico                  |
| ---------------------------------- | ------------------------------------------ | --------------------------- |
| `fetcher_connection.synced`        | Snapshot de conexão e esquema sincronizado | Monitoramento de descoberta |
| `fetcher_connection.unreachable`   | Conexão marcada como inacessível           | Alertas de conectividade    |
| `extraction_request.created`       | Solicitação de extração criada             | Monitoramento de extração   |
| `extraction_request.submitted`     | Extração aceita pelo Fetcher               | Monitoramento de extração   |
| `extraction_request.completed`     | Extração concluída com artefato            | Disponibilidade de dados    |
| `extraction_request.failed`        | Extração falhou                            | Alertas de erro             |
| `extraction_request.cancelled`     | Extração cancelada                         | Monitoramento do pipeline   |
| `extraction_request.bridged`       | Extração vinculada a um job de ingestão    | Monitoramento do pipeline   |
| `extraction_request.bridge_failed` | Ponte para a ingestão falhou               | Alertas de erro             |

**Ingestão**

| Evento                | Gatilho                                           | Uso típico                         |
| --------------------- | ------------------------------------------------- | ---------------------------------- |
| `ingestion.completed` | Importação de arquivo concluída                   | Monitoramento de pipeline de dados |
| `ingestion.failed`    | Importação de arquivo falhou                      | Alertas de erro                    |
| `transaction.ignored` | Transação não correspondida marcada como ignorada | Trilha de auditoria                |

**Correspondência**

| Evento                       | Gatilho                                     | Uso típico                        |
| ---------------------------- | ------------------------------------------- | --------------------------------- |
| `match_run.completed`        | Job de correspondência concluído            | Monitoramento de jobs, relatórios |
| `match_run.failed`           | Job de correspondência falhou               | Alertas de erro                   |
| `match_group.confirmed`      | Grupo de correspondência confirmado         | Atualizações downstream           |
| `match_group.unmatched`      | Correspondência confirmada revertida        | Rastreamento de correções         |
| `transaction.matched`        | Transação marcada como correspondida        | Registro de auditoria             |
| `transaction.pending_review` | Candidato não automático precisa de revisão | Gatilhos de fila de revisão       |
| `fee_variance.created`       | Variação de taxa detectada                  | Investigação de taxas             |

**Exceções e disputas**

| Evento                            | Gatilho                                       | Uso típico                   |
| --------------------------------- | --------------------------------------------- | ---------------------------- |
| `exception.assigned`              | Exceção atribuída a um responsável            | Notificação de usuário       |
| `exception.resolved`              | Exceção resolvida                             | Sincronização de status      |
| `exception.dispatched`            | Exceção enviada para um destino externo       | Criação de tickets           |
| `exception.callback_processed`    | Callback externo processado                   | Sincronização de status      |
| `exception.force_match_resolved`  | Exceção resolvida via correspondência forçada | Fluxos de aprovação          |
| `exception.adjust_entry_resolved` | Exceção resolvida via lançamento de ajuste    | Trilha de auditoria          |
| `exception_comment.added`         | Comentário adicionado a uma exceção           | Sincronização de colaboração |
| `exception_comment.deleted`       | Comentário de exceção excluído                | Sincronização de colaboração |
| `dispute.opened`                  | Disputa aberta para uma exceção               | Rastreamento de disputas     |
| `dispute.won`                     | Disputa encerrada como ganha                  | Sincronização de status      |
| `dispute.lost`                    | Disputa encerrada como perdida                | Sincronização de status      |
| `evidence.submitted`              | Evidência enviada a uma disputa               | Rastreamento de disputas     |

**Governança e relatórios**

| Evento                     | Gatilho                                | Uso típico                    |
| -------------------------- | -------------------------------------- | ----------------------------- |
| `audit_log.created`        | Entrada de log de auditoria adicionada | Monitoramento de conformidade |
| `archive_metadata.created` | Ciclo de vida de arquivamento iniciado | Monitoramento de arquivamento |
| `archive.uploaded`         | Objeto de arquivo enviado              | Monitoramento de arquivamento |
| `archive.completed`        | Arquivo verificado e concluído         | Monitoramento de arquivamento |
| `actor.pseudonymized`      | Mapeamento de ator pseudonimizado      | Monitoramento de conformidade |
| `export_job.created`       | Job de exportação enfileirado          | Monitoramento de exportação   |
| `export_job.succeeded`     | Job de exportação concluído            | Disponibilidade de download   |
| `export_job.failed`        | Job de exportação falhou               | Alertas de erro               |
| `export_job.expired`       | Artefato de exportação expirado        | Ciclo de vida de exportação   |

### Estrutura do payload de evento

Todos os eventos seguem uma estrutura consistente:

```json theme={null}
{
 "id": "evt_001",
 "type": "exception.assigned",
 "timestamp": "2024-01-20T10:30:00Z",
 "version": "1.0",
 "tenant_id": "tenant_001",
 "context_id": "ctx_abc123",
 "data": {
 // Event-specific data
 },
 "metadata": {
 "correlation_id": "req_xyz789",
 "source": "matching_engine"
 }
}
```

## Payloads de eventos

***

### Ingestioncompleted

Disparado quando um lote de transações é importado com sucesso.

```json theme={null}
{
  "id": "evt_ing_001",
  "type": "ingestion.completed",
  "timestamp": "2024-01-20T10:30:00Z",
  "data": {
    "job_id": "job_imp_001",
    "source_id": "src_bank456",
    "source_name": "Chase Bank",
    "file_name": "statement_january.csv",
    "summary": {
      "total_rows": 1250,
      "imported": 1240,
      "duplicates_skipped": 8,
      "validation_errors": 2
    },
    "duration_seconds": 45,
    "started_at": "2024-01-20T10:29:15Z",
    "completed_at": "2024-01-20T10:30:00Z"
  }
}
```

### Matchconfirmed

Disparado quando uma correspondência é aprovada (automática ou manual).

```json theme={null}
{
  "id": "evt_mtch_001",
  "type": "match_group.confirmed",
  "timestamp": "2024-01-20T10:30:01Z",
  "data": {
    "match_id": "match_001",
    "confidence": 100,
    "rule_id": "rule_exact001",
    "rule_name": "Exact Match",
    "confirmation_type": "AUTO",
    "transactions": [
      {
        "id": "txn_bank_001",
        "source_name": "Chase Bank",
        "amount": 1000.0,
        "currency": "USD",
        "date": "2024-01-15"
      },
      {
        "id": "txn_ledger_001",
        "source_name": "Main Ledger",
        "amount": 1000.0,
        "currency": "USD",
        "date": "2024-01-15"
      }
    ],
    "variance": {
      "amount_diff": 0,
      "date_diff_days": 0
    }
  }
}
```

### Exceptionresolved

Disparado quando uma exceção é resolvida.

```json theme={null}
{
  "id": "evt_exc_002",
  "type": "exception.resolved",
  "timestamp": "2024-01-20T14:30:00Z",
  "data": {
    "exception_id": "exc_001",
    "resolution": {
      "type": "FORCE_MATCH",
      "match_id": "match_forced_001",
      "resolved_by": "user_123",
      "notes": "Verified: amount difference is bank wire fee"
    },
    "time_to_resolution": {
      "hours": 4,
      "within_sla": true
    }
  }
}
```

### Matchforcematched

Disparado quando um usuário força manualmente uma correspondência entre transações.

```json theme={null}
{
  "id": "evt_force_001",
  "type": "exception.force_match_resolved",
  "timestamp": "2024-01-20T14:30:00Z",
  "data": {
    "match_id": "match_forced_001",
    "exception_id": "exc_001",
    "forced_by": "user_123",
    "reason": "Amount difference is documented bank fee",
    "notes": "Verified with bank statement showing $250 wire fee deducted",
    "transactions": [
      {
        "id": "txn_bank_999",
        "source_name": "Chase Bank",
        "amount": 15000.0,
        "currency": "USD",
        "date": "2024-01-15"
      },
      {
        "id": "txn_ledger_777",
        "source_name": "Main Ledger",
        "amount": 15250.0,
        "currency": "USD",
        "date": "2024-01-14"
      }
    ],
    "variance": {
      "amount_diff": 250.0,
      "amount_variance_percent": 1.67,
      "date_diff_days": 1
    },
    "requires_approval": true,
    "approval_threshold": 10000.0
  }
}
```

<Note>
  Eventos de correspondência forçada são comumente usados para acionar fluxos de aprovação quando a variação excede os limites da empresa.
</Note>

### Matchunmatched

Disparado quando uma correspondência previamente confirmada é revertida.

```json theme={null}
{
  "id": "evt_unmatch_001",
  "type": "match_group.unmatched",
  "timestamp": "2024-01-20T15:45:00Z",
  "data": {
    "match_id": "match_001",
    "unmatched_by": "user_456",
    "reason": "Incorrect match - transactions belong to different invoices",
    "notes": "Bank txn is for Invoice #1234, ledger txn is for Invoice #5678",
    "original_match": {
      "confirmed_at": "2024-01-15T10:00:00Z",
      "confirmed_by": "system",
      "confidence": 85,
      "rule_name": "Tolerance Match"
    },
    "transactions": [
      {
        "id": "txn_bank_001",
        "source_name": "Chase Bank",
        "amount": 1000.0,
        "currency": "USD"
      },
      {
        "id": "txn_ledger_001",
        "source_name": "Main Ledger",
        "amount": 1005.0,
        "currency": "USD"
      }
    ],
    "action": {
      "exceptions_created": [
        "exc_new_001",
        "exc_new_002"
      ],
      "status": "Both transactions returned to unmatched pool"
    }
  }
}
```

<Warning>
  Desfazer uma correspondência confirmada cria novas exceções para ambas as transações e dispara uma entrada completa no log de auditoria.
</Warning>

### Matchruncompleted

Disparado quando uma execução de correspondência automática ou manual é concluída.

```json theme={null}
{
  "id": "evt_run_001",
  "type": "match_run.completed",
  "timestamp": "2024-01-20T06:05:23Z",
  "data": {
    "run_id": "run_001",
    "context_id": "ctx_abc123",
    "context_name": "Daily Bank Reconciliation",
    "trigger": "SCHEDULED",
    "started_at": "2024-01-20T06:00:00Z",
    "completed_at": "2024-01-20T06:05:23Z",
    "duration_seconds": 323,
    "statistics": {
      "transactions_processed": 1250,
      "matches_found": 1180,
      "matches_confirmed": 1120,
      "matches_pending_review": 60,
      "exceptions_created": 70,
      "by_confidence": {
        "high_90_100": 1120,
        "medium_60_89": 60,
        "low_0_59": 0
      }
    },
    "performance": {
      "transactions_per_second": 3.87,
      "avg_rule_evaluation_ms": 12.5
    }
  }
}
```

## Callbacks de entrada

***

Sistemas externos enviam callbacks para o Matcher para atualizar o status das exceções após o processamento. O endpoint de callback aceita atualizações de status, notas de resolução e mudanças de atribuição de qualquer sistema externo.

### Processar um callback

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/exceptions/{exceptionId}/callback" \
 -H "Authorization: Bearer $TOKEN" \
 -H "X-Idempotency-Key: callback-jira-1234" \
 -H "Content-Type: application/json" \
 -d '{
   "externalSystem": "JIRA",
   "externalIssueId": "RECON-1234",
   "status": "RESOLVED",
   "resolutionNotes": "Verified: amount difference is expected bank wire fee",
   "assignee": "john.doe@company.com"
 }'
```

O campo `externalSystem` identifica o sistema externo que processou a exceção. Valores comuns incluem `"JIRA"`, `"SERVICENOW"` ou `"WEBHOOK"`, mas os callbacks podem reportar qualquer identificador de sistema.

#### Resposta

```json theme={null}
{
  "status": "accepted"
}
```

<Tip>Referência da API: [Processar callback](/pt/reference/matcher/process-exception-callback)</Tip>

Quando o Matcher processa um callback, ele atualiza o status da exceção e registra a resolução na trilha de auditoria. Use o header `X-Idempotency-Key` para prevenir processamento duplicado.

### Retry automático para callbacks com falha

Se um callback anterior para a mesma chave de idempotência falhou durante o processamento, o Matcher tenta automaticamente readquirir o bloqueio de idempotência e reprocessar o callback. Isso significa que você não precisa gerar uma nova chave de idempotência ao retentar um callback com falha: basta reenviar a mesma requisição e o Matcher cuida da recuperação.

O comportamento de retry se aplica apenas a callbacks que foram marcados como `failed` internamente. Callbacks concluídos com sucesso continuam sendo deduplicados normalmente.

## Credenciais de callback

***

Callbacks de entrada são autenticados com um token bearer opaco que o sistema externo envia no header `X-Callback-Token`. Essas **credenciais de callback** são emitidas, listadas, rotacionadas e revogadas através de uma superfície CRUD dedicada em `/v1/exceptions/callbacks/credentials`. Cada credencial é vinculada ao tenant do chamador, e apenas o hash SHA-256 do token é armazenado no servidor — o token bruto é retornado **exatamente uma vez** no momento da emissão/rotação.

| Ação                  | Método e caminho                                                  | Notas                                                                                                                                                          |
| --------------------- | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Emitir credencial     | `POST /v1/exceptions/callbacks/credentials`                       | Cria uma credencial e retorna o token bruto uma vez (`201`).                                                                                                   |
| Listar credenciais    | `GET /v1/exceptions/callbacks/credentials`                        | Lista os metadados das credenciais do tenant (nunca os tokens brutos).                                                                                         |
| Rotacionar credencial | `POST /v1/exceptions/callbacks/credentials/{credentialId}/rotate` | Substitui atomicamente uma credencial ativa por uma recém-emitida (mesmo rótulo) e retorna o novo token bruto uma vez; a antiga é revogada na mesma transação. |
| Revogar credencial    | `DELETE /v1/exceptions/callbacks/credentials/{credentialId}`      | Revoga terminalmente uma credencial (`204`); auditada em modo somente-anexação.                                                                                |

<Tip>Referência da API: [Emitir credencial de callback](/pt/reference/matcher/mint-callback-credential) | [Listar credenciais de callback](/pt/reference/matcher/list-callback-credentials) | [Rotacionar credencial de callback](/pt/reference/matcher/rotate-callback-credential) | [Revogar credencial de callback](/pt/reference/matcher/revoke-callback-credential)</Tip>

### Emitir uma credencial

O corpo da requisição é opcional; forneça `externalSystem` como um rótulo legível para operadores do sistema que este token autentica.

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/exceptions/callbacks/credentials" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{ "externalSystem": "stripe" }'
```

A resposta `201` (`CredentialSecretResponse`) retorna:

| Campo            | Descrição                                                                                                                                |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `token`          | Token bearer bruto, exposto **uma vez**. Configure-o como o valor do header `X-Callback-Token` no sistema externo.                       |
| `credentialId`   | ID substituto da credencial emitida (usado para rotação/revogação).                                                                      |
| `createdAt`      | Momento da emissão (RFC 3339, UTC).                                                                                                      |
| `externalSystem` | O rótulo devolvido para confirmação.                                                                                                     |
| `webhookUrlHint` | Formato informativo da URL de callback de entrada para configurar externamente; o placeholder `{exceptionId}` é preenchido por callback. |

<Warning>
  O `token` bruto é exibido apenas nas respostas de emissão e rotação. Armazene-o com segurança ao recebê-lo — ele não pode ser recuperado novamente. Se for perdido ou vazado, rotacione ou revogue a credencial.
</Warning>

### Rotacionar uma credencial

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/exceptions/callbacks/credentials/{credentialId}/rotate" \
 -H "Authorization: Bearer $TOKEN"
```

A rotação retorna um novo `CredentialSecretResponse` (novo token bruto) e revoga a credencial anterior atomicamente, de modo que os chamadores externos não sofram interrupção ao trocar o token.

### Revogar uma credencial

```bash cURL theme={null}
curl -X DELETE "https://api.matcher.example.com/v1/exceptions/callbacks/credentials/{credentialId}" \
 -H "Authorization: Bearer $TOKEN"
```

A revogação é terminal: a credencial não pode mais autenticar callbacks de entrada.

## Segurança de webhooks

***

### Verificação de assinatura

Quando um segredo compartilhado de webhook está configurado, o Matcher assina cada entrega com um HMAC-SHA256 sobre o **corpo bruto da requisição** e o envia no header `X-Signature-256`, formatado como `sha256=<hex-digest>`:

```
X-Signature-256: sha256=abc123...
```

Cada entrega também inclui um header `X-Idempotency-Key` para que os receptores possam deduplicar retentativas.

**Processo de verificação:**

1. Calcule o HMAC-SHA256 do corpo bruto da requisição usando o segredo compartilhado do webhook
2. Adicione o prefixo `sha256=` ao hex digest
3. Compare (em tempo constante) com o header `X-Signature-256`

**Exemplo (Node.js):**

```javascript theme={null}
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
 const expectedSignature = crypto
 .createHmac('sha256', secret)
 .update(payload)
 .digest('hex');

 return `sha256=${expectedSignature}` === signature;
}
```

**Exemplo (Python):**

```python theme={null}
import hmac
import hashlib

def verify_webhook(payload, signature, secret):
 expected = hmac.new(
 secret.encode(),
 payload,
 hashlib.sha256
 ).hexdigest()
 return f"sha256={expected}" == signature
```

### Lista de permissão de IP

O Matcher envia webhooks a partir de faixas de IP específicas:

```
52.1.2.0/24
52.1.3.0/24
```

Configure seu firewall para permitir essas faixas.

### Requisitos de TLS

* Mínimo TLS 1.2
* Certificado SSL válido obrigatório
* Certificados autoassinados não são suportados em produção

## Lógica de retry

***

Entregas de webhook com falha são retentadas com backoff exponencial.

### Política de retry padrão

Uma entrega com falha é retentada até **3 vezes** por padrão. Os atrasos seguem backoff exponencial a partir de uma base de **1 segundo**, com jitter adicionado para distribuir as retentativas — então o espaçamento exato varia de uma tentativa para outra, em vez de seguir uma escala fixa.

### Condições de retry

Retries ocorrem para:

* Respostas HTTP 5xx
* Timeouts de conexão
* Falhas de resolução DNS

Sem retry para:

* Respostas HTTP 4xx (exceto 429)
* Certificados SSL inválidos
* Webhook desabilitado

## Melhores práticas

***

<AccordionGroup>
  <Accordion title="Verifique assinaturas de webhook">
    Sempre verifique a assinatura HMAC antes de processar payloads de webhook. Isso previne requisições falsificadas.
  </Accordion>

  <Accordion title="Responda rapidamente">
    Retorne uma resposta 2xx dentro de 5 segundos. Processe o evento de forma assíncrona se necessário.
  </Accordion>

  <Accordion title="Trate duplicatas de forma idempotente">
    Eventos podem ser entregues mais de uma vez. Use o ID do evento para deduplicação.
  </Accordion>

  <Accordion title="Monitore a saúde das entregas">
    Configure alertas para taxas de falha de webhook. Investigue falhas persistentes prontamente.
  </Accordion>

  <Accordion title="Use filtros de eventos">
    Inscreva-se apenas nos eventos que você precisa. A filtragem reduz ruído e carga de processamento.
  </Accordion>

  <Accordion title="Teste antes da produção">
    Use o endpoint de teste para verificar se seu handler de webhook funciona corretamente antes de habilitar em produção.
  </Accordion>
</AccordionGroup>

## Próximos passos

***

<Card title="Roteamento de exceções" icon="route" href="/pt/matcher/configuration/matcher-exception-routing" horizontal>
  Configure como exceções disparam eventos de webhook.
</Card>

<Card title="Fontes externas" icon="building-columns" href="/pt/matcher/integrations/matcher-external-sources" horizontal>
  Configure fontes de dados que podem enviar via webhooks.
</Card>
