Skip to content
Docs

Create campaigns, choose their audiences, and send or schedule them.

Base URLhttps://api.emailit.com/v2AuthenticationErrorsRate limits

Create a campaign

Creates a campaign in draft status. Requires an API key with the full scope. Emits a campaign.created event.

A new campaign has no recipients. Choose its audiences with Update a campaign, then send or schedule it. Credits are charged when the campaign sends: 2 credits per email.

POST/campaigns

Body parameters

namestringrequired
Internal name of the campaign. Recipients don’t see it. Other campaign endpoints accept the name in place of the ID, so keep names unique if you use them that way.
subjectstring
Subject line. Supports merge tags such as {{first_name}}.
from_emailstring
Sender address. It must be on a verified sending domain in the workspace, for example news@acme.com.
from_namestring
Sender display name, for example Acme. The message is sent from Acme <news@acme.com>.
reply_tostring
Reply-To address. Defaults to from_email when the campaign sends.
htmlstring
HTML body that Emailit sends. Supports the merge tags {{first_name}}, {{last_name}}, {{email}}, {{unsubscribe_url}} and {{cf.<key>}} for custom fields. Set the body when you create the campaign.
textstring
Plain-text body. Supports the same merge tags as html.
preview_textstring
Preview text stored with the campaign. Emailit doesn’t insert it into the message; add a hidden preheader to html if you need one.
contentstring
Editor source of the body (for example MJML), stored as-is. Emailit sends html and text, not content.
content_typestringdefault: html
Format of content: html, text or mjml. Emailit doesn’t compile MJML; send the compiled HTML in html.

Returns

Returns 201 Created with the campaign object. status is draft. The response doesn’t echo html, text or content.

Returns 400 if name is missing and 403 if the API key doesn’t have the full scope.

POST/campaigns
Terminal
curl -X POST https://api.emailit.com/v2/campaigns \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "October newsletter",
    "subject": "October news for {{first_name}}",
    "from_email": "news@acme.com",
    "from_name": "Acme",
    "reply_to": "support@acme.com",
    "html": "<p>Hi {{first_name}},</p><p>Here is what changed this month.</p><p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a></p>",
    "text": "Hi {{first_name}}, here is what changed this month. Unsubscribe: {{unsubscribe_url}}"
  }'
JSON
{
  "object": "campaign",
  "id": "cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN",
  "name": "October newsletter",
  "status": "draft",
  "subject": "October news for {{first_name}}",
  "from_email": "news@acme.com",
  "from_name": "Acme",
  "reply_to": "support@acme.com",
  "preview_text": null,
  "content_type": "html",
  "created_at": "2026-10-01T09:30:12.482193Z",
  "updated_at": "2026-10-01T09:30:12.482193Z"
}

Retrieve a campaign

Retrieves a campaign by its ID or name. Requires an API key with the full scope.

GET/campaigns/{id}

Path parameters

idstringrequired
The campaign ID (cmp_…) or the campaign name. URL-encode names that contain spaces or special characters.

Returns

Returns the campaign object.

objectstring
Always campaign.
idstring
Campaign ID, prefixed cmp_.
statusstring
draft, scheduled, queued, sending, sent, canceled or archived. queued means a scheduled campaign has reached its send time and is waiting for a worker.
namestring
Internal campaign name.
subjectstring
Subject line, with merge tags unresolved.
from_emailstring
Sender address. "" until set.
from_namestring
Sender display name. "" until set.
reply_tostring
Reply-To address. "" means replies go to from_email.
preview_textstring | null
Preview text stored with the campaign.
content_typestring
Format label of the editor source: html, text or mjml for campaigns created through the API.
scheduled_atstring | null
When a scheduled campaign sends, in UTC.
sent_atstring | null
When sending started.
recipientsobject[]
Audiences the campaign targets. Each item has audience_id (aud_…) and exclude (true for an excluded audience).

The body (html, text and content) isn’t included in the response. Engagement statistics are available in the dashboard under Email MarketingCampaigns.

Returns 404 if no campaign in the workspace matches id.

GET/campaigns/{id}
Terminal
curl https://api.emailit.com/v2/campaigns/cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN \
  -H "Authorization: Bearer $EMAILIT_API_KEY"
JSON
{
  "object": "campaign",
  "id": "cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN",
  "name": "October newsletter",
  "status": "scheduled",
  "subject": "October news for {{first_name}}",
  "from_email": "news@acme.com",
  "from_name": "Acme",
  "reply_to": "support@acme.com",
  "preview_text": null,
  "content_type": "html",
  "sent_at": null,
  "scheduled_at": "2026-10-08 09:00:00+00",
  "created_at": "2026-10-01 09:30:12.482193+00",
  "updated_at": "2026-10-01 10:02:47.118204+00",
  "recipients": [
    { "audience_id": "aud_3Cz7WJ9GpvD7P0PQez50xOmkZSV", "exclude": false },
    { "audience_id": "aud_3hRmYTSQ4ca6y9tbPI0IQPjVTL9", "exclude": true }
  ]
}

Update a campaign

Updates the fields you pass and leaves the others unchanged. Use it to choose the campaign’s audiences before you send it. Requires an API key with the full scope. Emits a campaign.updated event.

A scheduled campaign sends whatever is saved at its send time, so you can still edit it after scheduling.

POST/campaigns/{id}

Path parameters

idstringrequired
The campaign ID (cmp_…) or the campaign name.

Body parameters

namestring
Internal campaign name.
subjectstring
Subject line. Supports merge tags.
from_emailstring
Sender address on a verified sending domain.
from_namestring
Sender display name.
reply_tostring
Reply-To address. An empty string means replies go to from_email.
preview_textstring
Preview text stored with the campaign.
contentstring
Editor source of the body, stored as-is.
content_typestring
Format of content: html, text or mjml.
recipientsobject[]

The audiences to target. Replaces the current list. Include at least one audience with exclude set to false.

  • audience_id (string, required): an audience ID (aud_…) in this workspace.
  • exclude (boolean, default false): true saves the audience as an exclusion. The dashboard subtracts excluded audiences from its recipient estimate, but the send itself doesn’t apply exclusions at the moment, so also remove those contacts from the included audiences.

Duplicate audience IDs are ignored. At send time, Emailit emails every subscribed contact of the included audiences once, and skips unsubscribed contacts and suppressed addresses.

The HTML and text body are set when you create the campaign. Unknown body fields are ignored.

Returns

Returns the updated campaign object, including recipients.

Returns 422 if recipients has no included audience or references an audience outside the workspace, and 404 if the campaign doesn’t exist.

POST/campaigns/{id}
Terminal
curl -X POST https://api.emailit.com/v2/campaigns/cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Your October update, {{first_name}}",
    "recipients": [
      { "audience_id": "aud_3Cz7WJ9GpvD7P0PQez50xOmkZSV" },
      { "audience_id": "aud_3hRmYTSQ4ca6y9tbPI0IQPjVTL9", "exclude": true }
    ]
  }'
JSON
{
  "object": "campaign",
  "id": "cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN",
  "name": "October newsletter",
  "status": "draft",
  "subject": "Your October update, {{first_name}}",
  "from_email": "news@acme.com",
  "from_name": "Acme",
  "reply_to": "support@acme.com",
  "preview_text": null,
  "content_type": "html",
  "scheduled_at": null,
  "created_at": "2026-10-01 09:30:12.482193+00",
  "updated_at": "2026-10-01 10:02:47.118204+00",
  "recipients": [
    { "audience_id": "aud_3Cz7WJ9GpvD7P0PQez50xOmkZSV", "exclude": false },
    { "audience_id": "aud_3hRmYTSQ4ca6y9tbPI0IQPjVTL9", "exclude": true }
  ]
}

List campaigns

Returns the workspace’s campaigns, newest first. Requires an API key with the full scope.

GET/campaigns

Query parameters

pageintegerdefault: 1
Page number, starting at 1.
limitintegerdefault: 10
Campaigns per page, from 1 to 100.
statusstring
Shortcut status filter: draft, scheduled, sending (also matches queued), sent, canceled, archived or all.
matchstring

all (default) requires every filter. or matches any filter. See Filtering.

orderstring

Sort key for this list. See the sort keys below.

directionstring

asc or desc.

Filter keys

Filters use key.condition=value query parameters, for example status.exact=sent or created_at.after=2026-09-01. See Filtering for the conditions per type.

Key Type Notes
name string
subject string
status enum draft, scheduled, queued, sending, sent, archived
created_at date
sent_at date

Sort keys for order: name, subject, status, created_at, sent_at.

Returns

Returns a page of campaign objects without reply_to, preview_text, content_type and recipients. Use Retrieve a campaign for those.

dataobject[]
Campaigns on this page.
total_recordsinteger
Number of campaigns that match the query.
next_page_urlstring | null
Path of the next page, or null on the last page. It carries only page and limit, so add your search and filters again when you follow it.
previous_page_urlstring | null
Path of the previous page, or null on the first page.
GET/campaigns
Terminal
curl -G https://api.emailit.com/v2/campaigns \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -d limit=20 \
  -d status=sent \
  -d order=sent_at \
  -d direction=desc
JSON
{
  "data": [
    {
      "object": "campaign",
      "id": "cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN",
      "name": "October newsletter",
      "status": "sent",
      "subject": "Your October update, {{first_name}}",
      "from_email": "news@acme.com",
      "from_name": "Acme",
      "sent_at": "2026-10-08 09:00:04+00",
      "scheduled_at": "2026-10-08 09:00:00+00",
      "created_at": "2026-10-01 09:30:12.482193+00",
      "updated_at": "2026-10-08 09:00:31+00"
    }
  ],
  "total_records": 34,
  "next_page_url": "/v2/campaigns?page=2&limit=20",
  "previous_page_url": null
}

Send or schedule a campaign

Sends the campaign now, or schedules it when you pass a future scheduled_at. Requires an API key with the full scope and a verified workspace: unverified workspaces can’t send campaigns and get 403.

Before you send, make sure the campaign has a from_email on a verified domain, a subject, an html or text body, and at least one included audience (set with Update a campaign). Each email costs 2 credits.

POST/campaigns/{id}/send

Path parameters

idstringrequired
The campaign ID (cmp_…) or the campaign name.

Body parameters

scheduled_atstring

When to send. Accepts ISO 8601 (2026-10-08T09:00:00Z), a Unix timestamp in seconds, or natural language such as tomorrow at 9am (interpreted in UTC). The time must be in the future and the campaign must be a draft.

Omit it to send now. To send a scheduled campaign early, call this endpoint without scheduled_at.

Returns

Send now: the status changes to sending and Emailit emits campaign.sending. Emailit then creates one email per recipient: every subscribed contact of the included audiences, deduplicated by address, without unsubscribed contacts and suppressed addresses. Once every recipient has been handed to the sending pipeline, the status changes to sent and Emailit emits campaign.sent. Track delivery in the dashboard or with email events.

Schedule: the status changes to scheduled and Emailit emits campaign.scheduled. At the scheduled time the campaign becomes queued (campaign.queued) and then sends as above.

The response contains object, id, name and the new status, plus scheduled_at when you schedule.

Status When
403 The workspace isn’t verified, or the API key doesn’t have the full scope.
404 No campaign matches id.
422 scheduled_at can’t be parsed or isn’t in the future, or you tried to schedule a campaign that isn’t a draft.
POST/campaigns/{id}/send
Terminal
curl -X POST https://api.emailit.com/v2/campaigns/cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN/send \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "scheduled_at": "2026-10-08T09:00:00Z" }'
JSON
{
  "object": "campaign",
  "id": "cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN",
  "name": "October newsletter",
  "status": "scheduled",
  "scheduled_at": "2026-10-08T09:00:00.000000Z"
}

Cancel a campaign

Sets the campaign’s status to canceled and emits a campaign.canceled event. Requires an API key with the full scope.

Only campaigns in draft or sending status can be canceled; any other status returns 422. Canceling a campaign that is sending doesn’t recall emails that are already queued for delivery.

POST/campaigns/{id}/cancel

Path parameters

idstringrequired
The campaign ID (cmp_…) or the campaign name.

Returns

Returns object, id, name and status (canceled).

Returns 422 if the campaign’s status isn’t draft or sending, and 404 if the campaign doesn’t exist.

POST/campaigns/{id}/cancel
Terminal
curl -X POST https://api.emailit.com/v2/campaigns/cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN/cancel \
  -H "Authorization: Bearer $EMAILIT_API_KEY"
JSON
{
  "object": "campaign",
  "id": "cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN",
  "name": "October newsletter",
  "status": "canceled"
}

Delete a campaign

Permanently deletes a campaign. Requires an API key with the full scope. Emits a campaign.deleted event.

Deleting a campaign doesn’t affect emails that were already sent or queued. To stop a campaign that is sending, cancel it first.

DELETE/campaigns/{id}

Path parameters

idstringrequired
The campaign ID (cmp_…) or the campaign name.

Returns

Returns object, id, name and deleted: true. Returns 404 if the campaign doesn’t exist.

DELETE/campaigns/{id}
Terminal
curl -X DELETE https://api.emailit.com/v2/campaigns/cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN \
  -H "Authorization: Bearer $EMAILIT_API_KEY"
JSON
{
  "object": "campaign",
  "id": "cmp_3zNrBaNjAoPK1l0IL2GQ3pDkubN",
  "name": "October newsletter",
  "deleted": true
}

Was this page helpful?

Thanks for the feedback.

Thanks, we read every message.