---
title: "API reference: Campaigns"
url: "https://coldmeetings.com/docs/api/campaigns.md"
canonical_url: "https://coldmeetings.com/docs/api/campaigns"
last_updated: "2026-10-23"
type: "reference"
summary: "Create campaigns with multi step sequences, import verified prospects, run preflight, launch, pause and read reports with the ColdMeetings API."
related: ["https://coldmeetings.com/docs/api.md", "https://coldmeetings.com/docs/errors.md"]
---

# API reference: Campaigns

> **For AI agents:** the complete index of ColdMeetings pages is [llms.txt](https://coldmeetings.com/llms.txt). Every page is also served as markdown at its URL plus .md.

Create campaigns with multi step sequences, import verified prospects, run preflight, launch, pause and read reports with the ColdMeetings API.

A campaign is a sequence of steps, a list of prospects and a status. This is where credits are spent: each imported prospect costs one.

Base URL: `YOUR_API_BASE_URL`. Every request and response is JSON. Errors use [one envelope](https://coldmeetings.com/docs/errors.md).

| Operation | What it does |
| --- | --- |
| [`GET /v1/campaigns`](#get-v1campaigns) | List campaigns. |
| [`POST /v1/campaigns`](#post-v1campaigns) | Create a draft campaign with its sequence. |
| [`GET /v1/campaigns/{id}`](#get-v1campaignsid) | One campaign. |
| [`POST /v1/campaigns/{id}/prospects`](#post-v1campaignsidprospects) | Import prospects: dedupe, suppression, region gate, verification, one credit each. |
| [`GET /v1/campaigns/{id}/preflight`](#get-v1campaignsidpreflight) | Everything that still blocks launch. |
| [`POST /v1/campaigns/{id}/launch`](#post-v1campaignsidlaunch) | Launch through the sending engine. |
| [`POST /v1/campaigns/{id}/pause`](#post-v1campaignsidpause) | Pause a campaign. Always pauses locally, even when the engine is unreachable; an unconfirmed engine pause is retried until it succeeds. |
| [`POST /v1/campaigns/{id}/resume`](#post-v1campaignsidresume) | Resume a campaign you paused. Runs the preflight, removes suppressed leads at the sending engine, then restarts it. Refused while the engine has not confirmed the pause (409), and for a campaign ColdMeetings paused itself (403). |
| [`GET /v1/campaigns/{id}/report`](#get-v1campaignsidreport) | Sent, bounce, complaint and reply rates, reply intents, meetings booked. |

## GET /v1/campaigns

List campaigns.

Authentication: send your API key as a bearer token. See [Authentication](https://coldmeetings.com/docs/authentication.md).

### Query parameters

| Name | Type | Notes |
| --- | --- | --- |
| `limit` | integer | Rows per page, 1 to 100. More than 100 is held to 100. |
| `cursor` | string | The next_cursor of the previous page, sent back unchanged to the same route. Leave it out for the first page. A cursor that was edited or came from another route is refused. |

### Response

Status 200 OK.

```json
{
  "campaigns": [
    {
      "id": "cmp_2LmQx7RtVw3ZbN1pEs9fKd",
      "name": "Q4 outbound to software teams",
      "status": "draft",
      "timezone": "America/New_York",
      "pause_reason": null,
      "pause_origin": null,
      "steps": [
        {
          "delay_days": 0,
          "variants": [
            {
              "subject": "Outbound without the busywork",
              "body": "Hello,\n\nWe run outbound for B2B software teams, from sending domains to booked calls. Would a short call about your pipeline be useful?\n\n{{sender_address}}\n{{unsubscribe}}"
            }
          ]
        },
        {
          "delay_days": 3,
          "variants": [
            {
              "subject": "Following up",
              "body": "Hello,\n\nA quick follow up on my note. If outbound is not a priority this quarter, tell me and I will stop writing.\n\n{{sender_address}}\n{{unsubscribe}}"
            }
          ]
        }
      ],
      "created_at": "2026-10-17T12:00:00.000Z",
      "launched_at": null
    }
  ],
  "next_cursor": null
}
```

- `status` is `draft`, `active` or `paused`. `pause_reason` explains a pause and `pause_origin` says who paused it (`customer` or `system`); both are `null` otherwise.
- Oldest first, 20 a page. Send `limit` (1 to 100) for more, and send `next_cursor` back as `cursor` for the next page; `next_cursor` is `null` on the last page.

### Errors

- [`unauthorized`](https://coldmeetings.com/docs/errors.md#unauthorized), HTTP 401: The API key is missing, malformed, revoked or unknown.
- [`rate_limited`](https://coldmeetings.com/docs/errors.md#rate_limited), HTTP 429: Too many requests for this key. Wait the number of seconds in `Retry-After`.

### Example request

```bash
curl YOUR_API_BASE_URL/v1/campaigns \
  -H "Authorization: Bearer $COLDMEETINGS_API_KEY"
```

## POST /v1/campaigns

Create a draft campaign with its sequence.

Creates a draft. Nothing is sent until you import prospects and launch.

Authentication: send your API key as a bearer token. See [Authentication](https://coldmeetings.com/docs/authentication.md).

### Request body

Send a JSON object.

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `name` | string | Yes | Up to 120 characters. |
| `timezone` | string | No | Default `"America/New_York"`. At least 3 characters. Up to 64 characters. |
| `steps` | array of object | Yes | 1 to 6 items. |
| `steps[].delay_days` | integer | Yes | Days to wait after the previous step. 0 for step 1. From 0 to 30. |
| `steps[].variants` | array of object | Yes | A/B alternatives. The first is the control. Every body must contain {{unsubscribe}} and {{sender_address}}. 1 to 4 items. |
| `steps[].variants[].subject` | string | Yes | Up to 200 characters. |
| `steps[].variants[].body` | string | Yes | Up to 5000 characters. |

Example body:

```json
{
  "name": "Q4 outbound to software teams",
  "timezone": "America/New_York",
  "steps": [
    {
      "delay_days": 0,
      "variants": [
        {
          "subject": "Outbound without the busywork",
          "body": "Hello,\n\nWe run outbound for B2B software teams, from sending domains to booked calls. Would a short call about your pipeline be useful?\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    },
    {
      "delay_days": 3,
      "variants": [
        {
          "subject": "Following up",
          "body": "Hello,\n\nA quick follow up on my note. If outbound is not a priority this quarter, tell me and I will stop writing.\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    }
  ]
}
```

### Response

Status 201 Created.

```json
{
  "id": "cmp_2LmQx7RtVw3ZbN1pEs9fKd",
  "name": "Q4 outbound to software teams",
  "status": "draft",
  "timezone": "America/New_York",
  "pause_reason": null,
  "pause_origin": null,
  "steps": [
    {
      "delay_days": 0,
      "variants": [
        {
          "subject": "Outbound without the busywork",
          "body": "Hello,\n\nWe run outbound for B2B software teams, from sending domains to booked calls. Would a short call about your pipeline be useful?\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    },
    {
      "delay_days": 3,
      "variants": [
        {
          "subject": "Following up",
          "body": "Hello,\n\nA quick follow up on my note. If outbound is not a priority this quarter, tell me and I will stop writing.\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    }
  ],
  "created_at": "2026-10-17T12:00:00.000Z",
  "launched_at": null
}
```

- Every `body` must contain both `{{unsubscribe}}` and `{{sender_address}}`. The first step has `delay_days` 0 and later steps wait at least 1 day.
- A subject that starts with `Re:` or `Fwd:` is refused, because it pretends to continue an earlier thread.

### Errors

- [`unauthorized`](https://coldmeetings.com/docs/errors.md#unauthorized), HTTP 401: The API key is missing, malformed, revoked or unknown.
- [`invalid_input`](https://coldmeetings.com/docs/errors.md#invalid_input), HTTP 400: The sequence breaks a rule. The message lists every problem. A body that is empty, is not JSON or fails validation also answers this, and the message names the field.
- [`payload_too_large`](https://coldmeetings.com/docs/errors.md#payload_too_large), HTTP 413: The body is over 256 KiB.
- [`rate_limited`](https://coldmeetings.com/docs/errors.md#rate_limited), HTTP 429: Too many requests for this key. Wait the number of seconds in `Retry-After`.

### Example request

```bash
curl -X POST YOUR_API_BASE_URL/v1/campaigns \
  -H "Authorization: Bearer $COLDMEETINGS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Q4 outbound to software teams",
  "timezone": "America/New_York",
  "steps": [
    {
      "delay_days": 0,
      "variants": [
        {
          "subject": "Outbound without the busywork",
          "body": "Hello,\n\nWe run outbound for B2B software teams, from sending domains to booked calls. Would a short call about your pipeline be useful?\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    },
    {
      "delay_days": 3,
      "variants": [
        {
          "subject": "Following up",
          "body": "Hello,\n\nA quick follow up on my note. If outbound is not a priority this quarter, tell me and I will stop writing.\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    }
  ]
}'
```

## GET /v1/campaigns/{id}

One campaign.

Authentication: send your API key as a bearer token. See [Authentication](https://coldmeetings.com/docs/authentication.md).

### Path parameters

| Name | Type | Notes |
| --- | --- | --- |
| `id` | string | Id of the campaign. |

### Response

Status 200 OK.

```json
{
  "id": "cmp_2LmQx7RtVw3ZbN1pEs9fKd",
  "name": "Q4 outbound to software teams",
  "status": "draft",
  "timezone": "America/New_York",
  "pause_reason": null,
  "pause_origin": null,
  "steps": [
    {
      "delay_days": 0,
      "variants": [
        {
          "subject": "Outbound without the busywork",
          "body": "Hello,\n\nWe run outbound for B2B software teams, from sending domains to booked calls. Would a short call about your pipeline be useful?\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    },
    {
      "delay_days": 3,
      "variants": [
        {
          "subject": "Following up",
          "body": "Hello,\n\nA quick follow up on my note. If outbound is not a priority this quarter, tell me and I will stop writing.\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    }
  ],
  "created_at": "2026-10-17T12:00:00.000Z",
  "launched_at": null
}
```

### Errors

- [`unauthorized`](https://coldmeetings.com/docs/errors.md#unauthorized), HTTP 401: The API key is missing, malformed, revoked or unknown.
- [`unknown_product`](https://coldmeetings.com/docs/errors.md#unknown_product), HTTP 404: No such campaign on this account.
- [`rate_limited`](https://coldmeetings.com/docs/errors.md#rate_limited), HTTP 429: Too many requests for this key. Wait the number of seconds in `Retry-After`.

### Example request

```bash
curl YOUR_API_BASE_URL/v1/campaigns/cmp_2LmQx7RtVw3ZbN1pEs9fKd \
  -H "Authorization: Bearer $COLDMEETINGS_API_KEY"
```

## POST /v1/campaigns/{id}/prospects

Import prospects: dedupe, suppression, region gate, verification, one credit each.

Each prospect that is imported costs one prospect credit. Skipped prospects cost nothing.

Authentication: send your API key as a bearer token. See [Authentication](https://coldmeetings.com/docs/authentication.md).

> This operation answers 503 `provider_unavailable` when its outside service cannot be reached. The email verification service could not be reached. The credit hold is released and nothing is charged. Nothing is simulated and nothing is charged.

### Path parameters

| Name | Type | Notes |
| --- | --- | --- |
| `id` | string | Id of the campaign. |

### Request body

Send a JSON object.

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `allow_risky` | boolean | No | Also import role mailboxes and free-provider addresses. Default `false`. |
| `prospects` | array of object | Yes | 1 to 500 items. |
| `prospects[].email` | string | Yes | An email address. It is trimmed and lowercased. Up to 254 characters. |
| `prospects[].first_name` | string | No | Up to 80 characters. |
| `prospects[].company` | string | No | Up to 120 characters. |
| `prospects[].country` | string | Yes | ISO 3166-1 alpha-2 country of the prospect. Required: it decides region gating. Exactly 2 characters. |

Example body:

```json
{
  "allow_risky": false,
  "prospects": [
    {
      "email": "jordan@northwind.example",
      "first_name": "Jordan",
      "company": "Northwind",
      "country": "US"
    },
    {
      "email": "sam@contoso.example",
      "first_name": "Sam",
      "company": "Contoso",
      "country": "CA"
    },
    {
      "email": "lena@fabrikam.example",
      "first_name": "Lena",
      "company": "Fabrikam",
      "country": "DE"
    }
  ]
}
```

### Response

Status 201 Created.

```json
{
  "imported": 2,
  "skipped": [
    {
      "email": "lena@fabrikam.example",
      "reason": "region_blocked"
    }
  ],
  "credits_charged": 2,
  "credits_remaining": 9848
}
```

- `skipped[].reason` is one of `invalid_email`, `duplicate_in_request`, `region_blocked`, `suppressed`, `already_imported`, `suppressed_or_already_imported`, or a verification verdict such as `invalid: domain accepts no mail`.
- Prospects in the EU, UK and Israel are skipped as `region_blocked`.
- `risky` addresses (role mailboxes and free providers) are skipped unless you send `allow_risky: true`.
- Credits are held while the import runs and charged only for prospects that were really imported. A failed request releases the hold.

### Errors

- [`unauthorized`](https://coldmeetings.com/docs/errors.md#unauthorized), HTTP 401: The API key is missing, malformed, revoked or unknown.
- [`invalid_input`](https://coldmeetings.com/docs/errors.md#invalid_input), HTTP 400: The campaign is not a draft, or the body is invalid. A body that is empty, is not JSON or fails validation also answers this, and the message names the field.
- [`payload_too_large`](https://coldmeetings.com/docs/errors.md#payload_too_large), HTTP 413: The body is over 256 KiB.
- [`unknown_product`](https://coldmeetings.com/docs/errors.md#unknown_product), HTTP 404: No such campaign on this account.
- [`insufficient_credits`](https://coldmeetings.com/docs/errors.md#insufficient_credits), HTTP 402: The import needs more credits than the account has. Nothing is imported or charged.
- [`provider_unavailable`](https://coldmeetings.com/docs/errors.md#provider_unavailable), HTTP 503: Verification could not be reached. Nothing is charged.
- [`rate_limited`](https://coldmeetings.com/docs/errors.md#rate_limited), HTTP 429: Too many requests for this key. Wait the number of seconds in `Retry-After`.

### Example request

```bash
curl -X POST YOUR_API_BASE_URL/v1/campaigns/cmp_2LmQx7RtVw3ZbN1pEs9fKd/prospects \
  -H "Authorization: Bearer $COLDMEETINGS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "allow_risky": false,
  "prospects": [
    {
      "email": "jordan@northwind.example",
      "first_name": "Jordan",
      "company": "Northwind",
      "country": "US"
    },
    {
      "email": "sam@contoso.example",
      "first_name": "Sam",
      "company": "Contoso",
      "country": "CA"
    },
    {
      "email": "lena@fabrikam.example",
      "first_name": "Lena",
      "company": "Fabrikam",
      "country": "DE"
    }
  ]
}'
```

## GET /v1/campaigns/{id}/preflight

Everything that still blocks launch.

Lists everything that still blocks a launch. `ready` is `true` when `blockers` is empty.

Authentication: send your API key as a bearer token. See [Authentication](https://coldmeetings.com/docs/authentication.md).

### Path parameters

| Name | Type | Notes |
| --- | --- | --- |
| `id` | string | Id of the campaign. |

### Response

Status 200 OK.

```json
{
  "ready": false,
  "blockers": [
    "The campaign has no prospects. Import some first.",
    "No mailbox sits on a domain with verified SPF, DKIM and DMARC."
  ]
}
```

### Errors

- [`unauthorized`](https://coldmeetings.com/docs/errors.md#unauthorized), HTTP 401: The API key is missing, malformed, revoked or unknown.
- [`unknown_product`](https://coldmeetings.com/docs/errors.md#unknown_product), HTTP 404: No such campaign on this account.
- [`rate_limited`](https://coldmeetings.com/docs/errors.md#rate_limited), HTTP 429: Too many requests for this key. Wait the number of seconds in `Retry-After`.

### Example request

```bash
curl YOUR_API_BASE_URL/v1/campaigns/cmp_2LmQx7RtVw3ZbN1pEs9fKd/preflight \
  -H "Authorization: Bearer $COLDMEETINGS_API_KEY"
```

## POST /v1/campaigns/{id}/launch

Launch through the sending engine.

Runs the same checks as preflight, then hands the campaign to the sending engine.

Authentication: send your API key as a bearer token. See [Authentication](https://coldmeetings.com/docs/authentication.md).

> This operation answers 503 `provider_unavailable` when its outside service cannot be reached. The sending engine could not be reached. The campaign stays a draft. Nothing is simulated and nothing is charged.

### Path parameters

| Name | Type | Notes |
| --- | --- | --- |
| `id` | string | Id of the campaign. |

### Response

Status 200 OK.

```json
{
  "id": "cmp_2LmQx7RtVw3ZbN1pEs9fKd",
  "name": "Q4 outbound to software teams",
  "status": "active",
  "timezone": "America/New_York",
  "pause_reason": null,
  "pause_origin": null,
  "steps": [
    {
      "delay_days": 0,
      "variants": [
        {
          "subject": "Outbound without the busywork",
          "body": "Hello,\n\nWe run outbound for B2B software teams, from sending domains to booked calls. Would a short call about your pipeline be useful?\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    },
    {
      "delay_days": 3,
      "variants": [
        {
          "subject": "Following up",
          "body": "Hello,\n\nA quick follow up on my note. If outbound is not a priority this quarter, tell me and I will stop writing.\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    }
  ],
  "created_at": "2026-10-17T12:00:00.000Z",
  "launched_at": "2026-10-17T12:00:00.000Z"
}
```

### Errors

- [`unauthorized`](https://coldmeetings.com/docs/errors.md#unauthorized), HTTP 401: The API key is missing, malformed, revoked or unknown.
- [`unknown_product`](https://coldmeetings.com/docs/errors.md#unknown_product), HTTP 404: No such campaign on this account.
- [`invalid_input`](https://coldmeetings.com/docs/errors.md#invalid_input), HTTP 400: Preflight found blockers. The message lists them.
- [`provider_unavailable`](https://coldmeetings.com/docs/errors.md#provider_unavailable), HTTP 503: The sending engine could not be reached. The campaign stays a draft.
- [`rate_limited`](https://coldmeetings.com/docs/errors.md#rate_limited), HTTP 429: Too many requests for this key. Wait the number of seconds in `Retry-After`.

### Example request

```bash
curl -X POST YOUR_API_BASE_URL/v1/campaigns/cmp_2LmQx7RtVw3ZbN1pEs9fKd/launch \
  -H "Authorization: Bearer $COLDMEETINGS_API_KEY"
```

## POST /v1/campaigns/{id}/pause

Pause a campaign. Always pauses locally, even when the engine is unreachable; an unconfirmed engine pause is retried until it succeeds.

The campaign is paused here first, even when the sending engine cannot be reached. A pause the engine has not confirmed is retried until it does, and the campaign cannot be resumed meanwhile. A background job checks every 5 minutes for retries that are due. Attempts wait 5 minutes, 30 minutes, 2 hours, 6 hours and then 12 hours; when the last attempt fails, an operator is told.

Authentication: send your API key as a bearer token. See [Authentication](https://coldmeetings.com/docs/authentication.md).

### Path parameters

| Name | Type | Notes |
| --- | --- | --- |
| `id` | string | Id of the campaign. |

### Response

Status 200 OK.

```json
{
  "id": "cmp_2LmQx7RtVw3ZbN1pEs9fKd",
  "name": "Q4 outbound to software teams",
  "status": "paused",
  "timezone": "America/New_York",
  "pause_reason": "paused by customer",
  "pause_origin": "customer",
  "steps": [
    {
      "delay_days": 0,
      "variants": [
        {
          "subject": "Outbound without the busywork",
          "body": "Hello,\n\nWe run outbound for B2B software teams, from sending domains to booked calls. Would a short call about your pipeline be useful?\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    },
    {
      "delay_days": 3,
      "variants": [
        {
          "subject": "Following up",
          "body": "Hello,\n\nA quick follow up on my note. If outbound is not a priority this quarter, tell me and I will stop writing.\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    }
  ],
  "created_at": "2026-10-17T12:00:00.000Z",
  "launched_at": "2026-10-17T12:00:00.000Z",
  "engine": {
    "status": "paused"
  }
}
```

- `engine.status` is `paused`, `not_launched` for a draft, or `unavailable` with a `message` when the engine could not be told yet.

### Errors

- [`unauthorized`](https://coldmeetings.com/docs/errors.md#unauthorized), HTTP 401: The API key is missing, malformed, revoked or unknown.
- [`unknown_product`](https://coldmeetings.com/docs/errors.md#unknown_product), HTTP 404: No such campaign on this account.
- [`rate_limited`](https://coldmeetings.com/docs/errors.md#rate_limited), HTTP 429: Too many requests for this key. Wait the number of seconds in `Retry-After`.

### Example request

```bash
curl -X POST YOUR_API_BASE_URL/v1/campaigns/cmp_2LmQx7RtVw3ZbN1pEs9fKd/pause \
  -H "Authorization: Bearer $COLDMEETINGS_API_KEY"
```

## POST /v1/campaigns/{id}/resume

Resume a campaign you paused. Runs the preflight, removes suppressed leads at the sending engine, then restarts it. Refused while the engine has not confirmed the pause (409), and for a campaign ColdMeetings paused itself (403).

Starts a campaign you paused sending again. Before anything starts, the preflight runs and every address you have suppressed since is removed from the campaign's leads at the sending engine; if the engine does not confirm, nothing starts. A campaign that ColdMeetings paused itself, for example for spam complaints, cannot be resumed with this request. Only an operator can resume it, and only once the 7-day cooldown has passed since the pause.

Authentication: send your API key as a bearer token. See [Authentication](https://coldmeetings.com/docs/authentication.md).

### Path parameters

| Name | Type | Notes |
| --- | --- | --- |
| `id` | string | Id of the campaign. |

### Response

Status 200 OK.

```json
{
  "id": "cmp_2LmQx7RtVw3ZbN1pEs9fKd",
  "name": "Q4 outbound to software teams",
  "status": "active",
  "timezone": "America/New_York",
  "pause_reason": null,
  "pause_origin": null,
  "steps": [
    {
      "delay_days": 0,
      "variants": [
        {
          "subject": "Outbound without the busywork",
          "body": "Hello,\n\nWe run outbound for B2B software teams, from sending domains to booked calls. Would a short call about your pipeline be useful?\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    },
    {
      "delay_days": 3,
      "variants": [
        {
          "subject": "Following up",
          "body": "Hello,\n\nA quick follow up on my note. If outbound is not a priority this quarter, tell me and I will stop writing.\n\n{{sender_address}}\n{{unsubscribe}}"
        }
      ]
    }
  ],
  "created_at": "2026-10-17T12:00:00.000Z",
  "launched_at": "2026-10-17T12:00:00.000Z"
}
```

- `pause_reason` and `pause_origin` (`customer` or `system`) show why a paused campaign is paused.

### Errors

- [`unauthorized`](https://coldmeetings.com/docs/errors.md#unauthorized), HTTP 401: The API key is missing, malformed, revoked or unknown.
- [`unknown_product`](https://coldmeetings.com/docs/errors.md#unknown_product), HTTP 404: No such campaign on this account.
- [`invalid_input`](https://coldmeetings.com/docs/errors.md#invalid_input), HTTP 400: The campaign is not a paused campaign that was launched, or the preflight found blockers (the message lists them).
- [`forbidden`](https://coldmeetings.com/docs/errors.md#forbidden), HTTP 403: ColdMeetings paused this campaign itself, for example for spam complaints. Only an operator can lift that pause, and only after the 7-day cooldown.
- [`conflict`](https://coldmeetings.com/docs/errors.md#conflict), HTTP 409: The engine has not confirmed the campaign's pause yet, or the plan's active campaigns are all in use.
- [`provider_unavailable`](https://coldmeetings.com/docs/errors.md#provider_unavailable), HTTP 503: The sending engine could not remove suppressed leads or start the campaign. Nothing was started and the campaign stays paused.
- [`rate_limited`](https://coldmeetings.com/docs/errors.md#rate_limited), HTTP 429: Too many requests for this key. Wait the number of seconds in `Retry-After`.

### Example request

```bash
curl -X POST YOUR_API_BASE_URL/v1/campaigns/cmp_2LmQx7RtVw3ZbN1pEs9fKd/resume \
  -H "Authorization: Bearer $COLDMEETINGS_API_KEY"
```

## GET /v1/campaigns/{id}/report

Sent, bounce, complaint and reply rates, reply intents, meetings booked.

Authentication: send your API key as a bearer token. See [Authentication](https://coldmeetings.com/docs/authentication.md).

### Path parameters

| Name | Type | Notes |
| --- | --- | --- |
| `id` | string | Id of the campaign. |

### Response

Status 200 OK.

```json
{
  "campaign": {
    "id": "cmp_2LmQx7RtVw3ZbN1pEs9fKd",
    "name": "Q4 outbound to software teams",
    "status": "active",
    "timezone": "America/New_York",
    "pause_reason": null,
    "pause_origin": null,
    "steps": [
      {
        "delay_days": 0,
        "variants": [
          {
            "subject": "Outbound without the busywork",
            "body": "Hello,\n\nWe run outbound for B2B software teams, from sending domains to booked calls. Would a short call about your pipeline be useful?\n\n{{sender_address}}\n{{unsubscribe}}"
          }
        ]
      },
      {
        "delay_days": 3,
        "variants": [
          {
            "subject": "Following up",
            "body": "Hello,\n\nA quick follow up on my note. If outbound is not a priority this quarter, tell me and I will stop writing.\n\n{{sender_address}}\n{{unsubscribe}}"
          }
        ]
      }
    ],
    "created_at": "2026-10-17T12:00:00.000Z",
    "launched_at": "2026-10-17T12:00:00.000Z"
  },
  "prospects": 2,
  "sent": 120,
  "bounces": 2,
  "complaints": 0,
  "replies": 6,
  "bounce_rate": 0.0167,
  "reply_rate": 0.05,
  "spam_rate": 0,
  "reply_intents": {
    "interested": 2,
    "not_interested": 3,
    "opt_out": 1
  },
  "meetings_booked": 1
}
```

- The rates are `null` until at least one send is recorded. They are fractions, so `0.05` is five percent.

### Errors

- [`unauthorized`](https://coldmeetings.com/docs/errors.md#unauthorized), HTTP 401: The API key is missing, malformed, revoked or unknown.
- [`unknown_product`](https://coldmeetings.com/docs/errors.md#unknown_product), HTTP 404: No such campaign on this account.
- [`rate_limited`](https://coldmeetings.com/docs/errors.md#rate_limited), HTTP 429: Too many requests for this key. Wait the number of seconds in `Retry-After`.

### Example request

```bash
curl YOUR_API_BASE_URL/v1/campaigns/cmp_2LmQx7RtVw3ZbN1pEs9fKd/report \
  -H "Authorization: Bearer $COLDMEETINGS_API_KEY"
```

## Related

- [API reference](https://coldmeetings.com/docs/api.md)
- [Errors](https://coldmeetings.com/docs/errors.md)
