> ## Documentation Index
> Fetch the complete documentation index at: https://developers.kit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Delivery format

> The envelope, headers, and HTTP behavior of a webhook delivery

Every delivery is an HTTP `POST` to your endpoint's URL with a JSON body (the "envelope") and a set of headers.

## Envelope

A delivery carries an **array of events**. Most deliveries carry exactly one; when many events of the same type happen at once (a bulk action in the app), Kit batches them into deliveries of up to 100 events each, so your handler should always iterate `events`.

```json theme={null}
{
  "delivery_id": 123456,
  "events": [
    {
      "id": "9c2e1f3a-6b7d-4e8f-a1b2-c3d4e5f60718",
      "type": "subscriber.created",
      "created": "2026-07-29T14:32:10Z",
      "data": {
        "subscriber": {
          "id": 987654,
          "first_name": "Ada",
          "email_address": "ada@example.com",
          "state": "active",
          "created_at": "2026-07-29T14:32:10Z",
          "fields": { "company": "Kit" }
        }
      }
    }
  ]
}
```

| Field         | Type    | Description                                                                        |
| ------------- | ------- | ---------------------------------------------------------------------------------- |
| `delivery_id` | integer | Identifies this POST. A [retry](/webhooks/retries) of a failed delivery reuses it. |
| `events`      | array   | 1 to 100 events, all of the same `type`.                                           |

Each event in `events`:

| Field     | Type          | Description                                                                                                                                                |
| --------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`      | string (UUID) | Unique id of the event. **This is your [deduplication](/webhooks/verifying-signatures#idempotency) key** — it stays the same if the event is ever re-sent. |
| `type`    | string        | The [event type](/webhooks/event-types).                                                                                                                   |
| `created` | string        | ISO 8601 UTC timestamp of when the event occurred (not when it was delivered).                                                                             |
| `data`    | object        | The event payload. Its shape depends on `type` — see [event types](/webhooks/event-types).                                                                 |

<Note>
  A delivery never mixes event types and never carries more than 100 events. Kit also splits a batch once it would pass roughly 512 KB of event payload, so most deliveries stay well under that; a single event larger than 512 KB is still delivered on its own rather than dropped.
</Note>

## Headers

| Header            | Description                                                                                              |
| ----------------- | -------------------------------------------------------------------------------------------------------- |
| `Content-Type`    | Always `application/json`.                                                                               |
| `X-Kit-Delivery`  | The `delivery_id`, matching the body.                                                                    |
| `X-Kit-Signature` | Timestamped HMAC signature of the raw body — see [Verifying signatures](/webhooks/verifying-signatures). |
| `User-Agent`      | `Kit-Webhooks/2.0`.                                                                                      |

## HTTP behavior

* Deliveries are always `POST` requests.
* Respond with any `2xx` status to acknowledge. Kit reads only the status code, not the response body.
* Any non-`2xx` response, a connection failure, or a timeout marks the delivery failed and schedules a [retry](/webhooks/retries). A retry re-POSTs the **entire** `events` array, so process each event idempotently by its `id`.
* Sign or validate against the **raw request body** exactly as received — don't re-serialize the JSON first, or the signature won't match.

<Warning>
  Your endpoint must be a public HTTP(S) URL. Kit blocks delivery to private, internal, or loopback addresses.
</Warning>


## Related topics

- [Webhooks overview](/webhooks/overview.md)
- [OAuth authorization](/plugins/oauth-authorization.md)
- [Retries](/webhooks/retries.md)
- [Verifying signatures](/webhooks/verifying-signatures.md)
- [Changelog](/changelog.md)
