> ## 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.

# POST Créer une campagne

> Crée et programme une campagne d'envoi.

## Endpoint

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

## Important — comment obtenir `instanceId`

`instanceId` est obligatoire pour créer une campagne.

Pour l’obtenir :

1. appeler `GET /api/v1/instances`
2. choisir une instance avec `status = "connected"` si possible
3. récupérer `data[n].id`
4. envoyer cette valeur dans `instanceId`

Ne pas utiliser à la place :

* `name`
* `waNumber`

## Body

| Champ         | Type     | Requis               | Description                                                                      |
| ------------- | -------- | -------------------- | -------------------------------------------------------------------------------- |
| `instanceId`  | UUID     | oui                  | Identifiant technique de l'instance MsgFlash, obtenu via `GET /api/v1/instances` |
| `name`        | string   | oui                  | Nom interne                                                                      |
| `schedule`    | ISO 8601 | oui                  | Date de démarrage                                                                |
| `repeat`      | string   | non                  | `none`, `daily`, `weekly`                                                        |
| `recipients`  | object   | oui                  | Sélecteur de destinataires                                                       |
| `templateId`  | UUID     | oui si mode template | Template utilisé                                                                 |
| `variables`   | object   | non                  | Variables `custom.*` globales                                                    |
| `type`        | enum     | oui si mode direct   | `text`, `image`, `video`, `audio`, `document`, `voice_note`, `buttons`           |
| `body`        | string   | selon type           | Obligatoire pour `text`, optionnel pour certains médias                          |
| `mediaUrl`    | string   | selon type           | Obligatoire pour les types média                                                 |
| `title`       | string   | si `buttons`         | Titre du message boutons                                                         |
| `description` | string   | si `buttons`         | Description du message boutons                                                   |
| `footer`      | string   | non                  | Pied de page du message boutons                                                  |
| `buttons`     | array    | si `buttons`         | Liste des boutons (max 2)                                                        |

## Règle de contenu

Une campagne doit avoir exactement un mode de contenu :

* soit `templateId`
* soit `type` + contenu direct

Ne pas envoyer les deux en même temps.

### `recipients`

| Champ     | Type      | Requis          | Description                        |
| --------- | --------- | --------------- | ---------------------------------- |
| `type`    | enum      | oui             | `all`, `tags`, `explicit`, `group` |
| `value`   | string\[] | selon type      | Tags ou IDs de contacts            |
| `groupId` | UUID      | si `type=group` | Groupe cible                       |

## Réponse succès `201`

```json theme={null}
{
  "data": {
    "id": "cmp_uuid",
    "userId": "user_uuid",
    "instanceId": "inst_uuid",
    "name": "Newsletter Avril",
    "status": "scheduled",
    "templateId": "tmpl_uuid",
    "type": null,
    "body": null,
    "mediaUrl": null,
    "schedule": "2026-04-15T09:00:00.000Z",
    "repeat": "none",
    "recipients": {
      "type": "all"
    },
    "stats": {
      "planned": 0,
      "queued": 0,
      "sent": 0,
      "delivered": 0,
      "read": 0,
      "failed": 0,
      "cancelled": 0
    },
    "safety": {
      "decision": "warn",
      "riskLevel": "medium",
      "score": 56,
      "state": "warming",
      "reasons": [
        "This instance is still warming up and campaign pacing should stay gradual."
      ],
      "recommendations": [
        "Start with previously engaged contacts before scaling volume."
      ],
      "appliedLimits": {
        "maxCampaignRecipients": 100,
        "maxColdRatio": 0.4
      },
      "audience": {
        "totalRecipients": 120,
        "coldRatio": 0.625
      }
    },
    "createdAt": "2026-04-10T09:00:00.000Z",
    "updatedAt": "2026-04-10T09:00:00.000Z"
  }
}
```

<Note>
  En V1, `safety.decision` vaut `allow` ou `warn`. Un warning n'empêche pas la création de la campagne.
</Note>

## Erreurs courantes

| HTTP  | Code                              | Quand                                                                 |
| ----- | --------------------------------- | --------------------------------------------------------------------- |
| `400` | `VALIDATION_ERROR`                | Campagne vide, body manquant, media manquant, destinataires invalides |
| `403` | `CAMPAIGNS_NOT_AVAILABLE_ON_PLAN` | Plan trop faible                                                      |
| `403` | `UNSUPPORTED_FEATURE`             | Fonctionnalité non supportée (boutons sans WhatsApp Business)         |
| `404` | `NOT_FOUND`                       | Instance ou template introuvable                                      |

## Exemples

### Campagne texte simple

```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": "INSTANCE_UUID",
    "name": "Newsletter Avril",
    "schedule": "2026-04-15T09:00:00.000Z",
    "recipients": {
      "type": "all"
    },
    "type": "text",
    "body": "Découvrez nos nouvelles offres !"
  }'
```

### Campagne avec boutons

```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": "INSTANCE_UUID",
    "name": "Sondage satisfaction",
    "schedule": "2026-04-15T10:00:00.000Z",
    "recipients": {
      "type": "tags",
      "value": ["client"]
    },
    "type": "buttons",
    "title": "Votre avis compte !",
    "description": "Êtes-vous satisfait de nos services ?",
    "footer": "Répondez avant demain",
    "buttons": [
      {
        "type": "reply",
        "displayText": "Très satisfait",
        "id": "satisfied"
      },
      {
        "type": "reply",
        "displayText": "À améliorer",
        "id": "needs_improvement"
      }
    ]
  }'
```
