# Campaign API (Coming soon)

>
> **Info:** **Coming soon.** The Campaign API is in preview and not yet wrapped by the SDKs. The shape below reflects the current API contract and may change before release.
>

A campaign calls a list of people with one agent: appointment reminders, lead qualification, surveys, renewals. You create the campaign, add contacts, and start it; the backend dials each contact from your number, runs the conversation, and works through the list at the concurrency you set.

## How it works

```mermaid
flowchart LR
  A["Create campaign<br/>agent + from number"] --> B["Add contacts<br/>number + instructions"]
  B --> C["Start"]
  C --> D{"Dial contacts<br/>up to concurrency"}
  D --> E["Agent holds<br/>each conversation"]
  E --> D
  C -. pause .-> P["Paused"]
  P -. start .-> D
  D --> F["Finished"]
```

- **One agent, many calls.** Every call uses the same stored agent, with its instructions, skills, knowledge and guardrail.
- **Per-contact context.** Each contact can carry instructions that are appended to the agent's prompt for that call only: the appointment time, the renewal date, the name to ask for.
- **Controlled pace.** `concurrency` caps how many calls are in progress at once. It defaults to one.
- **Pause and resume.** A campaign moves through `draft`, `running`, `paused` and `finished`.

## Preview of the API

| Endpoint                                  | Purpose                              |
| ----------------------------------------- | ------------------------------------ |
| `POST /v1/agents/campaigns`               | Create a campaign. `GET` lists them. |
| `GET /v1/agents/campaigns/{id}`           | Read a campaign and its progress.    |
| `POST /v1/agents/campaigns/{id}/contacts` | Add contacts to call.                |
| `POST /v1/agents/campaigns/{id}/start`    | Start or resume dialing.             |
| `POST /v1/agents/campaigns/{id}/pause`    | Stop placing new calls.              |

A campaign names the agent and the number people will see:

```json
{
  "name": "October renewals",
  "config_id": "cfg_renewals",
  "from_number": "+15125551234",
  "concurrency": 5,
  "tags": { "project": "renewals" }
}
```

Contacts are rung in the order they are added, each with optional instructions for that call:

```json
{
  "contacts": [
    {
      "to_number": "+15557654321",
      "instructions": "Ask for Dana. Her plan renews on October 12."
    },
    { "to_number": "+15557650000" }
  ]
}
```

Each contact moves through `pending`, `calling`, `done` or `failed`, and records its attempts, the call it became and, if it could not be rung, why.

## Get ready today

Everything a campaign needs already works:

1. [Create the agent](https://getstream.io/agents/docs/python/creating-an-agent/) that will make the calls, and test it with [simulations](https://getstream.io/agents/docs/python/simulations-and-evals/).
2. [Buy a number](https://getstream.io/agents/docs/python/telephony/purchase-number/) and try a single outbound call from the agent.
3. Add a [guardrail](https://getstream.io/agents/docs/python/guardrails/) so every call stays on script.

---

For the most recent version of this documentation, visit [https://getstream.io/agents/docs/python/campaign-api/](https://getstream.io/agents/docs/python/campaign-api/).