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

# Campaigns

> Create scheduled campaigns, track progress, and control execution.

## Endpoint

```txt theme={null}
POST /api/v1/campaigns
```

Authentication: `x-api-key: <api_key>`

<Warning>
  Campaigns require the Starter plan or higher.
</Warning>

## Main business rule

A campaign must include actual content to send.

Vous devez fournir :

* `name`
* `instanceId`
* `schedule`
* `recipients`

Et exactement un mode de contenu :

* soit `templateId`
* soit un message direct avec `type` + contenu associé

Creating an empty campaign is not allowed.

***

## Mode 1 — Template campaign

```bash theme={null}
curl -X POST https://srv.msgflash.com/api/v1/campaigns \
  -H "x-api-key: msgf_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "instanceId": "YOUR_INSTANCE_ID",
    "name": "Promo Black Friday",
    "schedule": "2026-04-02T10:00:00.000Z",
    "repeat": "noe",
    "templateId": "YOUR_TEMPLATE_ID",
    "variables": {
      "campaignName": "Black Friday"
    },
    "recipients": {
      "type": "all"
    }
  }'
```

## Mode 2 — Direct text campaign

```bash theme={null}
curl -X POST https://srv.msgflash.com/api/v1/campaigns \
  -H "x-api-key: msgf_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "instanceId": "YOUR_INSTANCE_ID",
    "name": "Relance panier",
    "schedule": "2026-04-02T10:00:00.000Z",
    "repeat": "noe",
    "type": "text",
    "body": "Hello, votre panier vous attend encore.",
    "recipients": {
      "type": "explicit",
      "value": ["CONTACT_UUID_1", "CONTACT_UUID_2"]
    }
  }'
```

## Mode 3 — Direct media campaign

```bash theme={null}
curl -X POST https://srv.msgflash.com/api/v1/campaigns \
  -H "x-api-key: msgf_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "instanceId": "YOUR_INSTANCE_ID",
    "name": "Promo visuelle",
    "schedule": "2026-04-02T10:00:00.000Z",
    "repeat": "noe",
    "type": "image",
    "body": "Découvrez notre offre de la semaine",
    "mediaUrl": "https://cdn.example.com/promo.jpg",
    "recipients": {
      "type": "all"
    }
  }'
```

***

## Recipients

<Tabs>
  <Tab title="Tous les contacts">
    ```json theme={null}
    {
      "recipients": {
        "type": "all"
      }
    }
    ```
  </Tab>

  <Tab title="Par tags">
    ```json theme={null}
    {
      "recipients": {
        "type": "tags",
        "value": ["vip", "newsletter"]
      }
    }
    ```
  </Tab>

  <Tab title="List explicite">
    ```json theme={null}
    {
      "recipients": {
        "type": "explicit",
        "value": ["CONTACT_UUID_1", "CONTACT_UUID_2"]
      }
    }
    ```
  </Tab>
</Tabs>

<Note>
  For `tags`, at least one tag is required. For `explicit`, at least one contact is required.
</Note>

***

## Types directs supportés

| Type         | Required content                         |
| ------------ | ---------------------------------------- |
| `text`       | `body` obligatoire                       |
| `image`      | `mediaUrl` obligatoire, `body` optionnel |
| `video`      | `mediaUrl` obligatoire, `body` optionnel |
| `document`   | `mediaUrl` obligatoire, `body` optionnel |
| `audio`      | `mediaUrl` obligatoire                   |
| `voice_note` | `mediaUrl` obligatoire                   |

***

## Response à la création

```json theme={null}
{
  "data": {
    "id": "cmp_uuid",
    "instanceId": "inst_uuid",
    "templateId": "tmpl_uuid",
    "type": null,
    "body": null,
    "mediaUrl": null,
    "name": "Promo Black Friday",
    "schedule": "2026-04-02T10:00:00.000Z",
    "status": "scheduled",
    "recipients": { "type": "all" },
    "stats": {
      "planned": 0,
      "queued": 0,
      "sent": 0,
      "delivered": 0,
      "read": 0,
      "failed": 0,
      "cancelled": 0,
      "processingStartedAt": null,
      "lastEnqueuedAt": null,
      "completedAt": null,
      "cancelledAt": null
    }
  }
}
```

<Note>
  The response can include a `safety` block with `decision`, `riskLevel`, `reasons`, and `recommendations`. In V1, this guidance does not block the campaign.
</Note>

***

## Campaign statuses

| Status         | Description                          |
| -------------- | ------------------------------------ |
| `draft`        | Réservé à certains flux dashboard    |
| `scheduled`    | En attente de la date prévue         |
| `running`      | En cours d'exécution                 |
| `paused`       | Pause manuelle                       |
| `paused_quota` | Pause automatique pour quota         |
| `paused_plan`  | Pause automatique pour plan/features |
| `completed`    | Campaign completed                   |
| `cancelled`    | Campaign cancelled                   |
| `failed`       | Fatal error                          |

<Note>
  A campaign now automatically moves to `completed` when no `queued` messages remain.
</Note>

***

## Pauser et reprendre

```bash theme={null}
curl -X POST https://srv.msgflash.com/api/v1/campaigns/CAMPAIGN_ID/pause \
  -H "x-api-key: msgf_live_your_api_key_here"
```

```bash theme={null}
curl -X POST https://srv.msgflash.com/api/v1/campaigns/CAMPAIGN_ID/resume \
  -H "x-api-key: msgf_live_your_api_key_here"
```

These actions are valid only for compatible statuses.

`resume` can also return a `safety` block if the instance is still warming up or if the audience is riskier than recommended.

### Parameters path

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id`      | UUID | yes      | Campaign ID |

***

## Statistiques

```bash theme={null}
curl https://srv.msgflash.com/api/v1/campaigns/CAMPAIGN_ID/stats \
  -H "x-api-key: msgf_live_your_api_key_here"
```

```json theme={null}
{
  "data": {
    "campaignId": "cmp_uuid",
    "status": "running",
    "stats": {
      "total": 1000,
      "planned": 1000,
      "queued": 150,
      "sent": 600,
      "delivered": 580,
      "read": 420,
      "failed": 10,
      "cancelled": 5
    },
    "progressPercent": 85,
    "timeline": {
      "scheduledFor": "2026-04-02T10:00:00.000Z",
      "processingStartedAt": "2026-04-02T10:00:01.000Z",
      "lastEnqueuedAt": "2026-04-02T10:03:20.000Z",
      "completedAt": null,
      "cancelledAt": null,
      "lastActivityAt": "2026-04-02T10:04:12.000Z"
    },
    "startedAt": "2026-04-02T10:00:01.000Z",
    "estimatedCompletionAt": null
  }
}
```

### Parameters path

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id`      | UUID | yes      | Campaign ID |

### Sens des compteurs

| Field       | Description                                         |
| ----------- | --------------------------------------------------- |
| `planned`   | Total number of messages generated for the campaign |
| `queued`    | Messages encore en file                             |
| `sent`      | Messages transmis à WhatsApp                        |
| `delivered` | Messages confirmés livrés                           |
| `read`      | Messages lus                                        |
| `failed`    | Échecs hors annulations                             |
| `cancelled` | Messages marqués annulés                            |

***

## Retrieve a campaign

```bash theme={null}
curl https://srv.msgflash.com/api/v1/campaigns/CAMPAIGN_ID \
  -H "x-api-key: msgf_live_your_api_key_here"
```

### Parameters path

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id`      | UUID | yes      | Campaign ID |

## Common errors

| Code                              | HTTP | When                                                               |
| --------------------------------- | ---- | ------------------------------------------------------------------ |
| `VALIDATION_ERROR`                | 400  | Empty campaign, missing body, missing media, or invalid recipients |
| `CAMPAIGNS_NOT_AVAILABLE_ON_PLAN` | 403  | Plan trop faible                                                   |
| `NOT_FOUND`                       | 404  | Instance ou template not found                                     |
| `MONTHLY_OUTBOUND_QUOTA_EXCEEDED` | 429  | Quota exhausted                                                    |
