Disparar un flujo por la API
Un flujo es una automatización montada en el editor visual del panel: mensajes, preguntas, condiciones, esperas. El disparador API permite que tu sistema inicie ese flujo para un contacto en el momento justo — un pedido pagado, un lead que llegó desde el sitio, una factura vencida — sin montar cada mensaje en el código.
Preparar el flujo
- En el editor, añade el disparador API y conéctalo al primer paso.
- Opcionalmente, elige en el disparador el número que va a enviar.
- Publica y activa el flujo. El disparo usa siempre la versión publicada — un
disparador que solo existe en el borrador responde
422 flow_no_api_trigger.
El id del flujo aparece en el editor y en GET /flows.
Disparar
curl -X POST https://api.joinotify.com/flows/cm1fl0w000001/trigger \
-H 'Authorization: Bearer sk_live_xxx' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: pedido-1042-pagado' \
-d '{
"contact": { "phone": "+5541987111527" },
"data": { "pedido": "1042", "total": "$ 189,90" }
}'
{ "data": { "runId": "cm1run0000001", "replayed": false } }
- El contacto viene por
contact.idocontact.phone. Con el teléfono, un contacto que no existe se crea — y disparacontact.created. - Los datos de
dataquedan disponibles en el flujo como{{trigger.pedido}}, con un valor predeterminado opcional:{{trigger.cupon|sin cupón}}. - El número que envía es
phoneNumberId, si lo mandas; si no, el configurado en el disparador; si no, el número activo más antiguo de la cuenta.
La respuesta llega antes que los mensajes: el flujo se ejecuta justo después, fuera de la solicitud.
runId: null no es un errorOcurre cuando el disparador no está conectado a ningún paso, o cuando el mismo contacto empezó este flujo hace unos instantes — hay un intervalo mínimo entre ejecuciones, para que un evento duplicado en tu sistema no envíe todo dos veces.
Empezar una ejecución cancela las otras en curso del mismo contacto en ese número, en cualquier flujo. Un contacto conversa con un flujo a la vez.
Reintentar sin duplicar
Con Idempotency-Key, repetir el disparo en hasta 24 horas devuelve 200 con el mismo
runId y replayed: true, sin empezar otra ejecución. Dos diferencias con
POST /messages:
- el cuerpo no se compara — la misma clave devuelve la misma ejecución, aunque cambie
data; - una llamada que falló (flujo inactivo, número inválido) no guarda la clave, y la repetición vuelve a intentarlo.
Lo que se comprueba después
El disparo acepta la solicitud; las reglas de envío valen cuando sale cada mensaje:
- una plantilla de marketing para un contacto dado de baja o en la lista de supresión
termina la ejecución con el motivo
contact_opted_out; - un mensaje libre con la ventana de 24 horas cerrada termina con
window_closed, salvo que el paso tenga una plantilla de respaldo configurada; - si la cuenta pierde el derecho de uso por el camino, la ejecución se detiene con
billing.
Seguir el resultado
Suscríbete a dos eventos en tu endpoint de webhooks:
| Evento | Qué trae |
|---|---|
flow.answer.captured | Cada respuesta que guardó un paso de Pregunta o de Esperar respuesta |
flow.run.completed | El final de la ejecución, con todas las variables del flujo |
Los datos que enviaste en data no vuelven en el evento — guarda el runId para cruzar
los dos extremos. Las ejecuciones que fallan o se cancelan no generan
flow.run.completed. Los payloads están en el catálogo de eventos.
Límites y alcance
- Cada disparo gasta una solicitud del límite de envío de tu clave. Los mensajes que el flujo envía después no.
- Una API key restringida a algunos números puede disparar, pero solo con números de su alcance. Listar y consultar flujos exige una clave sin restricción.