Passer au contenu principal

Endpoint

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

ChampTypeRequisDescription
instanceIdUUIDouiIdentifiant technique de l’instance MsgFlash, obtenu via GET /api/v1/instances
namestringouiNom interne
scheduleISO 8601ouiDate de démarrage
repeatstringnonnone, daily, weekly
recipientsobjectouiSélecteur de destinataires
templateIdUUIDoui si mode templateTemplate utilisé
variablesobjectnonVariables custom.* globales
typeenumoui si mode directtext, image, video, audio, document, voice_note, buttons
bodystringselon typeObligatoire pour text, optionnel pour certains médias
mediaUrlstringselon typeObligatoire pour les types média
titlestringsi buttonsTitre du message boutons
descriptionstringsi buttonsDescription du message boutons
footerstringnonPied de page du message boutons
buttonsarraysi buttonsListe 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

ChampTypeRequisDescription
typeenumouiall, tags, explicit, group
valuestring[]selon typeTags ou IDs de contacts
groupIdUUIDsi type=groupGroupe cible

Réponse succès 201

{
  "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"
  }
}
En V1, safety.decision vaut allow ou warn. Un warning n’empêche pas la création de la campagne.

Erreurs courantes

HTTPCodeQuand
400VALIDATION_ERRORCampagne vide, body manquant, media manquant, destinataires invalides
403CAMPAIGNS_NOT_AVAILABLE_ON_PLANPlan trop faible
403UNSUPPORTED_FEATUREFonctionnalité non supportée (boutons sans WhatsApp Business)
404NOT_FOUNDInstance ou template introuvable

Exemples

Campagne texte simple

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

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"
      }
    ]
  }'