# Events

> Browse the events Emailit records for your workspace in the dashboard or with the Events API, and use them to backfill or reconcile webhooks.

An event is a record that something happened in your workspace: an email was delivered, a link was clicked, a message arrived on your inbound subdomain, a contact was created. Emailit stores every event, shows them in the dashboard, and builds every [webhook](/docs/webhooks/) request from them. This page explains how to browse events and read them with the API.

## What an event contains

| Field | Description |
| --- | --- |
| `id` | The event ID, starting with `evt_`. In webhook requests it's called `event_id`. |
| `type` | What happened, for example `email.delivered` or `contact.created`. See [Event types](/docs/webhooks/event-types/). |
| `data.object` | The resource the event is about, such as the email, click, domain or contact, as it was when the event happened. |
| `created_at` | When the event was recorded. |

```json
{
  "object": "event",
  "id": "evt_2xGk7Nq1VbD5sR8tLmW3eYhC6aP",
  "type": "email.delivered",
  "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"
    }
  },
  "created_at": "2026-10-01T09:14:03.540000+00:00"
}
```

## Events and webhooks

Events are the source of webhook requests. When Emailit records an event, it queues a request for every enabled webhook that is subscribed to that event type and whose [payload filter](/docs/webhooks/set-up/#filter-events-by-payload) matches. The event is stored whether or not any webhook receives it.

This has two consequences:

- A webhook only receives events that happen while it exists and is enabled. Events recorded while a webhook was disabled, or before it was created, aren't sent to it later.
- You can use the event list to fill gaps. After an outage or a disabled period, read the events for that time window with the API and process the ones your webhook missed. Deduplicate by event ID, which is the same `evt_` ID webhooks use as `event_id`.

## Browse events in the dashboard

Go to **Email API → Events**. The table shows each event's **Event type**, **ID** and **Created** time, newest first.

- By default the page shows the last 2 days. Add a **Created** filter to look further back, within your retention window.
- Filter by **Type** to see one kind of event, for example only `email.bounced`.
- Select an event to see its **Created** time, **Type** and the full **Payload** as JSON, with a copy button.

## Read events with the API

Both endpoints need an API key with **Full Access**.

### List events

[List events](/docs/api-reference/events/list/) returns events newest first.

| Query parameter | Description |
| --- | --- |
| `type` | One type, or several separated by commas, for example `email.bounced,email.complained`. |
| `include_data` | `true` to include `data` for each event. Defaults to `false`, which returns only `id`, `type` and `created_at`. |
| `page`, `limit` | Page number and page size. `limit` is 1 to 100 and defaults to 100. |
| `created_at.after`, `created_at.before` | Date filters. See [Filtering](/docs/api-reference/filtering/). |

```bash
curl -G https://api.emailit.com/v2/events \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  --data-urlencode "type=email.bounced,email.complained" \
  --data-urlencode "created_at.after=2026-09-28T00:00:00Z" \
  --data-urlencode "include_data=true"
```

```json
{
  "data": [
    {
      "object": "event",
      "id": "evt_2xGkB3n8WqZ5cT1vRmK7pLsD4hY",
      "type": "email.bounced",
      "data": { "object": { "id": "em_2xGkA9m1PdX6bR3sQnJ8tKfW2eV", "object": "email", "status": "bounced" } },
      "created_at": "2026-09-30T17:02:41.118000+00:00"
    }
  ],
  "next_page_url": "/v2/events?page=2&limit=100&type=email.bounced%2Cemail.complained&include_data=true",
  "previous_page_url": null
}
```

Two limits keep this endpoint fast:

- **Default window.** Without a `created_at` filter, the list covers the last 2 days. Add `created_at.after` to read older events.
- **Page depth.** The offset, `(page - 1) × limit`, can't be more than 2,500. Deeper pages return `422` with the code `events_offset_too_large`. Narrow the request with `type` or a `created_at` range instead of paging further.

### Retrieve an event

[Retrieve an event](/docs/api-reference/events/get/) returns one event by its `evt_` ID, always with `data`.

```bash
curl https://api.emailit.com/v2/events/evt_2xGk7Nq1VbD5sR8tLmW3eYhC6aP \
  -H "Authorization: Bearer $EMAILIT_API_KEY"
```

## Reconcile missed webhook events

1. **Pick the window.** Note when your endpoint started failing or when the webhook was disabled, and when it was fixed.

2. **List the events.** Call `GET /v2/events` with `created_at.after` and `created_at.before` set to that window, the `type` values your webhook handles, and `include_data=true`. Follow `next_page_url` until it's `null`. If you hit `events_offset_too_large`, split the window into shorter ranges.

3. **Process what you haven't seen.** Skip events whose ID you've already stored as processed, and handle the rest with the same code your webhook uses.

For requests that were queued but failed, [Retry failed](/docs/webhooks/retries-and-failures/#retry-failed-requests) on the webhook is simpler, as long as the failures are less than 7 days old.

## Retention

Events follow the **Logs** retention window, the same as request logs and webhook requests:

| | Pay as you go | Pro | Business | Custom |
| --- | --- | --- | --- | --- |
| Request logs kept | 7 days | 30 days | 30 days | Flexible |

## Related

  - [Event types](/docs/webhooks/event-types/)
  - [Events API](/docs/api-reference/events/)

---
Source: https://emailit.com/docs/logs/events/
