POST /api/v1/sequences/{sequenceId}/versions/{versionId}/publish
Congela el borrador, le pone fecha y apunta la secuencia hacia él. Es el único momento en que se comprueba el grafo, y el único momento en que tiene consecuencias.
Qué significa una publicación rechazada
Cada defecto responde400, se nombra a sí mismo y nombra los nodos implicados, todos a la vez, para que corrijas en una sola pasada en lugar de volver a publicar para descubrir el siguiente.
| Defecto | Qué significa | Cómo corregirlo |
|---|---|---|
| vacía | La versión no tiene ningún nodo | Añade al menos un nodo |
| sin entrada | Todos los nodos tienen algo que apunta a ellos: no hay forma de entrar | Elimina la conexión que cierra el bucle arriba |
| varias entradas | Dos nodos no tienen nada que apunte a ellos | Conecta uno detrás del otro; un recorrido tiene una sola puerta |
| ciclo | Las conexiones vuelven sobre sí mismas: un contacto daría vueltas para siempre | Elimina la conexión que va hacia atrás |
| huérfano | Un nodo es inalcanzable desde la entrada | Conéctalo, o elimínalo |
| rama colgante | Una rama no lleva a ninguna parte | Conecta su final, o quita la rama |
| rama ambigua | Un nodo tiene dos conexiones de salida sin forma de elegir | Conserva una sola conexión |
| conexión fuera del grafo | Una conexión apunta a un nodo de otra versión | Elimina esa conexión y reconecta dentro de esta versión |
| envío vacío | Un nodo send_email no tiene asunto o no tiene contenido | Haz PATCH del nodo con un asunto y HTML |
| acción incompleta | Un nodo add_tag / remove_tag no tiene etiqueta | Haz PATCH del nodo con un tagId |
| fin con sucesor | Un nodo end_sequence tiene un nodo detrás | Elimina lo que sigue: nada se ejecuta después del fin |
| webhook no válido | Un nodo webhook no tiene URL, o tiene una que la política rechaza | Haz PATCH del nodo con una URL pública https:// |
400: una versión publicada es una instantánea, y volver a publicarla en el sitio reescribiría lo que están recorriendo los contactos. Usa la reversión en su lugar.
Autorización
| Rol en la organización | Este endpoint |
|---|---|
OWNER | Permitido |
ADMIN | Permitido |
MEMBER | Rechazado — 403 |
Ejemplo
bash
curl -X POST -H "x-api-key: $AGENTMAIL_API_KEY" \
"https://www.agentsmail.io/api/v1/sequences/$SEQUENCE_ID/versions/$VERSION_ID/publish"Respuesta
200 OK: la llamada tuvo éxito.401 Unauthorized: clave ausente o no válida, o su propietario dejó la organización.403 Forbidden: el propietario de la clave esmemberde la organización, noadmin.404 Not Found: no existe ese recurso, o pertenece a otra organización. La API nunca confirma que un id existe a quien no tiene derecho sobre él.429 Too Many Requests: más de 120 solicitudes en un minuto para esta clave.
Campos de la respuesta
| Campo | Tipo | Descripción |
|---|---|---|
success | boolean | Indica si la operación tuvo éxito |
data.id | string | Identificador único de la versión |
data.sequenceId | string | La secuencia a la que pertenece |
data.version | number | Su número de orden, empezando por 1 |
data.status | string | draft o published |
data.publishedAt | string | null |
data.triggerType | string | list_joined o tag_added |
data.triggerTargetId | string | La lista o etiqueta que inscribe contactos |
data.createdAt | string | Fecha ISO de creación |
data.updatedAt | string | Fecha ISO del último cambio |
Ejemplo de respuesta
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"
}
}Receta para agentes
Construye el grafo con libertad y luego lee el rechazo: la validación ocurre al publicar, no en cada edición. Un400 aquí es el grafo siendo rechazado, no 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` nombra los pasos con defectos: corrige el borrador y vuelve a publicar
return repairDraft(details ?? error)
}
// Nada se ejecuta hasta que la propia secuencia está activa
await fetch(`${base}/sequences/${sequenceId}`, {
method: 'PATCH',
headers: {...headers, 'content-type': 'application/json'},
body: JSON.stringify({status: 'active'}),
})