Email Blasts
Read blast-level engagement analytics — summary tiles, top-blast rankings, per-blast performance, activity timeseries, and per-recipient engagement.
email-blasts:read covers every endpoint on this page. For per-recipient send data across every email (not just blasts), see Buyer Signals.
Endpoints on this page
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1alpha1/email-blasts/summary | Aggregate tile stats across a period. Details ↓ |
GET | /api/v1alpha1/email-blasts/top | Top-performing blasts ranked by engagement. Details ↓ |
GET | /api/v1alpha1/email-blasts | Table of blasts sent in the period. Details ↓ |
GET | /api/v1alpha1/email-blasts/{blastId} | Summary + performance for one blast. Details ↓ |
GET | /api/v1alpha1/email-blasts/{blastId}/activity | Daily activity timeseries for one blast. Details ↓ |
GET | /api/v1alpha1/email-blasts/{blastId}/recipients | Per-recipient engagement rows for one blast. Details ↓ |
Get summary tiles
GET /api/v1alpha1/email-blasts/summary
Dashboard-tile aggregates across the requested period. One object, no pagination.
Query parameters
| Parameter | Type | Description |
|---|---|---|
periodDays | number | 7, 14, or 30. Default 7. |
ownerUserId | string | (optional) usr_... id — restrict to blasts owned by one user. |
Response
totalSuccessfulSentexcludes bounces and pre-send failures. Percentages are computed againsttotalSuccessfulSent, nottotalRecipients.
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/summary?periodDays=30" \
-H "X-Cirrus-Api-Key: $TOKEN"import requests
response = requests.get(
"https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/summary",
headers={"X-Cirrus-Api-Key": token},
params={"periodDays": 30},
)
response.raise_for_status()
summary = response.json()using System.Net.Http;
using System.Web;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);
var query = HttpUtility.ParseQueryString(string.Empty);
query["periodDays"] = "30";
var uri = new UriBuilder("https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/summary")
{
Query = query.ToString()
}.Uri;
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var summary = await response.Content.ReadAsStringAsync();{
"periodDays": 30,
"totalBlasts": 12,
"totalRecipients": 4820,
"totalSuccessfulSent": 4778,
"totalOpens": 2310,
"totalClicks": 442,
"totalReplies": 118,
"openPercentage": 48.3,
"clickPercentage": 9.2,
"replyPercentage": 2.5
}Get top blasts
GET /api/v1alpha1/email-blasts/top
Blasts ranked by engagement (rankingScore) across the period. The dashboard uses this to power its "top-performing blasts" carousel.
Query parameters
| Parameter | Type | Description |
|---|---|---|
periodDays | number | 7, 14, or 30. Default 7. |
ownerUserId | string | (optional) usr_... id. |
limit | number | Clamped 1–20, default 5. |
Response
unique*counts are per-recipient — a recipient who opens three times contributes 1 touniqueOpens. Rates are computed offsuccessfulSentCount.rankingScoreis a blended engagement metric (weighted mix ofopenRate,clickRate,replyRate) that Cirrus uses to sort. Not documented as a formula because the weighting can change; consume it as an opaque relative ranking.
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/top?periodDays=30&limit=5" \
-H "X-Cirrus-Api-Key: $TOKEN"import requests
response = requests.get(
"https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/top",
headers={"X-Cirrus-Api-Key": token},
params={"periodDays": 30, "limit": 5},
)
response.raise_for_status()
top = response.json()using System.Net.Http;
using System.Web;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);
var query = HttpUtility.ParseQueryString(string.Empty);
query["periodDays"] = "30";
query["limit"] = "5";
var uri = new UriBuilder("https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/top")
{
Query = query.ToString()
}.Uri;
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var top = await response.Content.ReadAsStringAsync();{
"items": [
{
"blastId": "blast_...",
"blastName": "Q3 product update — pipeline forecasting",
"recipientCount": 482,
"successfulSentCount": 478,
"uniqueOpens": 231,
"uniqueClicks": 44,
"uniqueReplies": 12,
"openRate": 48.3,
"clickRate": 9.2,
"replyRate": 2.5,
"rankingScore": 78.4
}
]
}List email blasts
GET /api/v1alpha1/email-blasts
Table of blasts sent in the period, one row per blast. This is the primary browse endpoint — supports search, sort, and paging.
Query parameters
| Parameter | Type | Description |
|---|---|---|
cursor | string | Standard keyset cursor. |
limit | number | Clamped 1–100, default 25. |
sort | string | sentAt, openRate, clickRate, replyRate, engagementScore, recipientCount. Prefix - for descending. Default -sentAt. |
periodDays | number | 7, 14, or 30. Default 7. |
ownerUserId | string | (optional) usr_... id. |
search | string | (optional) Substring match on blast name or template name. Case-insensitive. |
Response
See the EmailBlastmodel for the full field reference.
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/email-blasts?periodDays=30&limit=25" \
-H "X-Cirrus-Api-Key: $TOKEN"import requests
response = requests.get(
"https://altus.cirrusinsight.com/api/v1alpha1/email-blasts",
headers={"X-Cirrus-Api-Key": token},
params={"periodDays": 30, "limit": 25},
)
response.raise_for_status()
page = response.json()using System.Net.Http;
using System.Web;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);
var query = HttpUtility.ParseQueryString(string.Empty);
query["periodDays"] = "30";
query["limit"] = "25";
var uri = new UriBuilder("https://altus.cirrusinsight.com/api/v1alpha1/email-blasts")
{
Query = query.ToString()
}.Uri;
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var page = await response.Content.ReadAsStringAsync();{
"items": [
{
"blastId": "blast_...",
"blastName": "Q3 product update — pipeline forecasting",
"templateName": "Product Update — Q3",
"sentAt": "2026-07-14T13:00:12Z",
"sender": {
"userId": "usr_...",
"displayName": "Alex Rivera"
},
"recipientCount": 482,
"openRate": 48.3,
"clickRate": 9.2,
"replyRate": 2.5,
"engagementScore": 78.4
}
],
"nextCursor": null
}Get an email blast
GET /api/v1alpha1/email-blasts/{blastId}
One blast's summary + performance snapshot. Two nested objects: summary (identity — name, template, sender, status, recipient count) and performance (engagement rates + raw counts).
Response
statusis one of:Draft,Assigned,Scheduled,SendNow,Rejected,Processing,Queued,Sending,Success,PartialSuccess,Failure,Sent,PastDue. Most integrations only care aboutSendingandSent.successfulSentCountsubtracts pre-send failures and hard bounces fromrecipientCount. Rates onperformanceare computed offsuccessfulSentCount.
Errors
404 email-blast-not-found— no blast with that id in your org.
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/blast_..." \
-H "X-Cirrus-Api-Key: $TOKEN"import requests
response = requests.get(
f"https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/{blast_id}",
headers={"X-Cirrus-Api-Key": token},
)
response.raise_for_status()
blast = response.json()using System.Net.Http;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);
var response = await client.GetAsync(
$"https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/{blastId}");
response.EnsureSuccessStatusCode();
var blast = await response.Content.ReadAsStringAsync();{
"blastId": "blast_...",
"summary": {
"blastName": "Q3 product update — pipeline forecasting",
"templateName": "Product Update — Q3",
"subject": "Q3 product update — new pipeline forecasting",
"sender": {
"userId": "usr_...",
"displayName": "Alex Rivera"
},
"sentAt": "2026-07-14T13:00:12Z",
"status": "Sent",
"recipientCount": 482,
"successfulSentCount": 478
},
"performance": {
"totalOpens": 542,
"totalClicks": 61,
"totalReplies": 14,
"openRate": 48.3,
"clickRate": 9.2,
"replyRate": 2.5,
"engagementScore": 78.4
}
}Get blast activity
GET /api/v1alpha1/email-blasts/{blastId}/activity
Daily activity timeseries for one blast. Same shape as /buyer-signals/activity, scoped to a single blast.
Query parameters
| Parameter | Type | Description |
|---|---|---|
periodDays | number | 7, 14, or 30. Default 7. Windowed relative to today, not the blast's send time. |
Response
sendsis typically zero for days after the send date — the blast dispatches once, then engagement trickles in. Historical opens/clicks/replies show up on their respective event dates.
Errors
404 email-blast-not-found— no blast with that id in your org.
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/blast_.../activity?periodDays=14" \
-H "X-Cirrus-Api-Key: $TOKEN"import requests
response = requests.get(
f"https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/{blast_id}/activity",
headers={"X-Cirrus-Api-Key": token},
params={"periodDays": 14},
)
response.raise_for_status()
chart = response.json()using System.Net.Http;
using System.Web;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);
var query = HttpUtility.ParseQueryString(string.Empty);
query["periodDays"] = "14";
var uri = new UriBuilder(
$"https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/{blastId}/activity")
{
Query = query.ToString()
}.Uri;
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var chart = await response.Content.ReadAsStringAsync();{
"periodDays": 14,
"items": [
{ "date": "2026-08-11", "action": "sends", "count": 0 },
{ "date": "2026-08-11", "action": "opens", "count": 22 },
{ "date": "2026-08-11", "action": "clicks", "count": 4 },
{ "date": "2026-08-11", "action": "replies", "count": 1 }
]
}List blast recipients
GET /api/v1alpha1/email-blasts/{blastId}/recipients
Per-recipient engagement rows for one blast — one row per contact who was on the send list.
Query parameters
| Parameter | Type | Description |
|---|---|---|
cursor | string | Standard keyset cursor. |
limit | number | Clamped 1–100, default 25. |
sort | string | lastReplyAt, lastOpenAt, replies, opens, sentAt. Prefix - for descending. Default -lastOpenAt. |
hasReplied | boolean | (optional) true restricts to recipients whose reply was tracked. |
search | string | (optional) Substring match on recipient email. |
Response
- Same shape as the sent-emails signal drill-down under Buyer Signals — the columns are the tracked-event roll-up per recipient. Blasts just scope it to one campaign's recipient list.
Errors
404 email-blast-not-found— no blast with that id in your org.
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/blast_.../recipients?limit=50" \
-H "X-Cirrus-Api-Key: $TOKEN"import requests
response = requests.get(
f"https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/{blast_id}/recipients",
headers={"X-Cirrus-Api-Key": token},
params={"limit": 50},
)
response.raise_for_status()
page = response.json()using System.Net.Http;
using System.Web;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);
var query = HttpUtility.ParseQueryString(string.Empty);
query["limit"] = "50";
var uri = new UriBuilder(
$"https://altus.cirrusinsight.com/api/v1alpha1/email-blasts/{blastId}/recipients")
{
Query = query.ToString()
}.Uri;
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var page = await response.Content.ReadAsStringAsync();{
"items": [
{
"recipientEmail": "guest@example.com",
"sentAt": "2026-07-14T13:00:14Z",
"opens": 5,
"clicks": 1,
"replies": 1,
"lastOpenAt": "2026-07-14T14:12:03Z",
"lastReplyAt": "2026-07-14T15:22:18Z",
"lastOpenLocation": "New York, NY"
}
],
"nextCursor": null
}