> ## Documentation Index
> Fetch the complete documentation index at: https://developers.benchmarkemail.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage campaigns

# Manage Campaigns

Create, read, update, and manage email campaigns using the API. Browse available email templates to use as starting points.

## Goal

By the end of this guide you will be able to list campaigns, retrieve campaign details, create new campaigns, update campaign settings, duplicate campaigns, delete campaigns, and browse email templates.

## Prerequisites

* An API key with **`campaigns:write`** scope (for full CRUD) or **`campaigns:read`** scope (for read-only access)
* Your API base URL (found on the Settings > API Keys page)
* At least one contact list and a verified sending domain (for creating campaigns)

**Important:** Scheduling, sending, canceling, and test-sending campaigns is not available via API key. Use the Benchmark Email web application for those actions. API keys can prepare campaigns (create, configure, assign recipients) that are then sent manually from the UI.

## Steps

### 1. List campaigns

Retrieve campaigns with optional filtering by status, pagination, and sorting.

```bash theme={null}
curl "https://api-us-west-2-c1.benchmarkemail.com/api/email/campaign?page=1&size=25&sort=updatedAt:desc" \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
```

**Response** (`200 OK`):

```json theme={null}
{
  "total": 42,
  "records": [
    {
      "_id": "66f1a6e4698f1bca60426001",
      "name": "March Newsletter",
      "from": "news@mybusiness.com",
      "subject": "Your March Update is Here",
      "previewText": "New features, tips, and more",
      "status": "draft",
      "createdAt": "2026-03-25T10:00:00.000Z",
      "updatedAt": "2026-03-28T14:30:00.000Z"
    },
    {
      "_id": "66f1a6e4698f1bca60426002",
      "name": "Spring Sale Announcement",
      "from": "offers@mybusiness.com",
      "subject": "Spring Sale - 30% Off Everything",
      "previewText": "Limited time offer",
      "previewImageUrl": "https://cdn.benchmarkemail.com/previews/66f1a6e4698f1bca60426002.png",
      "status": "sent",
      "sentCount": 4520,
      "failedCount": 12,
      "totalRecipients": 4532,
      "scheduledAt": "2026-03-20T09:00:00.000Z",
      "createdAt": "2026-03-18T16:00:00.000Z",
      "updatedAt": "2026-03-20T09:05:00.000Z",
      "stats": {
        "sent": 4520,
        "delivered": 4389,
        "opens": {
          "unique": 1876,
          "rate": 42.74
        },
        "clicks": {
          "unique": 623,
          "rate": 14.19
        }
      }
    }
  ]
}
```

**Query parameters:**

| Parameter  | Type    | Description                                                                                       |
| ---------- | ------- | ------------------------------------------------------------------------------------------------- |
| `page`     | integer | Page number (1-indexed)                                                                           |
| `size`     | integer | Results per page                                                                                  |
| `statuses` | string  | Filter by status: `draft`, `scheduled`, `sent`, `sending`, `paused`, `failed`, `cancelled`        |
| `sort`     | string  | Sort field and direction, e.g. `name:asc`, `createdAt:desc`, `updatedAt:desc`, `scheduledAt:desc` |
| `criteria` | string  | Search filter text to match campaign names                                                        |

### 2. Get a campaign by ID

```bash theme={null}
curl https://api-us-west-2-c1.benchmarkemail.com/api/email/campaign/66f1a6e4698f1bca60426001 \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
```

**Response** (`200 OK`):

```json theme={null}
{
  "_id": "66f1a6e4698f1bca60426001",
  "name": "March Newsletter",
  "from": "news@mybusiness.com",
  "fromName": "My Business",
  "subject": "Your March Update is Here",
  "previewText": "New features, tips, and more",
  "body": "<html>...</html>",
  "plainTextBody": "Your March Update is Here...",
  "replyToAddresses": ["support@mybusiness.com"],
  "contactStructureId": "64a1b2c3d4e5f6a7b8c9d0e1",
  "lists": ["66f1a6e4698f1bca60425001"],
  "status": "draft",
  "createdAt": "2026-03-25T10:00:00.000Z",
  "updatedAt": "2026-03-28T14:30:00.000Z",
  "__v": 2
}
```

### 3. Create a campaign

Create a new draft campaign. At minimum, provide a name. Other fields like subject, from address, and body can be set during creation or added later via update.

```bash theme={null}
curl -X POST https://api-us-west-2-c1.benchmarkemail.com/api/email/campaign \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "April Product Update",
    "from": "news@mybusiness.com",
    "fromName": "My Business",
    "subject": "What'\''s New in April",
    "previewText": "Exciting updates inside",
    "body": "<html><body><h1>April Update</h1><p>Here are the latest updates...</p></body></html>",
    "plainTextBody": "April Update\n\nHere are the latest updates...",
    "replyToAddresses": ["support@mybusiness.com"],
    "contactStructureId": "64a1b2c3d4e5f6a7b8c9d0e1",
    "lists": ["66f1a6e4698f1bca60425001"]
  }'
```

**Response** (`200 OK`):

```json theme={null}
{
  "_id": "66f1a6e4698f1bca60426003",
  "name": "April Product Update",
  "from": "news@mybusiness.com",
  "fromName": "My Business",
  "subject": "What's New in April",
  "previewText": "Exciting updates inside",
  "status": "draft",
  "createdAt": "2026-03-28T15:00:00.000Z",
  "updatedAt": "2026-03-28T15:00:00.000Z"
}
```

**Campaign fields:**

| Field                | Type    | Description                                                        |
| -------------------- | ------- | ------------------------------------------------------------------ |
| `name`               | string  | Campaign name (for internal reference)                             |
| `from`               | string  | Sender email address (must be from a verified domain)              |
| `fromName`           | string  | Sender display name (max 100 characters)                           |
| `subject`            | string  | Email subject line                                                 |
| `previewText`        | string  | Preview text shown in inbox (max 100 characters)                   |
| `body`               | string  | HTML email body                                                    |
| `plainTextBody`      | string  | Plain text version of the email                                    |
| `replyToAddresses`   | array   | Reply-to email addresses                                           |
| `contactStructureId` | string  | Contact structure for recipient selection                          |
| `lists`              | array   | List IDs to send to                                                |
| `allowDuplicates`    | boolean | Allow creating a campaign with a duplicate name (default: `false`) |

### 4. Update a campaign

Update an existing draft campaign. Include the `__v` version field for optimistic concurrency control.

```bash theme={null}
curl -X PATCH https://api-us-west-2-c1.benchmarkemail.com/api/email/campaign/66f1a6e4698f1bca60426003 \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "April Product Update - Don'\''t Miss Out!",
    "previewText": "New features and improvements",
    "lists": [
      "66f1a6e4698f1bca60425001",
      "66f1a6e4698f1bca60425002"
    ],
    "__v": 0
  }'
```

**Response** (`200 OK`):

```json theme={null}
{
  "_id": "66f1a6e4698f1bca60426003",
  "name": "April Product Update",
  "from": "news@mybusiness.com",
  "fromName": "My Business",
  "subject": "April Product Update - Don't Miss Out!",
  "previewText": "New features and improvements",
  "status": "draft",
  "createdAt": "2026-03-28T15:00:00.000Z",
  "updatedAt": "2026-03-28T15:30:00.000Z",
  "__v": 1
}
```

### 5. Duplicate a campaign

Create a copy of an existing campaign. Useful for creating variations or reusing a previous campaign as a template.

```bash theme={null}
curl -X POST https://api-us-west-2-c1.benchmarkemail.com/api/email/campaign/66f1a6e4698f1bca60426002/duplicate \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring Sale Follow-Up"
  }'
```

**Response** (`200 OK`):

```json theme={null}
{
  "_id": "66f1a6e4698f1bca60426004",
  "name": "Spring Sale Follow-Up",
  "from": "offers@mybusiness.com",
  "subject": "Spring Sale - 30% Off Everything",
  "status": "draft",
  "createdAt": "2026-03-28T16:00:00.000Z",
  "updatedAt": "2026-03-28T16:00:00.000Z"
}
```

The duplicated campaign starts in `draft` status regardless of the original campaign's status.

### 6. Delete a campaign

```bash theme={null}
curl -X DELETE https://api-us-west-2-c1.benchmarkemail.com/api/email/campaign/66f1a6e4698f1bca60426003 \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
```

**Response** (`204 No Content`): Empty body.

### 7. Browse email templates

List available email templates to use as starting points for your campaigns. Templates are read-only via API key.

```bash theme={null}
curl "https://api-us-west-2-c1.benchmarkemail.com/api/email/template?lang=en" \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
```

**Response** (`200 OK`):

```json theme={null}
{
  "total": 24,
  "records": [
    {
      "id": "welcome-email-001",
      "name": "Welcome Email",
      "subject": "Welcome to Our Community",
      "imageUrl": "https://cdn.benchmarkemail.com/templates/welcome-email-001.png",
      "unlayerId": 12345,
      "attributeIds": ["onboarding", "welcome"],
      "lang": "en"
    },
    {
      "id": "monthly-newsletter-002",
      "name": "Monthly Newsletter",
      "subject": "Your Monthly Update",
      "imageUrl": "https://cdn.benchmarkemail.com/templates/monthly-newsletter-002.png",
      "unlayerId": 12346,
      "attributeIds": ["newsletter"],
      "lang": "en"
    }
  ]
}
```

Get a specific template by ID:

```bash theme={null}
curl "https://api-us-west-2-c1.benchmarkemail.com/api/email/template/66f1a6e4698f1bca60427001?lang=en" \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
```

You can also list template categories:

```bash theme={null}
curl "https://api-us-west-2-c1.benchmarkemail.com/api/email/template/categories?lang=en" \
  -H "X-API-Key: bme_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
```

## Common Errors

| Status | Error                            | Cause                                                   | Fix                                                                         |
| ------ | -------------------------------- | ------------------------------------------------------- | --------------------------------------------------------------------------- |
| `401`  | `UnauthorizedError`              | Invalid or inactive API key                             | Verify your key in Settings > API Keys                                      |
| `403`  | `ForbiddenError` — missing scope | Key lacks `campaigns:write` or `campaigns:read` scope   | Create or upgrade your key with the required scope                          |
| `403`  | `ForbiddenError` — send blocked  | Attempted to schedule, cancel, or test-send via API key | These operations are not available via API key. Use the web application     |
| `400`  | `ValidationError`                | Invalid campaign data (e.g., unverified from address)   | Check the request body. The `from` address must belong to a verified domain |
| `404`  | `RecordNotFound`                 | Campaign ID does not exist                              | Verify the campaign ID                                                      |
| `400`  | `DuplicateFieldError`            | Duplicate campaign name                                 | Set `allowDuplicates: true` in the request body, or use a unique name       |
| `429`  | `TooManyRequestsError`           | Rate limit exceeded                                     | Wait for the `Retry-After` period. See [Rate Limits](../rate-limits.md)     |

## Next Steps

* [View Reports](./view-reports.md) — check performance metrics for sent campaigns
* [Manage Lists](./manage-lists.md) — create and manage the lists your campaigns send to
* [Manage Contacts](./manage-contacts.md) — manage the contacts on those lists
* [Migration from Legacy](./migration-from-legacy.md) — set up your complete email program via API
