List Contact Events
Retrieve a paginated, reverse-chronological timeline of what happened to a single contact — sends, deliveries, bounces, opens, clicks, list subscribes and unsubscribes, opt-out changes, purchases, and lifecycle events — each resolved to the campaign, automation, or list it relates to.
Rows are returned newest first. The default response is lean and already filtered
to genuine activity; use the type, type_group, from, and to parameters to
narrow it.
Timeline vs. contact summary
This endpoint is the per-event history. It answers "what happened to this contact,
and in what order". For the contact's current state — the headline subscription
status and the aggregated engagement and deliverability summaries (last opened,
last clicked, suppression and bounce state) — use
Get Contact instead. This endpoint does not recompute those
summaries; it lists the individual events beneath them.
Consistent row shape
Every row carries the same keys regardless of its event_type — uuid,
event_type, happened_at, the campaign, automation, and list references,
and a detail object. References are null when they don't apply, and detail is
null for event types with no extra payload. See Detail Object
for the per-type detail shapes.
What the timeline includes
The stream reflects genuine engagement and lifecycle activity. Automatic
list-management link clicks — the one-click unsubscribe link and the
subscription-preferences link in an email footer — are not reported as clicked
events, so a clicked row always represents a real content click.
On a purchased row, the detail records what the contact bought (product
identity), not how much they paid — it carries no amount or currency. For revenue
figures, use List Campaign Recipients with
include=purchases.
Request
GET /contacts/{uuid}/events
Path Parameters
| Parameter | Type | Description |
|---|---|---|
uuid | string | Contact's UUID |
Query Parameters
All parameters are optional.
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (min: 1) |
per_page | integer | 100 | Items per page (min: 1, max: 100) |
type | string | - | Return only events of this exact type. See Event types. |
type_group | string | - | Return only events in this group: delivery, engagement, subscription, commerce, or lifecycle. See Event groups. |
from | string | - | Inclusive lower bound on the event date, YYYY-MM-DD. Returns events on or after this date. |
to | string | - | Inclusive upper bound on the event date, YYYY-MM-DD. Returns events on or before this date. |
Filters are combined with AND. Giving both type and type_group requires the
event to match both — useful only when the type belongs to the group, otherwise the
result is empty.
An invalid type, type_group, from, or to value returns 422 VALIDATION_ERROR. Both from and to must be calendar dates in YYYY-MM-DD
form; a date-time or any other format is rejected.
Event types
type accepts one of:
| Value | Meaning |
|---|---|
sent | A campaign or automation email was sent to the contact. |
delivered | Delivery to the inbox was confirmed. |
bounced | The message bounced. detail holds the bounce classification. |
opened | The contact opened a message. |
clicked | The contact clicked a tracked link. detail holds the clicked link. |
subscribed | The contact was subscribed to a list. Carries a list reference. |
unsubscribed | The contact was unsubscribed from a list. Carries a list reference. |
globally_unsubscribed | The contact opted out of all mail. |
globally_resubscribed | A previous global opt-out was reversed. |
automation_unsubscribed | The contact opted out of an automation. |
purchased | A purchase was attributed to the contact. detail holds the purchased product. |
created | The contact record was created. |
imported | The contact was added through an import. |
Event groups
type_group expands to a set of event types:
| Group | Event types |
|---|---|
delivery | sent, delivered, bounced |
engagement | opened, clicked |
subscription | subscribed, unsubscribed, globally_unsubscribed, globally_resubscribed, automation_unsubscribed |
commerce | purchased |
lifecycle | created, imported |
Example Requests
List a contact's events:
curl -X GET "https://email.easy.tools/api/v1/contacts/7b1f9c2e-3a4d-4b8e-9c1d-2e3f4a5b6c7d/events?page=1&per_page=50" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Show only engagement events (opens and clicks):
curl -X GET "https://email.easy.tools/api/v1/contacts/7b1f9c2e-3a4d-4b8e-9c1d-2e3f4a5b6c7d/events?type_group=engagement" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Restrict to a date range:
curl -X GET "https://email.easy.tools/api/v1/contacts/7b1f9c2e-3a4d-4b8e-9c1d-2e3f4a5b6c7d/events?from=2026-03-01&to=2026-03-31" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Response
Success Response (200 OK)
Each row has the same shape; detail is null unless the event type carries a
type-specific payload. The example below shows a click, a purchase, a bounce, and a
list unsubscribe:
{
"data": [
{
"uuid": "af556d1b-2b71-4df5-8228-fcaaf509db4c",
"event_type": "clicked",
"happened_at": "2026-06-20T09:14:02Z",
"campaign": {
"uuid": "d5a66ae0-e974-4b1b-81ef-4f14c425550a",
"name": "Spring Sale"
},
"automation": null,
"list": null,
"detail": { "url": "https://shop.example/products/42" }
},
{
"uuid": "6732395d-199f-46d3-9f20-01aedc0d4a1b",
"event_type": "purchased",
"happened_at": "2026-06-19T18:41:05Z",
"campaign": {
"uuid": "d5a66ae0-e974-4b1b-81ef-4f14c425550a",
"name": "Spring Sale"
},
"automation": null,
"list": null,
"detail": {
"order_uuid": "2ca53614-fcaf-47df-bf6b-d9ab90be6b04",
"product_uuid": "9354ecda-05bd-4144-bb8f-ba9c59fc8d61",
"product_name": "Pro plan",
"variant_name": "annual",
"is_subscription": true
}
},
{
"uuid": "399e0e2a-10e0-42ea-8f31-364d12d4ec4e",
"event_type": "bounced",
"happened_at": "2026-06-18T07:00:00Z",
"campaign": {
"uuid": "a7b50db9-ada9-4367-86e8-88cb8d9353ac",
"name": "Welcome"
},
"automation": null,
"list": null,
"detail": { "type": "soft" }
},
{
"uuid": "48378307-161e-4c4b-8936-575402894764",
"event_type": "unsubscribed",
"happened_at": "2026-06-10T12:00:00Z",
"campaign": null,
"automation": null,
"list": {
"uuid": "c28f14de-47e6-41bc-8f3d-fb070c1c459c",
"name": "Newsletter"
},
"detail": null
}
],
"pagination": {
"current_page": 1,
"per_page": 100,
"total": 4
}
}
A contact with no matching events returns an empty data array.
Response Fields
| Field | Type | Description |
|---|---|---|
uuid | string | Unique identifier for the event. Stable across pages, so it can be used to de-duplicate while paginating. |
event_type | string | The kind of event. One of the values in Event types. |
happened_at | string | ISO 8601 timestamp (UTC) the event occurred. |
campaign | object|null | The campaign the event relates to, or null. See Reference Object. |
automation | object|null | The automation the event relates to, or null. See Reference Object. |
list | object|null | The list the event relates to (on subscribe and unsubscribe events), or null. See Reference Object. |
detail | object|null | The type-specific payload, or null for event types with no extra detail. Its shape depends on event_type. See Detail Object. |
A row resolves a campaign or an automation for email-related events
(whichever drove the message), and a list for subscribe and unsubscribe events.
Reference Object
The shape used by campaign, automation, and list.
| Field | Type | Description |
|---|---|---|
uuid | string | UUID of the campaign, automation, or list. Use a campaign.uuid with Get Campaign. |
name | string | Its display name. |
Detail Object
detail holds the type-specific payload, and its shape is determined by
event_type. Event types not listed below have detail: null.
clicked — the clicked link
| Field | Type | Description |
|---|---|---|
url | string | The URL the contact clicked. |
bounced — the bounce classification
| Field | Type | Description |
|---|---|---|
type | string | hard for a permanent failure, soft for a transient one. A bounce without an explicit classification is reported as soft. |
purchased — the purchased product
Product identity only — no amount or currency. For revenue, use
List Campaign Recipients with
include=purchases.
| Field | Type | Description |
|---|---|---|
order_uuid | string | UUID of the order the purchase belongs to. |
product_uuid | string | UUID of the purchased product. |
product_name | string | Product name. |
variant_name | string|null | Variant name, or null when the product has no variant. |
is_subscription | boolean | Whether the product is a subscription. |
Pagination Object
| Field | Type | Description |
|---|---|---|
current_page | integer | Current page number |
per_page | integer | Number of items per page |
total | integer | Number of events matching the applied filters |
Error Responses
Not Found Error (404)
Returned when the contact does not exist in your account, or when the uuid is not
a valid UUID.
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Contact not found"
}
}
Validation Error (422 Unprocessable Entity)
Returned for an invalid type, type_group, from, or to value.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid value 'bogus' for filter 'type'",
"details": {
"type": ["Invalid value 'bogus' for filter 'type'"]
}
}
}