Publier une version

POST /api/v1/sequences/{sequenceId}/versions/{versionId}/publish Fige le brouillon, le date et fait pointer la séquence vers lui. C'est le seul moment où le graphe est vérifié, et le seul moment où il a des conséquences.

Ce que signifie une publication refusée

Chaque défaut répond 400, se nomme lui-même, et nomme les nœuds concernés — tous à la fois, pour que vous corrigiez en une seule passe au lieu de republier pour découvrir le suivant.
DéfautCe que cela signifieComment le corriger
emptyLa version n'a aucun nœudAjoutez au moins un nœud
no entryChaque nœud a quelque chose qui pointe vers lui — il n'y a aucune entréeSupprimez la liaison qui ferme la boucle en haut
multiple entriesDeux nœuds n'ont rien qui pointe vers euxReliez l'un derrière l'autre ; un parcours n'a qu'une porte
cycleLes liaisons reviennent sur elles-mêmes — un contact tournerait en boucle indéfinimentSupprimez la liaison qui revient en arrière
orphanUn nœud est inaccessible depuis l'entréeReliez-le, ou supprimez-le
dangling branchUne branche ne mène nulle partReliez son extrémité, ou abandonnez la branche
ambiguous branchUn nœud a deux liaisons sortantes sans moyen de choisirGardez une seule liaison
edge out of graphUne liaison pointe vers un nœud d'une autre versionSupprimez cette liaison et recâblez à l'intérieur de cette version
empty sendUn nœud send_email n'a pas d'objet ou pas de contenuFaites un PATCH du nœud avec un objet et du HTML
incomplete actionUn nœud add_tag / remove_tag n'a pas de tagFaites un PATCH du nœud avec un tagId
end with successorUn nœud end_sequence est suivi d'un autre nœudSupprimez ce qui suit : rien ne s'exécute après la fin
invalid webhookUn nœud webhook n'a pas d'URL, ou une URL que la politique refuseFaites un PATCH du nœud avec une URL publique https://
Une version qui n'est pas un brouillon répond aussi 400 : une version publiée est un instantané, la republier sur place réécrirait ce que les contacts sont en train de parcourir. Utilisez plutôt le retour arrière.

Autorisation

Rôle dans l'organisationCet endpoint
OWNERAutorisé
ADMINAutorisé
MEMBERRefusé — 403
Une clé porte le rôle que son créateur détient dans cette organisation — jamais un rôle sur AgentsMail lui-même. Voir Clés d'API.

Exemple

bash
curl -X POST -H "x-api-key: $AGENTMAIL_API_KEY" \
  "https://www.agentsmail.io/api/v1/sequences/$SEQUENCE_ID/versions/$VERSION_ID/publish"

Réponse

  • 200 OK — l'appel a réussi.
  • 401 Unauthorized — clé absente ou invalide, ou son propriétaire a quitté l'organisation.
  • 403 Forbidden — le propriétaire de la clé est member de l'organisation, pas admin.
  • 404 Not Found — aucune ressource de ce type, ou elle appartient à une autre organisation. L'API ne confirme jamais l'existence d'un id à un appelant qui n'y a pas droit.
  • 429 Too Many Requests — plus de 120 requêtes en une minute pour cette clé.

Champs de la réponse

ChampTypeDescription
successbooleanIndique si l'opération a réussi
data.idstringIdentifiant unique de la version
data.sequenceIdstringLa séquence à laquelle elle appartient
data.versionnumberSon rang, à partir de 1
data.statusstringdraft ou published
data.publishedAtstringnull
data.triggerTypestringlist_joined ou tag_added
data.triggerTargetIdstringLa liste ou le tag qui inscrit les contacts
data.createdAtstringDate de création ISO
data.updatedAtstringDate ISO de la dernière modification

Exemple de réponse

json
{
  "success": true,
  "data": {
    "id": "4d19c0a2",
    "sequenceId": "9b3f2d10",
    "version": 1,
    "status": "subscribed",
    "publishedAt": "2026-08-23T10:22:05.000Z",
    "triggerType": "list_joined",
    "triggerTargetId": "0b7c51e8",
    "createdAt": "2026-08-23T10:22:05.000Z",
    "updatedAt": "2026-08-23T10:22:05.000Z"
  }
}

Recette pour agent

Construisez le graphe librement, puis lisez le refus : la validation a lieu à la publication, pas à chaque modification. Un 400 ici, c'est le graphe qui est refusé, pas un bug.
js
const publish = await fetch(
  `${base}/sequences/${sequenceId}/versions/${versionId}/publish`,
  {method: 'POST', headers}
)

if (publish.status === 400) {
  const {error, details} = await publish.json()
  // `details` nomme les étapes en défaut — corrigez le brouillon et publiez à nouveau
  return repairDraft(details ?? error)
}

// Rien ne s'exécute tant que la séquence elle-même n'est pas active
await fetch(`${base}/sequences/${sequenceId}`, {
  method: 'PATCH',
  headers: {...headers, 'content-type': 'application/json'},
  body: JSON.stringify({status: 'active'}),
})

Voir aussi