# Create campaign (/api-reference/campaigns/createCampaign)

`POST /campaigns`

Base URL: `https://next-api.useplunk.com`

Create a new email campaign. Campaigns are created as `DRAFT`; use `POST /campaigns/{id}/send` to send or schedule one.

The sender domain must already be verified for this project.

**Audience:** `audienceType` decides which companion field is required — `SEGMENT` requires `segmentId`, `FILTERED` requires `audienceCondition`, and `ALL` requires neither.

## Request body

- `name`: string (required) — Campaign name
- `description`: string — Campaign description
- `subject`: string (required) — Email subject line
- `body`: string (required) — HTML email body
- `from`: string (email) (required) — Sender email address (must be from verified domain)
- `fromName`: string — Sender name
- `replyTo`: string (email) — Reply-to email address
- `type`: enum ("TRANSACTIONAL" | "MARKETING" | "HEADLESS") — Content type of the campaign email. Defaults to `MARKETING`.
- `audienceType`: enum ("ALL" | "SEGMENT" | "FILTERED") (required) — Target audience type
- `segmentId`: string (uuid) — Segment ID. Required when `audienceType` is `SEGMENT`.
- `audienceCondition`: object — Audience filter tree. Required when `audienceType` is `FILTERED`. Same structure as a segment's `condition`.

Example:

```json
{
  "name": "string",
  "subject": "string",
  "body": "string",
  "from": "user@example.com",
  "audienceType": "ALL"
}
```

## Responses

### `201` — Campaign created

- `success`: boolean
- `data`: object
  - `id`: string
  - `name`: string
  - `description`: string
  - `subject`: string
  - `body`: string
  - `from`: string (email)
  - `fromName`: string
  - `replyTo`: string (email)
  - `type`: enum ("TRANSACTIONAL" | "MARKETING" | "HEADLESS") — Content type of the campaign email. Not to be confused with `audienceType`.
  - `status`: enum ("DRAFT" | "SCHEDULED" | "SENDING" | "SENT" | "CANCELLED")
  - `audienceType`: enum ("ALL" | "SEGMENT" | "FILTERED")
  - `audienceCondition`: object — Set when `audienceType` is `FILTERED`.
  - `segmentId`: string — Set when `audienceType` is `SEGMENT`.
  - `scheduledFor`: string (date-time) — When the campaign is scheduled to send. Null for immediate or unsent campaigns.
  - `totalRecipients`: integer
  - `sentCount`: integer
  - `deliveredCount`: integer
  - `openedCount`: integer
  - `clickedCount`: integer
  - `bouncedCount`: integer
  - `projectId`: string
  - `sentAt`: string (date-time)
  - `createdAt`: string (date-time)
  - `updatedAt`: string (date-time)

```json
{
  "success": false,
  "data": {
    "id": "string",
    "name": "string",
    "description": "string",
    "subject": "string",
    "body": "string",
    "from": "user@example.com",
    "fromName": "string",
    "replyTo": "user@example.com",
    "type": "TRANSACTIONAL",
    "status": "DRAFT",
    "audienceType": "ALL",
    "audienceCondition": {
      "logic": "AND",
      "groups": [
        {
          "filters": [
            {
              "field": "string",
              "operator": "equals"
            }
          ]
        }
      ]
    },
    "segmentId": "string",
    "scheduledFor": "2026-08-09T17:56:20.149Z",
    "totalRecipients": 0,
    "sentCount": 0,
    "deliveredCount": 0,
    "openedCount": 0,
    "clickedCount": 0,
    "bouncedCount": 0,
    "projectId": "string",
    "sentAt": "2026-08-09T17:56:20.149Z",
    "createdAt": "2026-08-09T17:56:20.149Z",
    "updatedAt": "2026-08-09T17:56:20.149Z"
  }
}
```

### `400` — `segmentId` missing for a `SEGMENT` campaign, or `audienceCondition` missing for a `FILTERED` campaign.

- `success`: enum (false)
- `error`: object
  - `code`: string — Machine-readable error code, e.g. `VALIDATION_ERROR`, `INVALID_API_KEY`, `IDEMPOTENCY_KEY_REUSED`.
  - `message`: string
  - `statusCode`: integer
  - `requestId`: string — Correlation ID for this request. Include it when contacting support.
  - `errors`: array<object> — Field-level detail, present on validation failures.
    items:
      - `field`: string — Dot-path of the offending field, e.g. `attachments.0.filename`.
      - `message`: string
      - `code`: string — Validation issue code, e.g. `invalid_type`, `too_big`, `reserved_event`.
      - `received`: object — The value that was received, when available.
  - `details`: object — Additional error context.
  - `suggestion`: string — Hint for fixing the request.
- `timestamp`: string (date-time)

```json
{
  "success": false,
  "error": {
    "code": "string",
    "message": "string",
    "statusCode": 0,
    "requestId": "string",
    "errors": [
      {
        "field": "string",
        "message": "string",
        "code": "string",
        "received": null
      }
    ],
    "details": null,
    "suggestion": "string"
  },
  "timestamp": "2026-08-09T17:56:20.149Z"
}
```

### `401` — Missing or invalid API key.

- `success`: enum (false)
- `error`: object
  - `code`: string — Machine-readable error code, e.g. `VALIDATION_ERROR`, `INVALID_API_KEY`, `IDEMPOTENCY_KEY_REUSED`.
  - `message`: string
  - `statusCode`: integer
  - `requestId`: string — Correlation ID for this request. Include it when contacting support.
  - `errors`: array<object> — Field-level detail, present on validation failures.
    items:
      - `field`: string — Dot-path of the offending field, e.g. `attachments.0.filename`.
      - `message`: string
      - `code`: string — Validation issue code, e.g. `invalid_type`, `too_big`, `reserved_event`.
      - `received`: object — The value that was received, when available.
  - `details`: object — Additional error context.
  - `suggestion`: string — Hint for fixing the request.
- `timestamp`: string (date-time)

```json
{
  "success": false,
  "error": {
    "code": "string",
    "message": "string",
    "statusCode": 0,
    "requestId": "string",
    "errors": [
      {
        "field": "string",
        "message": "string",
        "code": "string",
        "received": null
      }
    ],
    "details": null,
    "suggestion": "string"
  },
  "timestamp": "2026-08-09T17:56:20.149Z"
}
```

### `403` — The sender domain is not registered to this project, or has not completed DNS verification. Add and verify the domain in your project settings first.

- `success`: enum (false)
- `error`: object
  - `code`: string — Machine-readable error code, e.g. `VALIDATION_ERROR`, `INVALID_API_KEY`, `IDEMPOTENCY_KEY_REUSED`.
  - `message`: string
  - `statusCode`: integer
  - `requestId`: string — Correlation ID for this request. Include it when contacting support.
  - `errors`: array<object> — Field-level detail, present on validation failures.
    items:
      - `field`: string — Dot-path of the offending field, e.g. `attachments.0.filename`.
      - `message`: string
      - `code`: string — Validation issue code, e.g. `invalid_type`, `too_big`, `reserved_event`.
      - `received`: object — The value that was received, when available.
  - `details`: object — Additional error context.
  - `suggestion`: string — Hint for fixing the request.
- `timestamp`: string (date-time)

```json
{
  "success": false,
  "error": {
    "code": "string",
    "message": "string",
    "statusCode": 0,
    "requestId": "string",
    "errors": [
      {
        "field": "string",
        "message": "string",
        "code": "string",
        "received": null
      }
    ],
    "details": null,
    "suggestion": "string"
  },
  "timestamp": "2026-08-09T17:56:20.149Z"
}
```

### `422` — Request body failed schema validation. `error.errors` lists the offending fields.

- `success`: enum (false)
- `error`: object
  - `code`: string — Machine-readable error code, e.g. `VALIDATION_ERROR`, `INVALID_API_KEY`, `IDEMPOTENCY_KEY_REUSED`.
  - `message`: string
  - `statusCode`: integer
  - `requestId`: string — Correlation ID for this request. Include it when contacting support.
  - `errors`: array<object> — Field-level detail, present on validation failures.
    items:
      - `field`: string — Dot-path of the offending field, e.g. `attachments.0.filename`.
      - `message`: string
      - `code`: string — Validation issue code, e.g. `invalid_type`, `too_big`, `reserved_event`.
      - `received`: object — The value that was received, when available.
  - `details`: object — Additional error context.
  - `suggestion`: string — Hint for fixing the request.
- `timestamp`: string (date-time)

```json
{
  "success": false,
  "error": {
    "code": "string",
    "message": "string",
    "statusCode": 0,
    "requestId": "string",
    "errors": [
      {
        "field": "string",
        "message": "string",
        "code": "string",
        "received": null
      }
    ],
    "details": null,
    "suggestion": "string"
  },
  "timestamp": "2026-08-09T17:56:20.149Z"
}
```

## Example request

```bash
curl -X POST 'https://next-api.useplunk.com/campaigns' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name":"string","subject":"string","body":"string","from":"user@example.com","audienceType":"ALL"}'
```
