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

# Create SMS campaign

> POST /v1/sms/campaigns

Creates an SMS campaign. Optionally launches it immediately.

<Note>
  Campaigns are one-time broadcasts. Replies are handled by the agent using its `system_prompt` — include any campaign context in the agent's prompt before launching.
</Note>

## Request

```bash theme={null}
curl -X POST https://api.nixflex.com/v1/sms/campaigns \
  -H "Authorization: Bearer KEY_ID:KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agent_125207e452f8714a",
    "from_number": "+447446466847",
    "name": "March promotion",
    "message_template": "Hi {{first_name}}, 20% off cleanings this month at Acme Dental. Reply YES to book.",
    "recipients": [
      { "phone": "+447111000001", "variables": { "first_name": "Sarah" } },
      { "phone": "+447111000002", "variables": { "first_name": "James" } }
    ],
    "schedule_type": "now"
  }'
```

## Body parameters

| Field              | Type     | Required      | Notes                                              |
| ------------------ | -------- | ------------- | -------------------------------------------------- |
| `agent_id`         | string   | Yes           | Agent associated with the campaign                 |
| `from_number`      | string   | Yes           | Your imported Twilio number                        |
| `name`             | string   | Yes           | Display name in dashboard                          |
| `message_template` | string   | Yes           | Message text. Supports `{{variable}}` placeholders |
| `recipients`       | array    | Yes           | Up to 10,000. Each item: `{ phone, variables }`    |
| `schedule_type`    | enum     | Yes           | `now` or `schedule`                                |
| `scheduled_at`     | ISO date | If `schedule` | When to launch                                     |

### Recipient object

| Field       | Type   | Required | Notes                                                      |
| ----------- | ------ | -------- | ---------------------------------------------------------- |
| `phone`     | string | Yes      | E.164 format, e.g. `+447111000001`                         |
| `variables` | object | No       | Key-value pairs to fill `{{placeholders}}` in the template |

## Placeholders

Use `{{variable_name}}` in `message_template`. Each recipient's `variables` object fills them.

Template: `Hi {{first_name}}, see you on {{day}}.`

Recipient: `{ "phone": "+44...", "variables": { "first_name": "Sarah", "day": "Tuesday" } }`

Sent SMS: `Hi Sarah, see you on Tuesday.`

Missing variables render as empty strings (no crash).

## Response

`201 Created`:

```json theme={null}
{
  "campaign_id": "smsc_a1b2c3d4",
  "agent_id": "agent_125207e452f8714a",
  "name": "March promotion",
  "status": "running",
  "total_count": 2,
  "delivered_count": 0,
  "failed_count": 0,
  "pending_count": 2,
  "source": "api",
  "created_at": "2026-05-17T03:45:12Z"
}
```

When `schedule_type` is `now`, returns `status: running` and sends immediately. With `schedule`, returns `status: scheduled` — launch later with [Launch SMS campaign](/api-reference/sms/campaigns-launch).

## Errors

See [Errors](/reference/errors). Common: `agent_not_owned`, `from_number_not_owned`, `too_many_recipients`, `invalid_schedule`.
