# Run a campaign

A campaign sends one approved WhatsApp template to many contacts. It starts as a draft, you preview it, and launching freezes the recipient list.

## 1. Create the draft

```bash title="cURL"
curl https://api.lelemon.cl/v2/campaigns \
  -H "Authorization: Bearer $LELEMON_API_KEY" \
  -H "Idempotency-Key: cmp-bf-2026" \
  --json '{
    "name": "Black Friday",
    "templateId": "tpl_...",
    "audience": { "externalRefs": ["cust-88123", "cust-88124"] },
    "variables": { "name": "contact.name", "coupon": "BF26" },
    "schedule": { "at": "2026-11-27T10:00:00-03:00" }
  }'
```


`schedule` is required, and `schedule.at` is the only required field inside it: a date-time with its offset, or `"now"` to start as soon as you launch. A date in the past also starts at once. `schedule.window` limits sending to a daily time window, and `batchSize` (default 100, up to 1000) with `batchEveryMinutes` (default 15) control how fast it goes out. `audience` takes `contactFilter` or `externalRefs`. `variables` maps each template variable to `contact.name`, `contact.phone`, `contact.email`, `contact.externalRef` or a fixed value.

## 2. Preview before sending

```bash title="cURL"
curl -X POST https://api.lelemon.cl/v2/campaigns/cmp_.../preview \
  -H "Authorization: Bearer $LELEMON_API_KEY"
```


The preview shows who gets the message, who is skipped and why, a rendered sample and the estimated cost. The cost is `null` unless the server has WhatsApp prices configured.

## 3. Launch

```bash title="cURL"
curl -X POST https://api.lelemon.cl/v2/campaigns/cmp_.../launch \
  -H "Authorization: Bearer $LELEMON_API_KEY" \
  -H "Idempotency-Key: launch-cmp-bf-2026"
```


Launching freezes the recipient list. Lelemon sends in batches. A campaign has at most one message per contact, so restarting or repeating a batch never sends twice to the same person. Use `/pause`, `/resume` and `/cancel` to control it.

## 4. Follow it

```bash title="cURL"
curl "https://api.lelemon.cl/v2/campaigns/cmp_.../recipients?limit=100" \
  -H "Authorization: Bearer $LELEMON_API_KEY"
```


`GET /v2/campaigns/{id}` shows `counts`: how many recipients are pending, queued, sent, delivered, read, failed or skipped, and `replied`, the recipients whose contact wrote back after the message, counted once each. `replied` is not a status, so a recipient can be read and replied at the same time.

If a contact answers, the agent in `onReply` continues. Contacts who tap the opt-out button are opted out and skipped from then on.
