# 4send — Webhooks (o aviso de volta)

Cadastre um endpoint HTTP em **Integrações → Webhooks**. O 4send faz `POST` nele
quando eventos acontecem. Ao criar o webhook, você recebe um **secret** — guarde-o
pra verificar a assinatura.

## Formato do corpo
```json
{
  "event": "mensagem.entregue",
  "timestamp": "2026-08-04T12:00:00.000Z",
  "namespace": "default",
  "data": { "id": "msg_663f...", "channelType": "whatsapp", "status": "delivered", "contact": "ct_663f..." }
}
```

## Eventos
| Evento | Quando |
|---|---|
| `mensagem.enviada` | saiu do 4send |
| `mensagem.entregue` | entregue no aparelho |
| `mensagem.lida` | lida pelo destinatário |
| `mensagem.falhou` | falha no envio |
| `fluxo.concluido` | o contato percorreu a jornada até o fim |
| `fluxo.parado` | o contato SAIU antes do fim (comprou, respondeu, foi removido). Traz `reason` quando informado — é o que separa "converteu" de "desistiu" |
| `contato.criado` / `contato.atualizado` | mudança no contato |

## Assinatura (HMAC)
Toda entrega leva o cabeçalho:
```
X-4send-Signature: t=<timestamp>,v1=<hmac_sha256>
```
O `v1` é `HMAC_SHA256(secret, "<timestamp>.<corpo_cru>")` em hex. **Verifique sempre
contra o CORPO CRU** (raw body) — se você re-serializar o JSON, a assinatura quebra.

### Verificar em Node.js (Express)
```javascript
import crypto from 'node:crypto';
import express from 'express';

const app = express();
const SECRET = process.env.FOURSEND_WEBHOOK_SECRET;

// IMPORTANTE: capture o corpo CRU (não use express.json() antes de verificar)
app.post('/webhooks/4send', express.raw({ type: 'application/json' }), (req, res) => {
  const header = req.get('X-4send-Signature') || '';
  const m = /t=([^,]+),v1=(.+)/.exec(header);
  if (!m) return res.sendStatus(400);
  const [, t, sig] = m;
  const raw = req.body.toString('utf8');
  const expected = crypto.createHmac('sha256', SECRET).update(`${t}.${raw}`).digest('hex');
  const ok = sig.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
  if (!ok) return res.sendStatus(401);

  const evt = JSON.parse(raw);
  // ... trate evt.event / evt.data
  res.sendStatus(200);
});
```

### Verificar em Python
```python
import hmac, hashlib, re

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    m = re.match(r"t=([^,]+),v1=(.+)", header or "")
    if not m:
        return False
    t, sig = m.group(1), m.group(2)
    expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(sig, expected)
```

## Boas práticas
- Responda `2xx` rápido; processe o evento em background.
- O 4send re-tenta em caso de falha (backoff) — trate entregas repetidas de forma
  idempotente (ex.: dedupe por `data.id` + `event`).
