Skip to content
Letterhead Letterhead Letterhead Help Center
Admin Tools

Get a contact's activity

GET
/api/v3/contacts/{email}/activity
curl --request GET \
--url 'https://api.tryletterhead.com/api/v3/contacts/example/activity?api=true' \
--header 'Authorization: Bearer <token>'

Returns one page of a contact’s engagement events across your company’s newsletters — deliveries, opens, clicks, bounces, and purchases — newest first by default. Each entry names the newsletter the event happened on and, for clicks, the URL that was clicked.

Use this when you want the event-by-event history. For the rolled-up counters and rates, use Get a contact’s engagement breakdown. For just the single most recent event timestamp, use Get a contact’s last activity.

This is a company-level (v3) read. Authenticate with a company API key as a Bearer token.

Error responses

A parameter outside its allowed range returns 400. Validation messages are returned in data, not in items.

email
required
string

The contact’s email address.

api
required
boolean

Set to true.

eventType[]
string

Repeatable. Return only these event types. One or more of delivery, open, click, bounce, purchase. Omit to return all five.

search
string

Free-text filter across the event’s newsletter title and link URL. Max 255 characters.

page
integer

1-based page number. Minimum 1. Defaults to 1.

limit
integer

Events per page. Minimum 1, maximum 100. Defaults to 50.

direction
string

Sort order on the event timestamp: desc (newest first, the default) or asc.

channel
string

Narrow the feed to a single newsletter by its channel slug. Omit for every newsletter in the company.

200 OK

Media type application/json
object
items
object
entries
Array<object>
object
type

The event type: delivery, open, click, bounce, or purchase.

string
occurredAt

When the event happened, ISO 8601 in UTC.

string
campaignId

Identifier of the newsletter send the event belongs to. A 10-character alphanumeric string, such as ruf4e0ifs9.

string
letterTitle

Title of the newsletter that produced the event.

string
linkUrl

For click events, the URL that was clicked. Null otherwise.

string
channelName

Display name of the newsletter’s channel. Null for company-level sends, which are not tied to a single channel.

string
channel

Slug of the newsletter’s channel. Null for company-level sends.

string
bounceType

For bounce events, the bounce classification (for example hard, soft, admin, block). Null otherwise.

string
nullable
bounceReason

For bounce events, the human-readable reason, with internal ESP details removed. Null otherwise.

string
nullable
purchaseAmount

For purchase events, the amount. Null otherwise.

string
nullable
purchaseCurrency

For purchase events, the ISO currency code. Null otherwise.

string
nullable
purchaseSource

For purchase events, where the purchase was recorded. Null otherwise.

string
nullable
purchaseProductName

For purchase events, the product purchased. Null otherwise.

string
nullable
isPromotion

True when the event is attributed to a promotion rather than editorial content.

boolean
ipAddress
string
page
integer
limit
integer
message
string
total
integer
Example
{
"items": {
"entries": [
{
"type": "click",
"occurredAt": "2026-08-14T14:22:07+00:00",
"campaignId": "9f1c0925-3f0e-59b5-b26a-62e952f17f57",
"letterTitle": "The Thursday Briefing",
"linkUrl": "https://example.com/city-council-votes-on-transit-plan",
"channelName": "Daily Digest",
"channel": "daily-digest",
"bounceType": null,
"bounceReason": null,
"purchaseAmount": null,
"purchaseCurrency": null,
"purchaseSource": null,
"purchaseProductName": null,
"isPromotion": false,
"ipAddress": "203.0.113.42"
},
{
"type": "open",
"occurredAt": "2026-08-14T14:21:35+00:00",
"campaignId": "9f1c0925-3f0e-59b5-b26a-62e952f17f57",
"letterTitle": "The Thursday Briefing",
"linkUrl": null,
"channelName": "Daily Digest",
"channel": "daily-digest",
"bounceType": null,
"bounceReason": null,
"purchaseAmount": null,
"purchaseCurrency": null,
"purchaseSource": null,
"purchaseProductName": null,
"isPromotion": false,
"ipAddress": "203.0.113.42"
},
{
"type": "delivery",
"occurredAt": "2026-08-14T11:00:04+00:00",
"campaignId": "9f1c0925-3f0e-59b5-b26a-62e952f17f57",
"letterTitle": "The Thursday Briefing",
"linkUrl": null,
"channelName": "Daily Digest",
"channel": "daily-digest",
"bounceType": null,
"bounceReason": null,
"purchaseAmount": null,
"purchaseCurrency": null,
"purchaseSource": null,
"purchaseProductName": null,
"isPromotion": false,
"ipAddress": null
},
{
"type": "bounce",
"occurredAt": "2026-08-07T11:00:11+00:00",
"campaignId": "5d7ca091-9ee8-ca65-3737-c3a7be269f95",
"letterTitle": "The Thursday Briefing",
"linkUrl": null,
"channelName": "Daily Digest",
"channel": "daily-digest",
"bounceType": "soft",
"bounceReason": "Mailbox full",
"purchaseAmount": null,
"purchaseCurrency": null,
"purchaseSource": null,
"purchaseProductName": null,
"isPromotion": false,
"ipAddress": null
}
],
"page": 1,
"limit": 50
},
"message": "Activity retrieved.",
"total": 218
}

400 Validation Error

Media type application/json
object
data
Array<string>
items
Array<object>
object
message
string
total
integer
Example
{
"data": [
"The limit may not be greater than 100."
],
"items": [],
"message": "Looks like the input data doesn't meet our requirements.",
"total": 0
}

Still can’t find what you need? Contact support.