Skip to main content

Reports API - Contact Activity

Use the contact activity report API retrieve one contact's email history

Written by Marcus Warren

Use the contact activity report to retrieve one contact's email history: which messages they were sent and what they did with each one (delivered, bounced, opened, clicked which links, unsubscribed), with a summary across all of them.


Endpoints

Method

URL

Description

GET

https://e1.envoke.com/v2/reports/contacts/{ID}

Return the activity of the contact with this Envoke contact ID.

GET

https://e1.envoke.com/v2/reports/contacts?email={email}

Return the activity of the contact with this email address.

GET

https://e1.envoke.com/v2/reports/contacts?remote_id={remote_id}

Return the activity of the contact with this remote ID.

Authentication is via HTTP Basic Auth using your API ID and API Key.


Get a Contact's Activity

GET https://e1.envoke.com/v2/reports/contacts/{ID}

Returns one JSON object with three parts: contact (who), summary (counts across every message), and messages (one entry per message, newest first, paged with limit and skip). Replace {ID} with the Envoke contact ID, the id of the Contact API.

A contact that does not exist, belongs to another account, or has been deleted returns [] with HTTP 200. A contact who has never been sent a message returns the object with every count 0, every time null, and messages [].

This report covers email messages only: form submissions and other contact events are not included.

Accounts restricted from contact-level email activity. On an account restricted from seeing contacts associated with email activity (the setting that hides a contact's Email sending history in Envoke), this endpoint and Find a Contact's Activity return HTTP 403; see Errors. The message reports are not affected.

Query Parameters

Parameter

Type

Default

Description

activity_from

string

—

Count only activity on or after this date or time. See Date parameters.

activity_to

string

—

Count only activity on or before this date or time.

limit

integer

10

Maximum number of entries in messages; values above 100 return 100.

skip

integer

0

Number of messages entries to skip.

limit and skip apply only to the messages array; contact and summary are always complete. Any other parameter, including sent_from and sent_to, returns HTTP 400 (Parameter 'sent_from' is not valid).


Find a Contact's Activity by Email or Remote ID

GET https://e1.envoke.com/v2/reports/contacts?email={email} GET https://e1.envoke.com/v2/reports/contacts?remote_id={remote_id}

Returns the same object as Get a Contact's Activity for the contact found by email or by remote_id. Give exactly one of the two, plus any of activity_from, activity_to, limit, and skip. URL-encode the value (@ is %40).

The value is compared as a whole, exactly as the Contact API's filter[email] and filter[remote_id] compare it, so a value the Contact API finds is found here. Letter case does not matter: MAYA.CHEN@EXAMPLE.ORG finds the contact maya.chen@example.org, and a remote ID is matched the same way. An empty value is an error rather than a match for every contact without an email address or remote ID. When no contact matches, the response is [] with HTTP 200. When more than one contact matches, the request fails with HTTP 400 rather than choosing one; use the contact's id instead. More than one match is possible for remote_id, and for email on accounts that allow several contacts to share an address.


Response

contact

Field

Type

Description

id

string

Envoke contact ID.

email

string

The contact's email address.

remote_id

string

The contact's remote ID, or "" when it has none.

summary

Counts of messages, across every message in the report (not only the current page of messages), inside the activity window when one is given:

Field

Type

Description

sends

integer

Messages the contact was sent.

delivered

integer

Messages with delivered true.

bounces

integer

Messages with bounced true.

opens

integer

Messages with opened true.

clicks

integer

Messages with clicked true.

unsubscribes

integer

Messages with unsubscribed true.

last_send_time

string or null

The most recent time the contact was sent a message.

last_open_time

string or null

The most recent open record.

last_click_time

string or null

The most recent click record.

Envoke records a contact's first open of a message in each email client and their first click on each link, never a repeat (see Times and time zone). So last_open_time is the latest of those first opens: a contact who reopens an old message in the same email client does not move it, but opening a new message, or the same message in another client, does. last_click_time works the same way for links.

messages

One entry per message the contact was sent, ordered by sent_time, newest first, then by message id, highest first. A message is included when the contact has a send record for it and, when an activity window is given, at least one activity record for it inside the window. Messages the contact was selected for but skipped (no consent, invalid address) are not included. A message is listed whatever its status today, as on the contact page: a transactional message, or a message sent and later returned to draft, appears here even though the message reports do not answer for it.

Field

Type

Description

id

string

Message ID; the Message API id.

name

string

The message's internal name.

sent_time

string

When this contact was sent the message. For an automated message, the time of this contact's send, not the message's set-up date.

delivered

boolean

true when the contact was sent the message and has no bounce record for it. With an activity window, the send must be inside the window; a bounce counts whenever it arrived.

bounced

boolean

true when the contact has any bounce record for the message, including a temporary deferral.

opened

boolean

true when the contact opened the message.

first_open_time

string or null

The contact's first open of the message, or null.

opens

integer

The number of email clients the contact opened the message in; not the number of times they opened it.

clicked

boolean

true when the contact clicked any tracked link in the message.

clicks

integer

The number of different links the contact clicked; not the number of clicks.

links

array

{ "id", "url", "first_click_time" } for each link the contact clicked, most recent first.

unsubscribed

boolean

true when the contact revoked consent or used one-click unsubscribe from the message (the events counted in unsubscribes).

In links, id is the tracked link's ID (the same as in the single-message report's links) and url is the link as written in the message with Envoke's tracking parameters removed, or "" for Envoke's own links (view online, preferences, poll answers). Merge tags in a link are not replaced, so url can be or contain a merge tag ({@customfield-url_test}, https://example.org/show?seat={@seat|url}) rather than a valid URL. first_click_time is the contact's first click on that link. For a message with an anonymous poll, poll-answer clicks are left out entirely, as in the Sent message report's drill-downs: they are not listed in links, not counted in clicks, clicked, or the summary (clicks and last_click_time), and do not by themselves place the message inside an activity window.

Activity window. With activity_from or activity_to, every flag and count reflects only the records inside the window, except sent_time, which is always the contact's send. A contact sent the message before the window who opened it inside the window shows opened true and delivered false, because the send is outside the window. delivered follows the message-level delivered: with a window it needs a send inside the window and no bounce for the message at any time.

Relation to the contact page. Each entry matches the row for the same message in the contact's Email sending history in Envoke (https://e1.envoke.com/contacts/{id}/delivery-history.json, .campaigns[] | {campaign_id, flags}): bounced, opened, and clicked equal its bounce, open, and click flags, except that on a message with an anonymous poll a contact whose only clicks were poll answers has clicked false where the page shows a click. A message the page lists from opens or clicks alone, with no send record for the contact, is not in this report. The app and this report both show times in your account's time zone.

Response

{   "contact": {     "id": "1004",     "email": "maya.chen@example.org",     "remote_id": "MRCT-0412"   },   "summary": {     "sends": 3,     "delivered": 3,     "bounces": 0,     "opens": 2,     "clicks": 1,     "unsubscribes": 0,     "last_send_time": "2026-05-14 09:31:07",     "last_open_time": "2026-05-14 12:02:44",     "last_click_time": "2026-05-14 12:03:10"   },   "messages": [     {       "id": "2004",       "name": "Pirates Opening Night",       "sent_time": "2026-05-14 09:31:07",       "delivered": true,       "bounced": false,       "opened": true,       "first_open_time": "2026-05-14 12:02:44",       "opens": 1,       "clicked": true,       "clicks": 1,       "links": [         { "id": "88125", "url": "https://example.org/tickets/pirates", "first_click_time": "2026-05-14 12:03:10" }       ],       "unsubscribed": false     },     {       "id": "2001",       "name": "Spring Season Announcement",       "sent_time": "2026-04-15 10:00:52",       "delivered": true,       "bounced": false,       "opened": true,       "first_open_time": "2026-04-15 10:04:19",       "opens": 2,       "clicked": false,       "clicks": 0,       "links": [],       "unsubscribed": false     },     {       "id": "2006",       "name": "Welcome to Maple Ridge",       "sent_time": "2025-11-03 08:00:12",       "delivered": true,       "bounced": false,       "opened": false,       "first_open_time": null,       "opens": 0,       "clicked": false,       "clicks": 0,       "links": [],       "unsubscribed": false     }   ] }

Errors

Invalid requests return HTTP 400 with the validation envelope (see Error Responses). Besides the shared date, limit, skip, and unknown-parameter errors:

Error

Cause

One of the parameters 'email' or 'remote_id' must be provided

GET /v2/reports/contacts without either.

Only one of the parameters 'email' or 'remote_id' may be provided

Both were given.

Invalid 'email': ''

email (or remote_id: Invalid 'remote_id': '') was given with an empty value.

More than one contact found for 'remote_id': 'MRCT-0412'

Several contacts have this remote ID (or, with email, this address: More than one contact found for 'email': 'maya.chen@example.org').

Parameter 'email' is not valid

email or remote_id given on GET /v2/reports/contacts/{ID}, where the path already names the contact.

Response

Cause

[] with HTTP 200

The contact does not exist, belongs to another account, or is deleted; or no contact has this email or remote_id.

HTTP 404, 404 Not Found

{ID} is not a number.

HTTP 403, Contact-level email activity is not available on this account

The account is restricted from seeing contacts associated with email activity. Returned by both contact activity endpoints.

The 403 body:

{   "success": false,   "result_text": "Contact-level email activity is not available on this account",   "result_data": [] }

Examples

One contact's activity, ten most recent messages

curl -X GET -gs -u "$API_ID:$API_KEY" \   "https://e1.envoke.com/v2/reports/contacts/1004"

By email address

curl -X GET -gs -u "$API_ID:$API_KEY" \   "https://e1.envoke.com/v2/reports/contacts?email=maya.chen%40example.org"

By remote ID, activity in May

curl -X GET -gs -u "$API_ID:$API_KEY" \   "https://e1.envoke.com/v2/reports/contacts?remote_id=MRCT-0412&activity_from=2026-05-01&activity_to=2026-05-31"

Response (only 2004 had activity for this contact in May):

{   "contact": {     "id": "1004",     "email": "maya.chen@example.org",     "remote_id": "MRCT-0412"   },   "summary": {     "sends": 1,     "delivered": 1,     "bounces": 0,     "opens": 1,     "clicks": 1,     "unsubscribes": 0,     "last_send_time": "2026-05-14 09:31:07",     "last_open_time": "2026-05-14 12:02:44",     "last_click_time": "2026-05-14 12:03:10"   },   "messages": [     {       "id": "2004",       "name": "Pirates Opening Night",       "sent_time": "2026-05-14 09:31:07",       "delivered": true,       "bounced": false,       "opened": true,       "first_open_time": "2026-05-14 12:02:44",       "opens": 1,       "clicked": true,       "clicks": 1,       "links": [         { "id": "88125", "url": "https://example.org/tickets/pirates", "first_click_time": "2026-05-14 12:03:10" }       ],       "unsubscribed": false     }   ] }

A contact with a bounce

curl -X GET -gs -u "$API_ID:$API_KEY" \   "https://e1.envoke.com/v2/reports/contacts/1007?limit=1"

Response:

{   "contact": {     "id": "1007",     "email": "r.osei@example.org",     "remote_id": ""   },   "summary": {     "sends": 2,     "delivered": 1,     "bounces": 1,     "opens": 1,     "clicks": 0,     "unsubscribes": 0,     "last_send_time": "2026-03-10 18:00:41",     "last_open_time": "2025-09-02 08:47:15",     "last_click_time": null   },   "messages": [     {       "id": "2002",       "name": "Auditions Open",       "sent_time": "2026-03-10 18:00:41",       "delivered": false,       "bounced": true,       "opened": false,       "first_open_time": null,       "opens": 0,       "clicked": false,       "clicks": 0,       "links": [],       "unsubscribed": false     }   ] }

summary covers both messages; limit=1 returns only the newest in messages.


Note: The curl examples above are formatted for readability. All requests must use properly encoded URLs.

For code examples and interactive testing, visit api.envoke.com.

Did this answer your question?