---
name: run-campaign
order: 2
description: "Build and send an email campaign to a list or a segment with Sending. Use this for bulk sends, newsletters and announcements, not for single emails."
---

# Send a campaign

The flow is always the same: audience, content, estimate, send. The estimate is not
optional unless you want to discover the real volume after hitting send.

## 1. Build the audience

Contacts, one at a time or in batches:

```
upsert_contact { email, attributes: { name: "Sara", plan: "pro" } }
```

It is idempotent on the email: calling it again updates instead of duplicating. The
`attributes` are **merged** with the existing ones, and passing `null` on a key
deletes that key.

Then a static list:

```
create_list { name: "Pro customers" }
add_contacts_to_list { listId, contactIds }
```

Or a dynamic segment, which recomputes itself:

```
create_segment { name, rules }
estimate_segment { segmentId }   → how many people it covers right now
```

To find ids without guessing them: `list_contacts`, `list_lists`, `list_segments`,
`list_tags`.

## 2. Create the campaign

```
create_campaign {
  name: "October launch",
  subject: "Something new for you",
  html: "...",
  listId | segmentId
}
```

## 3. Read it back and fix it

```
get_campaign { campaignId }
update_campaign { campaignId, subject?, html?, ... }
```

If a detail is wrong, **fix the campaign** instead of creating a second one:
abandoned drafts stay around and confuse whoever opens the dashboard after you.

## 4. Estimate, then send

```
estimate_campaign { campaignId }   → real recipients after consent and suppression
send_campaign { campaignId }
```

The estimate is the right moment to have the user confirm: after `send_campaign` the
send actually starts. `list_campaigns` shows the state of the existing ones.

## What Sending always filters out

The estimated number is almost always lower than the list total, and that is
correct:

- contacts without consent for the channel,
- addresses on the **suppression list** (earlier bounces or complaints),
- recipients already reached by an identical idempotent send.

Do not try to work around these filters: they protect the domain reputation, which
is the deliverability of every campaign that comes after.

## Quota

`send_campaign` is subject to the plan quota. `get_usage` shows what is left of the
month: call it before preparing a large send, not after.
