Tipo de página: docs
Webhooks
Mensagens verificadas e contratos de webhook de financiamento, tratamento de duplicatas e comportamento de reconciliação atual.
Resposta direta
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.