---
title: "The email was opened"
method: POST
path: "email.opened"
tags: ["Webhooks"]
---

# The email was opened

`POST email.opened` (webhook)

Posted to the subscriptions to `email.opened` when the email is opened — the tracking pixel loaded, robots included, like `opened_at`. Signed and retried like every event. The test event (`POST /api/v1/webhooks/{id}/test`) arrives under this `type` too, with `data: { test: true, message }` and none of the fields of the real event: check `data.test` first.

## Headers

- `Mailcheer-Signature` string, required
- `Mailcheer-Timestamp` string, required
- `Mailcheer-Event-Id` string, required
- `Mailcheer-Event-Type` string, required
- `Mailcheer-Delivery-Id` string, required
- `Mailcheer-Attempt` string, required

## Payload

- union
  - EmailEvent: The body of an `email.*` call. A test event carries a different `data`: see `TestEvent`.
    - `id` string, required: `evt_…` — the same on every attempt and every replay of the event: the deduplication key.
    - `type` string, required: `email.sent`, `email.failed`, `email.delivered`, `email.opened`, `email.clicked`, `email.bounced` or `email.complained`.
    - `created_at` string, date-time, required: When the event occurred (not when it was delivered).
    - `test` true: Present, and `true`, on an event produced by a test key (`mch_test_…`): the email was simulated, nothing went out. Absent on a real event. `data` is that of a real event.
    - `data` object, required
      - `message_id` string, required: With `source: api`, the `id` returned by `POST /api/v1/emails`. With `source: campaign`, the `id` of the recipient's row in `GET /api/v1/campaigns/{id}/recipients`.
      - `email` string, required: The address the event concerns. For a campaign email whose contact was deleted after the send, an empty string.
      - `source` 'campaign' | 'api', required: Where the email came from.
      - `campaign_id` string: Campaign emails only: the campaign that sent it.
      - `campaign_name` string: Campaign emails only.
      - `subscriber_id` string: Campaign emails whose contact still exists.
      - `subject` string: The subject of the campaign or of the email, when it has one.
      - `url` string, uri: `email.clicked` only: the link that was clicked.
      - `reason` 'Permanent' | 'Transient' | 'Undetermined' | 'provider_rejected' | 'safety_review' | 'suspended' | 'interrupted': `email.bounced`: the bounce type reported by Amazon SES — `Permanent` (the address does not exist), `Transient`, `Undetermined`. `email.failed`: why the email did not go out — `provider_rejected` (our sending provider refused it), `safety_review` (handed to a human safety review: send the call again after the decision), `suspended` (the workspace was suspended by the review), `interrupted` (a failure before the send).
      - `recipient_type` 'to' | 'cc' | 'bcc': API emails only: `to` if the address was a recipient, `cc` or `bcc` if it was a copy.
  - TestEvent: The body of the test event (`POST /api/v1/webhooks/{id}/test`, or Settings → API). Its `type` is the subscription's first event, but its `data` holds only `test` and `message` — **none of the fields of the real event**. Check `data.test === true` before reading anything else, and answer 2xx without processing it.
    - `id` string, required: `evt_…` — the same on every attempt and every replay of the event: the deduplication key.
    - `type` 'email.sent' | 'email.failed' | 'email.delivered' | 'email.opened' | 'email.clicked' | 'email.bounced' | 'email.complained' | 'email.received' | 'subscriber.created' | 'subscriber.unsubscribed' | 'quota.threshold_reached', required
    - `created_at` string, date-time, required: When the event occurred (not when it was delivered).
    - `data` object, required
      - `test` true, required: Always `true`: this is a test.
      - `message` string, required: A sentence in the language of the request (`Accept-Language`) or of the screen.

## Acknowledgement `2XX`

Any 2xx within 15 seconds acknowledges receipt. Anything else — another status, a redirect (not followed), no answer, a network error — is retried: 5 attempts in all, the next ones 30 s, 2 min, 10 min and 1 h after the previous failure.

---

[API](https://skmtc.dev/mailcheer/apis/mailcheer-api.md) · [All operations](https://skmtc.dev/mailcheer/apis/mailcheer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mailcheer/apis/mailcheer-api/revisions/ba64b7ef2170?raw)
