> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.userbot.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.userbot.ai/_mcp/server.

# Verifica firma HMAC

Ogni webhook inviato da Userbot è firmato con **HMAC-SHA256** per garantire due cose: che la richiesta provenga davvero da Userbot (autenticità) e che il payload non sia stato alterato in transito (integrità). Verificare la firma su **ogni** richiesta in ingresso non è opzionale in produzione — senza di essa, chiunque potrebbe inviare payload falsi al tuo endpoint.

Per il setup dell'endpoint e la struttura degli eventi, vedi [Ricevere eventi webhook](/api-ricevere-eventi-webhook).

## Perché verificare la firma

I webhook espongono il tuo backend a richieste HTTP da internet. Anche con HTTPS, un attaccante potrebbe:

* **Inviare payload falsi** — es. creare record CRM inesistenti o triggerare azioni indesiderate
* **Replay di eventi catturati** — ripetere un evento legittimo per causare duplicati

La firma HMAC risolve entrambi i problemi: solo chi possiede il Webhook Secret (tu e Userbot) può generare una firma valida, e il timestamp limita la finestra di replay.

## Algoritmo

Segui questi passi in ordine per ogni richiesta webhook:

1. **Estrai gli header** `x-userbot-signature` e `x-userbot-timestamp`. Se mancano, rifiuta la richiesta con 401.
2. **Verifica il timestamp** — deve essere entro **±5 minuti** dal tempo corrente del tuo server. Eventi troppo vecchi o nel futuro lontano vanno scartati (anti-replay).
3. **Costruisci la stringa da firmare**: `{timestamp}.{raw_body}` — usa il body HTTP **grezzo** così com'è arrivato, senza normalizzazioni JSON (spazi, ordine chiavi). Un body ri-serializzato produce una firma diversa.
4. **Calcola l'HMAC-SHA256** con il tuo **Webhook Secret** (fornito in dashboard alla creazione del webhook).
5. **Confronta** il risultato esadecimale con `x-userbot-signature` usando un confronto **timing-safe** (es. `crypto.timingSafeEqual` in Node.js, `hmac.compare_digest` in Python) — evita confronti stringa diretti che possono leakare informazioni.

## Pseudocodice

```
message = "{timestamp}.{raw_request_body}"
expected_signature = HMAC-SHA256(webhook_secret, message)
is_valid = timing_safe_compare(expected_signature, x-userbot-signature)
```

Se `is_valid` è false, rispondi 401 e non processare il payload.

## Retry e deduplicazione

Anche con firma valida, lo stesso evento può arrivare più volte. Userbot ritenta la consegna se il tuo server non risponde con **200** entro **5 secondi** — timeout, errori 5xx o elaborazioni troppo lente causano retry.

L'header `x-userbot-attempt` indica il numero del tentativo (1, 2, 3…). Implementa deduplicazione basata su:

* **`eventId`** — presente in ogni payload e nell'header `x-userbot-event-id`
* **`data.messageId`** — per l'evento `message.added`, utile come chiave aggiuntiva

Prima di elaborare, controlla se hai già processato quell'`eventId`. Se sì, rispondi 200 comunque (Userbot smette di ritentare) ma non ripetere l'azione di business.

Per un esempio completo di server con verifica HMAC, vedi la sezione "Esempio server" in [Ricevere eventi webhook](/api-ricevere-eventi-webhook).

## Checklist

* [ ] Webhook Secret in secret manager, non in codice
* [ ] Verifica timestamp ±5 minuti
* [ ] Body grezzo per il calcolo HMAC, non JSON ri-parsato
* [ ] Confronto timing-safe della firma
* [ ] Deduplicazione per `eventId` prima dell'elaborazione