Skip to main content

List Campaign Recipients

Retrieve a paginated list of a campaign's recipients — the people the campaign was actually sent to — with each recipient's send status and, on request, their delivery outcome, engagement, and purchases.

This is the per-recipient counterpart to the campaign-wide totals returned by Get Campaign with ?include=stats,revenue. Each row is one recipient, and the default response is lean: contact identity and send status only. Request the delivery, engagement, and purchases sections through the include parameter to add per-recipient detail.

Recipients vs. live audience

This endpoint returns the historical sent set: who the campaign was already sent to, and what happened to each of them. It is fixed once a campaign has been sent, and returns an empty list for a campaign that has not been sent yet.

That is different from List Campaign Contacts, which resolves a campaign's audience live and answers who a send right now would target. That list keeps changing as contacts are added, removed, unsubscribe, or become undeliverable; this one records who was mailed and never re-evaluates.

Send status is not inbox delivery

status reflects the send attempt, not inbox delivery. sent means the message was accepted for delivery — it does not confirm the message reached the inbox. Confirmed delivery is reported by delivery.delivered, available when you request include=delivery.

Request

GET /campaigns/{uuid}/recipients

Path Parameters

ParameterTypeDescription
uuidstringCampaign's UUID

Query Parameters

All parameters are optional.

ParameterTypeDefaultDescription
pageinteger1Page number (min: 1)
per_pageinteger100Items per page (min: 1, max: 100)
statusstring-Filter by send status: pending, sent, or failed.
searchstring-Partial, case-insensitive match on the recipient's name or email address.
openedboolean-true returns only recipients who opened the email; false only those who didn't. Omit to include all.
clickedboolean-true returns only recipients who clicked a tracked link; false only those who didn't. Omit to include all.
purchasedboolean-true returns only recipients with an attributed purchase; false only those without. Omit to include all.
linkstring-A tracked link's UUID. Returns only recipients who clicked that link. Get valid link UUIDs from List Campaign Link Clicks. A UUID that is not one of the campaign's tracked links returns 422 VALIDATION_ERROR.
includestring-Comma-separated list of extra per-recipient sections to add to each row: delivery, engagement, purchases (include=delivery,engagement,purchases). Unrecognised values are ignored.

Each section you name in include is added as an extra key on every row. A section you don't request is omitted entirely — it is not returned as null — so the default response stays lean. See Delivery Object, Engagement Object, and Purchases Object.

An invalid status, opened, clicked, purchased, or link value — including a link UUID that does not belong to the campaign — returns 422 VALIDATION_ERROR.

Example Requests

List a campaign's recipients:

curl -X GET "https://email.easy.tools/api/v1/campaigns/550e8400-e29b-41d4-a716-446655440000/recipients?page=1&per_page=50" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"

Add per-recipient delivery, engagement, and purchases:

curl -X GET "https://email.easy.tools/api/v1/campaigns/550e8400-e29b-41d4-a716-446655440000/recipients?include=delivery,engagement,purchases" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"

Find only the recipients who clicked a specific tracked link:

curl -X GET "https://email.easy.tools/api/v1/campaigns/550e8400-e29b-41d4-a716-446655440000/recipients?link=b25cdf8d-47d3-4d30-b097-e83a05577e8e" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"

Response

Success Response (200 OK)

The default response carries identity and send status only:

{
"data": [
{
"contact_uuid": "6b505897-43c7-4e27-925d-dd67a6f0a80b",
"email": "john@example.com",
"first_name": "John",
"last_name": "Doe",
"status": "sent",
"sent_at": "2026-06-08T05:56:49Z",
"failed_at": null,
"created_at": "2026-06-08T05:56:49Z"
},
{
"contact_uuid": "e294fbd1-726c-4c98-afd8-d8e6908bcda7",
"email": "jane@example.com",
"first_name": "Jane",
"last_name": "Smith",
"status": "failed",
"sent_at": null,
"failed_at": "2026-06-08T05:56:51Z",
"created_at": "2026-06-08T05:56:49Z"
}
],
"pagination": {
"current_page": 1,
"per_page": 100,
"total": 2
}
}

A campaign with no recipients yet — for example one that has not been sent — returns an empty data array.

Including delivery and engagement

With include=delivery,engagement, each row gains a delivery and an engagement section:

{
"data": [
{
"contact_uuid": "e294fbd1-726c-4c98-afd8-d8e6908bcda7",
"email": "jane@example.com",
"first_name": "Jane",
"last_name": "Smith",
"status": "sent",
"sent_at": "2025-11-11T13:12:14Z",
"failed_at": null,
"created_at": "2025-11-11T13:12:14Z",
"delivery": {
"delivered": true,
"delivered_at": "2025-11-11T12:12:24Z",
"bounced": true,
"bounce_type": "soft",
"bounced_at": "2025-11-16T12:12:14Z",
"complained": true,
"complained_at": "2025-11-17T12:12:14Z"
},
"engagement": {
"opened": true,
"opened_at": "2025-11-11T14:12:14Z",
"open_count": 3,
"clicked": true,
"clicked_at": "2025-11-11T14:17:14Z",
"click_count": 2
}
}
],
"pagination": {
"current_page": 1,
"per_page": 100,
"total": 2
}
}

Including purchases

With include=purchases, each row gains a purchases section. revenue is the per-currency total attributed to that recipient, and items are the individual line items behind it:

{
"data": [
{
"contact_uuid": "6b505897-43c7-4e27-925d-dd67a6f0a80b",
"email": "john@example.com",
"first_name": "John",
"last_name": "Doe",
"status": "sent",
"sent_at": "2026-03-05T07:54:44Z",
"failed_at": null,
"created_at": "2026-03-05T07:54:44Z",
"purchases": {
"purchased": true,
"purchase_count": 2,
"revenue": [
{ "amount": 7032, "currency": "pln" }
],
"items": [
{
"order_uuid": "b86dad58-87da-420c-a6ec-38d2bc4c099b",
"product_uuid": "9354ecda-05bd-4144-bb8f-ba9c59fc8d61",
"product_name": "Pro plan",
"variant_name": null,
"is_subscription": false,
"amount": 3900,
"currency": "pln",
"purchased_at": "2026-03-05T07:10:41Z"
},
{
"order_uuid": "b86dad58-87da-420c-a6ec-38d2bc4c099b",
"product_uuid": "c2b1841a-73e6-4148-9784-28551af632b8",
"product_name": "Add-on",
"variant_name": "annual",
"is_subscription": false,
"amount": 3132,
"currency": "pln",
"purchased_at": "2026-03-05T07:10:41Z"
}
]
}
}
],
"pagination": {
"current_page": 1,
"per_page": 100,
"total": 2
}
}

Response Fields

Every row carries these fields. The delivery, engagement, and purchases keys are present only when named in include.

FieldTypeDescription
contact_uuidstringThe recipient contact's unique identifier
emailstringThe contact's current email address. May differ from the address originally mailed if the contact changed it after the send.
first_namestring|nullRecipient's first name. null when not set.
last_namestring|nullRecipient's last name. null when not set.
statusstringSend status: pending, sent, or failed. See Send status is not inbox delivery.
sent_atstring|nullISO 8601 timestamp (UTC) the message was sent. null until sent.
failed_atstring|nullISO 8601 timestamp (UTC) the send failed. null unless status is failed.
created_atstringISO 8601 timestamp (UTC) the recipient record was created.
deliveryobjectDelivery outcome. Only present when delivery is named in include. See Delivery Object.
engagementobjectOpens and clicks. Only present when engagement is named in include. See Engagement Object.
purchasesobjectAttributed purchases. Only present when purchases is named in include. See Purchases Object.

Delivery Object

Present only when delivery is named in include.

FieldTypeDescription
deliveredbooleanWhether delivery to the inbox was confirmed.
delivered_atstring|nullISO 8601 timestamp (UTC) of confirmed delivery. null when not delivered.
bouncedbooleanWhether the message bounced.
bounce_typestring|nullhard, soft, or null when the message did not bounce.
bounced_atstring|nullISO 8601 timestamp (UTC) of the bounce. null when the message did not bounce.
complainedbooleanWhether the recipient marked the message as spam.
complained_atstring|nullISO 8601 timestamp (UTC) of the complaint. null when there was none.

Engagement Object

Present only when engagement is named in include.

FieldTypeDescription
openedbooleanWhether the recipient opened the email.
opened_atstring|nullISO 8601 timestamp (UTC) of the first open. null when never opened.
open_countintegerTotal number of opens.
clickedbooleanWhether the recipient clicked any tracked link.
clicked_atstring|nullISO 8601 timestamp (UTC) of the first click. null when never clicked.
click_countintegerTotal number of link clicks.

Purchases Object

Present only when purchases is named in include.

FieldTypeDescription
purchasedbooleanWhether any purchase is attributed to the recipient.
purchase_countintegerTotal number of attributed purchases.
revenuearrayAttributed revenue, one entry per currency. Empty array [] when there is none. See Revenue entry.
itemsarrayThe purchased line items, one entry per product per order. Empty array [] when there is none. See Purchase item.
Revenue entry
FieldTypeDescription
amountintegerRevenue in the currency's minor units (for example cents or grosze). Divide by 100 for the major-unit value.
currencystringLowercase ISO 4217 currency code, e.g. "usd" or "pln".
Purchase item
FieldTypeDescription
order_uuidstringUUID of the order the item belongs to. Repeats across items from the same multi-product order — group by it to reconstruct orders.
product_uuidstringUUID of the purchased product.
product_namestringProduct name.
variant_namestring|nullVariant name, or null when the product has no variant.
is_subscriptionbooleanWhether the product is a subscription.
amountintegerItem price in the currency's minor units. Divide by 100 for the major-unit value.
currencystringLowercase ISO 4217 currency code, e.g. "usd" or "pln".
purchased_atstringISO 8601 timestamp (UTC) of the purchase.

Pagination Object

FieldTypeDescription
current_pageintegerCurrent page number
per_pageintegerNumber of items per page
totalintegerNumber of recipient rows matching the applied filters

Unfiltered, total counts every send attempt — including pending and failed ones — so it can be larger than the campaign's sent count and will not equal stats.sends. For campaign-wide totals such as sends, opens, clicks, and rates, use Get Campaign with ?include=stats,revenue.

Error Responses

Not Found Error (404)

{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Campaign with UUID '550e8400-e29b-41d4-a716-446655440000' not found"
}
}

Validation Error (422 Unprocessable Entity)

{
"error": {
"code": "VALIDATION_ERROR",
"message": "The given data was invalid",
"details": {
"status": ["The selected status is invalid."]
}
}
}