# Požadavky webhooků

> Přesný formát požadavků webhooků Emailitu, od metody a hlaviček po pole JSON s událostmi, a k tomu pořadí, duplicity a jak na požadavky odpovídat.

Tato stránka popisuje, co dorazí na váš endpoint: HTTP požadavek, jeho hlavičky, tělo ve formátu JSON a co Emailit očekává zpět. Použijte ji při psaní nebo ladění handleru webhooků.

## Požadavek

| Vlastnost | Hodnota |
| --- | --- |
| Metoda | `POST` |
| Tělo | Pole JSON s 1 až 100 událostmi v kompaktním zápisu (bez nadbytečných mezer) |
| Časový limit | 30 sekund |
| Přesměrování | Nesledují se. Odpověď `3xx` se počítá jako selhání. |
| Souběh | Pro každý webhook jeden požadavek najednou. Dávky se posílají jedna po druhé. |
| Zpoždění | Emailit kontroluje nové události každých několik sekund, takže většina událostí dorazí během několika sekund. |

```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
```

## Hlavičky

| Hlavička | Popis |
| --- | --- |
| `Content-Type` | Vždy `application/json`. |
| `User-Agent` | Vždy `Emailit-Webhooks/2.0`. |
| `X-Emailit-Signature` | Hexadecimálně zakódovaný HMAC-SHA256 z `{timestamp}.{raw body}` s celým tajným klíčem webhooku (včetně `whsec_`) jako klíčem. Viz [Ověření podpisu webhooků](/cs/docs/webhooks/request-signature/). |
| `X-Emailit-Timestamp` | Unixový čas v sekundách, kdy Emailit požadavek podepsal. Každý pokus, včetně opakování, se podepíše znovu s novým časovým razítkem. |

## Tělo

Tělo je vždy pole JSON, i když obsahuje jedinou událost. Každý prvek má tento tvar:

| Pole | Typ | Popis |
| --- | --- | --- |
| `event_id` | string | ID události, začíná na `evt_`. Stejná událost si při opakování ponechá stejné ID. Testovací události začínají na `evt_test_`. |
| `type` | string | [Typ události](/cs/docs/webhooks/event-types/), například `email.delivered`. |
| `object` | object | Zdroj, kterého se událost týká. |
| `data` | object | Obsahuje znovu `object`. `data.object` a `object` na nejvyšší úrovni jsou totožné; čtěte ten, který vám vyhovuje. |

Pole uvnitř `object` závisí na typu. Události stavů e-mailu popisují e-mail; `email.clicked` a `email.loaded` popisují proklik nebo načtení a e-mail obsahují jako vnořený objekt; události zdrojů, například `contact.created`, popisují daný zdroj.

### Ukázková dávka

Tento požadavek obsahuje dvě události: doručení a pozdější proklik odkazu ve stejném e-mailu.

```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"
      }
    }
  }
]
```

Časová razítka jsou ve formátu ISO 8601 v UTC. `meta` jsou metadata, která jste připojili při odeslání, nebo `null`. `contact` je `null`, když příjemce není mezi vašimi kontakty, a `campaign` je `null` u pošty odeslané přes API a SMTP.

## Pořadí

V rámci jednoho požadavku jsou události seřazené od nejstarších. Mezi požadavky pořadí zaručené není: neúspěšná dávka se zopakuje později, kdy už mohly dorazit novější události, a ruční opakování může poslat staré události až po nových.

Nespoléhejte na pořadí, v jakém události dorazí. U událostí e-mailů použijte `status` a `updated_at` e-mailu a ponechte si nejpokročilejší stav, který jste viděli (například nepřepisujte `clicked` opožděným `delivered`). V případě pochybností načtěte aktuální stav přes [Načtení e-mailu](/cs/docs/api-reference/emails/get/).

## Duplicity

Stejná událost může dorazit víckrát:

- Když váš endpoint po zpracování části dávky nestihne odpovědět včas nebo vrátí chybu, zopakuje se celá dávka, včetně událostí, které jste už zpracovali.
- Když použijete **Retry failed** nebo zopakujete jeden požadavek.

Každé zpracované `event_id` si uložte s omezením na jedinečnost a události, které jste už viděli, přeskakujte.

## Odpověď na požadavek

| Vaše odpověď | Výsledek |
| --- | --- |
| Jakýkoli `2xx` do 30 sekund | Všechny události v dávce se označí jako **Delivered**. Tělo odpovědi se ignoruje. |
| `3xx`, `4xx` nebo `5xx` | Dávka selhala a zopakuje se. |
| Žádná odpověď do 30 sekund, chyba spojení, chyba TLS | Dávka selhala a zopakuje se. Webové rozhraní ukáže stavový kód `0`. |

U neúspěšných požadavků Emailit uloží prvních 2 000 znaků těla vaší odpovědi. Najdete je na kartě **Requests** u webhooku, takže se vyplatí vracet krátkou chybovou zprávu, která pomůže s laděním.

Doporučení:

- **Ověřte a rychle potvrďte.** Zkontrolujte podpis, zařaďte události do fronty nebo je uložte do tabulky a vraťte `200`. Pomalou práci, například volání jiných API, dělejte v úloze na pozadí.
- **Pro události, které ignorujete, vracejte `2xx`.** Jinak se budou několik dní opakovat.
- **Při špatném podpisu vracejte `401`, nebo `403`.** Požadavek se zopakuje jako při každém jiném selhání, takže máte čas opravit špatně nastavený tajný klíč.

Plán opakování a co se stane, když endpoint opakovaně selhává, popisuje stránka [Opakování a selhání](/cs/docs/webhooks/retries-and-failures/).

## Související

  - [Ověření podpisu webhooků](/cs/docs/webhooks/request-signature/)
  - [Typy událostí](/cs/docs/webhooks/event-types/)

---
Zdroj: https://emailit.com/cs/docs/webhooks/webhook-requests/
