# Webhooks

URL canônica: https://texttree.ai/pt-br/docs/webhooks/
URL em Markdown: https://texttree.ai/pt-br/docs/webhooks.md
Tipo de página: docs
Translation status: draft
Legal status: english_controls

## Resumo

Mensagens verificadas e contratos de webhook de financiamento, tratamento de duplicatas e comportamento de reconciliação atual.

## Conteúdo fonte

# Webhooks

TextTree atualmente aceita retornos de chamada de provedor de dois limites:

- eventos do provedor de mensagens
- Par para financiamento de eventos

Todas as rotas de webhook são endpoints JSON atendidos pelo Phoenix.

## Pontos finais

- retornos de chamada de eventos assinados do provedor de mensagens
- retornos de chamada recebidos assinados do provedor de mensagens
-`POST /webhooks/peer/events`

Os endpoints de webhooks do cliente são configurados na página de Webhooks autenticados. As rotas de
Webhooks do provedor anterior são os retornos de chamada do provedor de entrada que o TextTree usa para atualizar
o status das mensagens, cancelamentos (opt-out) e financiamento.

## Tipos de eventos do cliente

Inscreva seu endpoint nos eventos que seu aplicativo precisa:

-`message.sent`
-`message.delivered`
-`message.failed`
-`message.received`
-`conversation.created`
-`conversation.updated`
-`opt_out.created`

## Forma de eventos do cliente

As cargas úteis do webhook do cliente usam um wrapper estável para que os receptores possam rotear através de `type` e
inspecione o objeto de domínio em `data`.

```json
{
  "id": "evt_123",
  "type": "message.delivered",
  "created_at": "2026-04-28T14:00:00Z",
  "data": {
    "message": {
      "id": "msg_123",
      "status": "delivered",
      "phone_number": "+15551234567",
      "segments": 1,
      "cost_cents": 1
    }
  }
}
```

Retorna qualquer resposta `2xx` para marcar a entrega como bem-sucedida. As respostas não `2xx` são retidas para
depuração e nova tentativa/reprodução no console.

## Verificação de assinatura

A verificação do webhook é obrigatória na fase alfa atual.

- As solicitações do provedor de mensagens devem incluir o cabeçalho de assinatura configurado
- As solicitações do provedor de SMS devem incluir o carimbo de data/hora configurado e os cabeçalhos de assinatura
- As solicitações de pares devem incluir `x-peer-timestamp` e `x-peer-signature`
- Os valores de assinatura usam o formato `sha256=<hex>`

A assinatura é calculada como um HMAC-SHA256 sobre o carimbo de data/hora e a representação canônica
da carga útil do TextTree, não nos bytes brutos da solicitação. TextTree rejeita pares de carimbo de data/hora/assinatura
ausentes, obsoletos, futuros ou incompatíveis; A janela de atualização padrão é de cinco minutos.

## Resposta de aceitação

Um webhook verificado que passa na validação de forma retorna `202 Accepted`:

```json
{
  "id": "8fca25fd-d7b7-4f58-8bdd-d4ab4ca3ae97",
  "status": "received",
  "provider": "messaging_provider",
  "event_type": "message.delivered",
  "external_id": "provider_evt_123",
  "duplicate": false
}
```

Se os mesmos `event_type` e `external_id` forem enviados novamente pelo mesmo provedor, TextTree retornará o
registro existente com `"duplicate": true` e não enfileira trabalho downstream duplicado.

## Respostas de falha

- `401` com `{"error":"invalid_signature"}` quando a verificação falha
- `422` com `{"error":"invalid_webhook_payload"}` quando a solicitação é assinada, mas falta o
  campos obrigatórios de identidade do evento

## Reprodução do console

Qualquer falha na entrega do webhook do cliente deverá ser reproduzível após a correção do endpoint. O fluxo
O Replay preserva a carga original e registra uma nova tentativa de entrega com código de resposta, latência e
corpo de resposta.

```txt
Webhooks → select endpoint → open failed delivery → Replay webhook
```

## Manipulação de eventos de mensagens

As cargas úteis do provedor de mensagens são normalizadas usando chaves como `type`, `id`, `message_id` e `metadata`.

### Eventos de mensagens reconciliados

-`message.sent`
-`message.delivered`
-`message.failed`

Eles atualizam o status downstream da mensagem e podem preencher identificadores de provedor na mensagem armazenada.

### Eventos de desativação reconciliados

-`recipient.opted_out`
-`contact.opted_out`
-`message.opted_out`
-`message.unsubscribed`

Na V1, eles criam ou atualizam exclusões no nível do workspace com metadados do provedor. O
As exclusões do espaço de trabalho bloqueiam envios únicos da IU, envios de API do desenvolvedor, envios de MCP e
entregas de campanha para esse número de telefone.

## Manipulação de eventos de paresAs cargas de pares são normalizadas a partir de chaves como `event`, `event_id`, `session_id`, `amount_cents`
e `metadata`.

### Eventos de financiamento reconciliados

-`funding.completed`
-`funding.failed`
-`funding.expired`

Os eventos de financiamento concluídos atualizam o status da sessão de financiamento e criam créditos idempotentes no razão.
Os eventos de financiamento com falha e expirados atualizam o estado armazenado da sessão de financiamento para revisão do operador.

## Exemplos

### Evento de mensagens entregue

```json
{
  "type": "message.delivered",
  "id": "provider_evt_123",
  "message_id": "msg_123"
}
```

### Evento de desativação de mensagens

```json
{
  "type": "recipient.opted_out",
  "id": "provider_evt_456",
  "phone_number": "+15551234567",
  "message_id": "msg_123"
}
```

### Evento de financiamento entre pares

```json
{
  "event": "funding.completed",
  "event_id": "peer_evt_123",
  "session_id": "session_123",
  "amount_cents": 500
}
```

## Notas operacionais

- Os eventos do fornecedor são persistidos antes da reconciliação assíncrona.
- Os eventos com falha permanecem visíveis no `/app` com motivos de falha e controles de reprodução.
- A reprodução destina-se à recuperação do operador após a correção de problemas subjacentes de dados ou do provedor.
- Eventos desconhecidos, mas assinados de forma válida, podem ser armazenados e ignorados até que a camada de domínio os suporte.
