# Richieste webhook

> Il formato esatto delle richieste webhook di Emailit, dal metodo e dagli header all’array JSON di eventi, più ordine, duplicati e come rispondere.

Questa pagina descrive cosa arriva al tuo endpoint: la richiesta HTTP, i suoi header, il corpo JSON e cosa si aspetta Emailit in risposta. Usala quando scrivi o esegui il debug di un gestore di webhook.

## Richiesta

| Proprietà | Valore |
| --- | --- |
| Metodo | `POST` |
| Corpo | Un array JSON da 1 a 100 eventi, compatto (senza spazi superflui) |
| Timeout | 30 secondi |
| Reindirizzamenti | Non vengono seguiti. Una risposta `3xx` conta come errore. |
| Concorrenza | Una richiesta alla volta per webhook. I batch vengono inviati uno dopo l’altro. |
| Latenza | Emailit controlla la presenza di nuovi eventi ogni pochi secondi, quindi la maggior parte degli eventi arriva in pochi secondi. |

```http
POST /webhooks/emailit HTTP/1.1
Host: acme.com
Content-Type: application/json
User-Agent: Emailit-Webhooks/2.0
X-Emailit-Signature: 7242b580f77ec488f8ac21b57f092e3db61a431694f13074c7b4c85a4dd04be3
X-Emailit-Timestamp: 1790846045
```

## Header

| Header | Descrizione |
| --- | --- |
| `Content-Type` | Sempre `application/json`. |
| `User-Agent` | Sempre `Emailit-Webhooks/2.0`. |
| `X-Emailit-Signature` | HMAC-SHA256 in esadecimale di `{timestamp}.{raw body}`, calcolato con il secret completo del webhook (compreso `whsec_`). Vedi [Firma delle richieste](/it/docs/webhooks/request-signature/). |
| `X-Emailit-Timestamp` | Ora Unix in secondi in cui Emailit ha firmato la richiesta. Ogni tentativo, compresi i nuovi tentativi, viene firmato di nuovo con un nuovo timestamp. |

## Corpo

Il corpo è sempre un array JSON, anche quando contiene un solo evento. Ogni elemento ha questa forma:

| Campo | Tipo | Descrizione |
| --- | --- | --- |
| `event_id` | string | L’ID dell’evento, che inizia con `evt_`. Lo stesso evento mantiene lo stesso ID tra un tentativo e l’altro. Gli eventi di test iniziano con `evt_test_`. |
| `type` | string | Il [tipo di evento](/it/docs/webhooks/event-types/), come `email.delivered`. |
| `object` | object | La risorsa a cui si riferisce l’evento. |
| `data` | object | Contiene di nuovo `object`. `data.object` e l’`object` di primo livello sono identici: leggi quello che preferisci. |

I campi dentro `object` dipendono dal tipo. Gli eventi di stato delle email descrivono l’email; `email.clicked` e `email.loaded` descrivono il clic o il caricamento e annidano l’email; gli eventi delle risorse, come `contact.created`, descrivono la risorsa.

### Esempio di batch

Questa richiesta contiene due eventi: una consegna e un clic successivo su un link della stessa email.

```json
[
  {
    "event_id": "evt_2xGk7Nq1VbD5sR8tLmW3eYhC6aP",
    "type": "email.delivered",
    "object": {
      "id": "em_2xGk7Lr3XcB8pQ1wYzK4dTfG9hJ",
      "object": "email",
      "from": "billing@acme.com",
      "to": "ada@example.com",
      "subject": "Your receipt #1042",
      "status": "delivered",
      "meta": { "order_id": "1042" },
      "updated_at": "2026-10-01T09:14:03.512000+00:00",
      "created_at": "2026-10-01T09:14:01.207000+00:00"
    },
    "data": {
      "object": {
        "id": "em_2xGk7Lr3XcB8pQ1wYzK4dTfG9hJ",
        "object": "email",
        "from": "billing@acme.com",
        "to": "ada@example.com",
        "subject": "Your receipt #1042",
        "status": "delivered",
        "meta": { "order_id": "1042" },
        "updated_at": "2026-10-01T09:14:03.512000+00:00",
        "created_at": "2026-10-01T09:14:01.207000+00:00"
      }
    }
  },
  {
    "event_id": "evt_2xGkC8w2TnF4yR7bMqL1sVdJ6pE",
    "type": "email.clicked",
    "object": {
      "id": "click_2xGkC7v5PmD3xQ9aLnK2rUcH8oW",
      "object": "click",
      "email_id": "em_2xGk7Lr3XcB8pQ1wYzK4dTfG9hJ",
      "email": {
        "id": "em_2xGk7Lr3XcB8pQ1wYzK4dTfG9hJ",
        "rcpt_to": "ada@example.com",
        "mail_from": "billing@acme.com",
        "subject": "Your receipt #1042",
        "created_at": "2026-10-01T09:14:01.207000+00:00",
        "campaign": null,
        "meta": { "order_id": "1042" }
      },
      "link": {
        "id": "link_2xGk7Mb6QwE1zS8cNpT4vXfK3gB",
        "url": "https://acme.com/orders/1042"
      },
      "contact": { "id": "con_2xFh3Ka9LmP2nR6tVwB8cDqY5sZ", "email": "ada@example.com" },
      "ip_address": "203.0.113.24",
      "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X)",
      "created_at": "2026-10-01T09:20:47.884000+00:00"
    },
    "data": {
      "object": {
        "id": "click_2xGkC7v5PmD3xQ9aLnK2rUcH8oW",
        "object": "click",
        "email_id": "em_2xGk7Lr3XcB8pQ1wYzK4dTfG9hJ",
        "email": {
          "id": "em_2xGk7Lr3XcB8pQ1wYzK4dTfG9hJ",
          "rcpt_to": "ada@example.com",
          "mail_from": "billing@acme.com",
          "subject": "Your receipt #1042",
          "created_at": "2026-10-01T09:14:01.207000+00:00",
          "campaign": null,
          "meta": { "order_id": "1042" }
        },
        "link": {
          "id": "link_2xGk7Mb6QwE1zS8cNpT4vXfK3gB",
          "url": "https://acme.com/orders/1042"
        },
        "contact": { "id": "con_2xFh3Ka9LmP2nR6tVwB8cDqY5sZ", "email": "ada@example.com" },
        "ip_address": "203.0.113.24",
        "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X)",
        "created_at": "2026-10-01T09:20:47.884000+00:00"
      }
    }
  }
]
```

I timestamp sono in formato ISO 8601 in UTC. `meta` contiene i metadati che hai allegato all’invio, oppure `null`. `contact` è `null` quando il destinatario non è uno dei tuoi contatti, e `campaign` è `null` per le email inviate via API e SMTP.

## Ordine

All’interno di una richiesta, gli eventi sono ordinati dal meno recente. Tra richieste diverse l’ordine non è garantito: un batch non riuscito viene ritentato più tardi, quando eventi più recenti potrebbero essere già arrivati, e un nuovo tentativo manuale può reinviare eventi vecchi dopo quelli nuovi.

Non fare affidamento sull’ordine di arrivo. Per gli eventi delle email, usa `status` e `updated_at` dell’email e conserva lo stato più avanzato che hai visto (ad esempio, non sovrascrivere `clicked` con un `delivered` arrivato in ritardo). Nel dubbio, recupera lo stato attuale con [Recupera un’email](/it/docs/api-reference/emails/get/).

## Duplicati

Lo stesso evento può arrivare più di una volta:

- Quando il tuo endpoint va in timeout o restituisce un errore dopo aver elaborato una parte di un batch, viene ritentato l’intero batch, compresi gli eventi che hai già gestito.
- Quando usi **Retry failed** o ritenti una singola richiesta.

Memorizza ogni `event_id` che hai elaborato, con un vincolo di unicità, e salta gli eventi che hai già visto.

## Risposta

| La tua risposta | Risultato |
| --- | --- |
| Qualsiasi `2xx` entro 30 secondi | Ogni evento del batch viene contrassegnato come **Delivered**. Il corpo della risposta viene ignorato. |
| `3xx`, `4xx` o `5xx` | Il batch non è riuscito e viene ritentato. |
| Nessuna risposta entro 30 secondi, errore di connessione, errore TLS | Il batch non è riuscito e viene ritentato. Il pannello mostra il codice di stato `0`. |

Per le richieste non riuscite, Emailit conserva i primi 2000 caratteri del corpo della tua risposta. Puoi leggerli nella scheda **Requests** del webhook, quindi restituire un breve messaggio di errore è utile per il debug.

Consigli:

- **Verifica, poi conferma subito.** Controlla la firma, metti gli eventi in una coda o in una tabella e restituisci `200`. Svolgi il lavoro lento, come chiamare altre API, in un job in background.
- **Restituisci `2xx` per gli eventi che ignori.** Altrimenti vengono ritentati per giorni.
- **Restituisci `401` o `403` per una firma non valida.** Viene ritentata come qualsiasi errore, e questo ti dà il tempo di correggere un secret configurato male.

Vedi [Nuovi tentativi ed errori](/it/docs/webhooks/retries-and-failures/) per il calendario dei nuovi tentativi e per cosa succede quando un endpoint continua a non rispondere correttamente.

## Vedi anche

  - [Verifica le firme dei webhook](/it/docs/webhooks/request-signature/)
  - [Tipi di evento](/it/docs/webhooks/event-types/)

---
Fonte: https://emailit.com/it/docs/webhooks/webhook-requests/
