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

# Create, Schedule, and Send Messaging Campaigns in Zexa

> Build and launch broadcast campaigns to your contact lists across SMS, WhatsApp, Telegram, Email, and Slack, with delivery analytics and scheduling.

A campaign in Zexa lets you send one message to hundreds or thousands of recipients at once. You pick the channel, choose a contact list, compose your message, and Zexa handles delivery and tracking.

## Create a campaign

<Steps>
  <Step title="Open New Campaign">
    In the [Zexa dashboard](https://app.zexa.ao), go to **Campaigns** > **New Campaign**.
  </Step>

  <Step title="Choose a channel">
    Select the delivery channel for this campaign: **SMS**, **WhatsApp**, **Telegram**, **Email**, or **Slack**.
  </Step>

  <Step title="Select a contact list">
    Pick an existing contact list or upload a new CSV file. Zexa will count the eligible recipients before you send.
  </Step>

  <Step title="Compose your message">
    Write your message body. If you selected **WhatsApp**, choose an approved template instead of typing freeform text. See [Templates](/messaging/templates) for details.
  </Step>

  <Step title="Set a Sender ID">
    Choose the Sender ID that recipients will see in the **From** field. The Sender ID must already be approved for the selected channel. See [Sender IDs](/messaging/sender-ids).
  </Step>

  <Step title="Schedule or send immediately">
    Optionally set a future send time using the date/time picker, or click **Send Now** to dispatch the campaign immediately.
  </Step>

  <Step title="Monitor the campaign report">
    After sending, open the campaign report to track delivery, failures, and opt-outs in real time.
  </Step>
</Steps>

## Campaign via API

Send a `POST` request to `/campaigns` to create and launch a campaign programmatically.

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
    --url https://api.zexa.ao/v1/campaigns \
    --header "Authorization: Bearer <api_key>" \
    --header "Content-Type: application/json" \
    --data '{
      "name": "June Promo",
      "channel": "sms",
      "contact_list_id": "lst_abc123",
      "sender_id": "ZEXA",
      "body": "Enjoy 20% off this weekend! Reply STOP to opt out.",
      "scheduled_at": null
    }'
  ```

  ```python python theme={null}
  import requests

  url = "https://api.zexa.ao/v1/campaigns"
  headers = {
      "Authorization": "Bearer <api_key>",
      "Content-Type": "application/json",
  }
  payload = {
      "name": "June Promo",
      "channel": "sms",
      "contact_list_id": "lst_abc123",
      "sender_id": "ZEXA",
      "body": "Enjoy 20% off this weekend! Reply STOP to opt out.",
      "scheduled_at": None,
  }

  response = requests.post(url, json=payload, headers=headers)
  print(response.json())
  ```
</CodeGroup>

A successful response returns a campaign object:

```json theme={null}
{
  "id": "cmp_xyz789",
  "status": "processing",
  "name": "June Promo",
  "channel": "sms",
  "total_recipients": 1500,
  "created_at": "2026-06-24T10:00:00Z"
}
```

## Check campaign status

Retrieve the current status and delivery metrics for any campaign with a `GET` request:

```bash curl theme={null}
curl --request GET \
  --url https://api.zexa.ao/v1/campaigns/cmp_xyz789 \
  --header "Authorization: Bearer <api_key>"
```

```json theme={null}
{
  "id": "cmp_xyz789",
  "name": "June Promo",
  "status": "sent",
  "total_recipients": 1500,
  "delivered": 1463,
  "failed": 37,
  "created_at": "2026-06-24T10:00:00Z",
  "sent_at": "2026-06-24T10:02:15Z"
}
```

## Campaign statuses

| Status       | Description                                                                      |
| ------------ | -------------------------------------------------------------------------------- |
| `draft`      | The campaign has been created but not yet sent or scheduled.                     |
| `scheduled`  | The campaign is queued and will be dispatched at the time set in `scheduled_at`. |
| `processing` | Zexa is actively dispatching messages to recipients.                             |
| `sent`       | All messages have been submitted to the delivery network.                        |
| `failed`     | The campaign encountered a fatal error and could not be sent. Contact support.   |

## Scheduling

Set the `scheduled_at` field to an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) timestamp to delay dispatch:

```json theme={null}
{
  "scheduled_at": "2026-07-01T08:00:00Z"
}
```

All times are interpreted as **UTC**. Pass `null` for `scheduled_at` to send immediately. You can update a scheduled campaign's send time via `PATCH /campaigns/{id}` as long as its status is still `scheduled`.

<Tip>
  Always include an opt-out instruction in SMS campaign messages — for example, **"Reply STOP to unsubscribe."** This is a best practice in most markets and required by carriers in many regions.
</Tip>

<Warning>
  Campaigns cannot be cancelled or modified once their status changes to `processing`. Review your recipient list, message body, and Sender ID carefully before sending.
</Warning>

***

<CardGroup cols={3}>
  <Card title="Contacts" icon="address-book" href="/messaging/contacts">
    Import and manage the contact lists you target in campaigns.
  </Card>

  <Card title="Sender IDs" icon="id-badge" href="/messaging/sender-ids">
    Register and get approval for the name shown to your recipients.
  </Card>

  <Card title="Templates" icon="file-lines" href="/messaging/templates">
    Create pre-approved WhatsApp message templates for outbound campaigns.
  </Card>
</CardGroup>
