---
title: "Campaigns"
description: "One-to-many sends to a segment or an inline recipient list. Draft, validate, schedule, send, pause, resume, and cancel — with a pre-send report that catches problems before anything goes out."
url: https://www.unitpost.com/docs/api/campaigns
section: API reference
updated: 2026-07-31
---
# Campaigns

## Campaigns

> One-to-many sends to a segment or an inline recipient list. Draft, validate, schedule, send, pause, resume, and cancel — with a pre-send report that catches problems before anything goes out.

Full schemas: [OpenAPI 3.1](https://www.unitpost.com/api/v1/openapi.json). HTML reference: https://www.unitpost.com/docs/api/campaigns.

## Operations

### `GET /api/v1/email/campaigns`

List campaigns

Retrieve a list of your campaigns, cursor-paginated. Each row is a reference to one campaign and its current status (`draft`, `scheduled`, `sending`, `sent`, …). Use a campaign's `id` with [Retrieve a campaign](#get-email-campaigns-id) for the full record, or with [List sent emails](#get-email) (`?campaign_id=`) to see the individual emails it produced. Requires the `campaigns:read` capability.

### `POST /api/v1/email/campaigns`

Create a campaign

Create a campaign in `draft`. Target either a saved segment (`segment_id`, see [Create a segment](#post-segments)) or an inline `recipients` list, and optionally scope it to a subscription topic (`topic_id`) so contacts who opted out of that topic are skipped automatically. Content comes from a `template_id` or inline `html`/`text`. Nothing is sent yet — edit the draft with [Update a campaign](#patch-email-campaigns-id), check it with [Validate a campaign](#get-email-campaigns-id-validate), then launch it with [Send a campaign](#post-email-campaigns-id-send). Requires the `campaigns:write` capability.

### `GET /api/v1/email/campaigns/{id}`

Retrieve a campaign

Retrieve a single campaign by `id`, including its status, targeting, content references, and schedule. To see the individual emails a sent campaign produced, filter [List sent emails](#get-email) by `campaign_id`; for a pre-send readiness report, use [Validate a campaign](#get-email-campaigns-id-validate). Requires the `campaigns:read` capability.

### `PATCH /api/v1/email/campaigns/{id}`

Update a campaign

Edit a campaign while it's still in `draft` (content edits after that return `409`). Beyond content and targeting, you can: send `archived` to archive/restore it; set `variable_fallbacks` (fill-only per-variable defaults) and/or `excluded_contact_ids` to resolve a send blocked by missing variables — the API equivalent of the dashboard's pre-send fix; set `topic_id` to scope it to a subscription topic (or `null` to clear); and set `open_tracking`/`click_tracking` (tri-state; `null` inherits the template/domain default). See what's blocking a send with [Validate a campaign](#get-email-campaigns-id-validate). Requires the `campaigns:write` capability.

### `DELETE /api/v1/email/campaigns/{id}`

Delete a campaign

Permanently delete a campaign that's in `draft` or a terminal state (sent, canceled, failed). A campaign that's mid-flight can't be deleted — stop it first with [Cancel a campaign](#post-email-campaigns-id-cancel). Requires the `campaigns:write` capability.

### `POST /api/v1/email/campaigns/{id}/send`

Send a campaign

Validate a campaign and then send it — immediately, or at its `scheduled_at` if one is set. If anything blocks the send (unverified domain, missing template variables, empty audience, …) you get a `409` with each blocking reason itemized in `error.details[]`. To see the full pre-send report without attempting a send, use [Validate a campaign](#get-email-campaigns-id-validate); fix variable issues via [Update a campaign](#patch-email-campaigns-id). A launched campaign can be [paused](#post-email-campaigns-id-pause) or [canceled](#post-email-campaigns-id-cancel). Requires the `campaigns:send` capability.

### `POST /api/v1/email/campaigns/{id}/cancel`

Cancel a campaign

Cancel a `draft`, `scheduled`, or `sending` campaign. Cancelation is terminal — the campaign can't be restarted afterwards. Messages already sent to recipients are not recalled. If you only want to stop temporarily, use [Pause a campaign](#post-email-campaigns-id-pause) instead. Requires the `campaigns:send` capability.

### `POST /api/v1/email/campaigns/{id}/pause`

Pause a campaign

Pause a `scheduled` or `sending` campaign. A paused send stops cleanly between recipients — already-sent messages are untouched, and no partial email is ever produced. Continue where it left off with [Resume a campaign](#post-email-campaigns-id-resume), or stop it for good with [Cancel a campaign](#post-email-campaigns-id-cancel). Requires the `campaigns:send` capability.

### `POST /api/v1/email/campaigns/{id}/resume`

Resume a campaign

Resume a `paused` campaign. Sending continues with the recipients that hadn't been reached yet; anyone already delivered to is skipped idempotently, so nobody receives the campaign twice. Pause a send with [Pause a campaign](#post-email-campaigns-id-pause). Requires the `campaigns:send` capability.

### `POST /api/v1/email/campaigns/{id}/reschedule`

Reschedule a campaign

Move a `scheduled` campaign to a new send time. Only campaigns that haven't started sending can be rescheduled — once a send is in flight, [pause](#post-email-campaigns-id-pause) or [cancel](#post-email-campaigns-id-cancel) it instead. Requires the `campaigns:send` capability.

### `GET /api/v1/email/campaigns/{id}/validate`

Validate a campaign

Run a non-mutating pre-send check and get the full readiness report: how many contacts will receive the campaign, how many are suppressed or excluded, which contacts are missing template variables, and a final `can_send` verdict. Nothing is sent or changed. Fix reported variable gaps with [Update a campaign](#patch-email-campaigns-id) (`variable_fallbacks` / `excluded_contact_ids`), then launch with [Send a campaign](#post-email-campaigns-id-send). Requires the `campaigns:read` capability.

## Related

- [Templates](https://www.unitpost.com/docs/api/templates): Reusable email designs in the canonical block-based JSON format the dashboard editor produces, with per-recipient `{{variables}}` filled at send time.
- [Brand kits](https://www.unitpost.com/docs/api/brand-kits): Read-only Brand Kit profiles (voice, labeled colors, pinned library graphics, core pages) for on-brand template authoring. Writes and URL import stay in the dashboard (Settings → Brand).
- [Domains](https://www.unitpost.com/docs/api/domains): The domains you send from. Add a domain, publish its DNS records, verify it, and manage its tracking and TLS defaults — sending is blocked until the domain verifies.
