Marketing Campaigns
List your workspace's Marketing Campaigns with their status and email counts.
A Campaign groups the Marketing Emails, Forms, Sequences and other assets behind one marketing push. The API can list Campaigns; creating and editing them is done in Signal.
Marketing endpoints need a plan that includes Marketing. The check runs on every request, so a key created while the plan included Marketing stops working with these endpoints if the plan changes (403 PLAN_FEATURE_REQUIRED).
The Campaign object#
| Field | Type | Notes |
|---|---|---|
id |
string | |
name |
string | |
status |
string | draft, live, scheduled, sending, sent or archived. Worked out from the Campaign and its Emails. |
description |
string or null | |
goal |
string or null | |
starts_on |
string or null | Start date as entered. |
ends_on |
string or null | End date as entered. |
assigned_to_user_id |
string or null | User ID of the person in Assigned To. |
assigned_to_name |
string or null | Their name. null when nobody is assigned or they're no longer a member. |
archived |
boolean | |
email_total |
integer | Number of Emails in the Campaign. |
email_counts |
object | Emails by status: draft, scheduled, sending, paused, sent and cancelled, each an integer. |
created_at |
string | ISO 8601 timestamp. |
updated_at |
string | ISO 8601 timestamp. |
Budgets and UTM tags aren't returned.
{
"id": "6a8c0e2f-4b6d-4f8a-9c1e-3a5c7e9b1d48",
"name": "Winter webinar series",
"status": "live",
"description": "Three webinars for operations leaders.",
"goal": "150 registrations",
"starts_on": "2026-11-01",
"ends_on": "2027-01-31",
"assigned_to_user_id": "5b8d1f3a-7e2c-4a9b-b6d4-1c3e5f7a9b20",
"assigned_to_name": "Jordan Smith",
"archived": false,
"email_total": 4,
"email_counts": { "draft": 1, "scheduled": 1, "sending": 0, "paused": 0, "sent": 2, "cancelled": 0 },
"created_at": "2026-10-20T14:05:00.000Z",
"updated_at": "2026-11-10T08:45:30.000Z"
}
List Campaigns#
GET /marketing/campaigns · Scope: marketing:read
Archived Campaigns are listed only when you ask for status=archived. Up to 500 Campaigns are considered; if a workspace has more, meta.truncated is true.
Query parameters#
| Parameter | Type | Required | Notes |
|---|---|---|---|
status |
string | No | draft, live, scheduled, sending, sent or archived. Empty means all except archived. |
limit |
integer | No | 1 to 100. Default 20. |
cursor |
string | No | meta.cursor from the previous page. |
Example#
curl "https://crm.empiraa.app/api/v1/marketing/campaigns?status=live" \
-H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch("https://crm.empiraa.app/api/v1/marketing/campaigns?status=live", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data, meta } = await res.json();
Response 200#
{
"data": [
{
"id": "6a8c0e2f-4b6d-4f8a-9c1e-3a5c7e9b1d48",
"name": "Winter webinar series",
"status": "live",
"description": null,
"goal": null,
"starts_on": null,
"ends_on": null,
"assigned_to_user_id": null,
"assigned_to_name": null,
"archived": false,
"email_total": 4,
"email_counts": { "draft": 1, "scheduled": 1, "sending": 0, "paused": 0, "sent": 2, "cancelled": 0 },
"created_at": "2026-10-20T14:05:00.000Z",
"updated_at": "2026-11-10T08:45:30.000Z"
}
],
"meta": { "cursor": null, "hasMore": false, "truncated": false },
"error": null
}
Errors#
| Status | Code | When |
|---|---|---|
| 400 | INVALID_REQUEST |
status isn't one of the values above, or cursor isn't a value this endpoint returned. |
| 403 | PLAN_FEATURE_REQUIRED |
The workspace's plan doesn't include Marketing. See the plan error body. |
| 503 | FEATURE_CHECK_ERROR |
Signal couldn't check the plan. Retry shortly. |
For Marketing events such as email opens, clicks and unsubscribes, use webhooks.

