Llamar a un flujo por API
Un flujo con una versión desplegada se puede ejecutar desde cualquier aplicación con una petición HTTP. La forma recomendada es lanzarlo en segundo plano y consultar después su estado: la petición responde al momento y tu aplicación no se queda esperando con la conexión abierta. Esta página explica cómo hacerlo, qué devuelve cada paso y cómo saber en qué punto está una ejecución. Los ejemplos son respuestas reales, recortadas para que se lean mejor.
La ventana Acceso a API del flujo genera el código de la llamada con tu flujo, tu clave y tu servidor ya puestos. Qué pestañas aparecen en ella depende de los componentes del flujo: lo explica Publicar un flujo.
Antes de empezar
- Una versión desplegada. Las llamadas ejecutan la versión desplegada, no el borrador que ves en el editor. Si cambias el flujo, despliega una versión nueva para que las llamadas la usen. Ver Versiones y publicación. La única excepción es la ejecución de prueba.
- Una clave API. Va en la cabecera
x-api-key. Ver Claves API. - El identificador del flujo. Es el que aparece en la URL del editor y en el código de Acceso a API. Los flujos se llaman siempre por su identificador, no por su nombre.
Todas las rutas empiezan por https://TU-SERVIDOR/api/v1/. En el código de Acceso a API ya aparece la dirección de tu servidor.
Qué llamada usar
| Quieres… | Llama a |
|---|---|
| Ejecutar el flujo y recoger el resultado | POST /background_run/{flow_id} y después su estado |
| Ir mostrando la respuesta mientras se escribe | Lo mismo, con el streaming activado |
| Que otro servicio lo dispare al ocurrir algo | POST /webhook/{flow_id} |
| Probar el borrador sin desplegarlo | POST /test_run/{flow_id} |
| Detener una ejecución en marcha | POST /run/{task_id}/cancel |
Lanzar la ejecución
curl -X POST "https://TU-SERVIDOR/api/v1/background_run/FLOW_ID" \ -H "x-api-key: TU_CLAVE" \ -H "Content-Type: application/json" \ -d '{"input_value": "Hola, ¿tenéis hueco para un corte el viernes por la tarde?", "session_id": "cliente-42"}'La respuesta llega al momento, con el identificador de la ejecución y la dirección donde consultar su estado:
{ "taskid": "98bd2e8a-0539-46a2-9e97-665a286d4351", "message": "Flow execution started.", "statusurl": "/api/v1/background_run/98bd2e8a-0539-46a2-9e97-665a286d4351/status"}El taskid es también el identificador de la ejecución en el registro de ejecuciones.
El cuerpo de la petición
Todos los campos son opcionales.
| Campo | Qué hace |
|---|---|
input_value | El texto de entrada, lo que escribiría el usuario en el chat. |
session_id | Identifica la conversación. Usa el mismo valor en cada mensaje de un mismo usuario para que el flujo recuerde lo anterior. Si no lo envías, NappAI genera uno nuevo y lo devuelve en el resultado. |
conversation_id | Agrupa los mensajes en la vista de conversaciones. Por defecto, el mismo valor que session_id. |
tweaks | Cambia campos de los componentes solo para esta llamada. Ver Cambiar campos en una llamada. |
files | Identificadores de ficheros ya subidos a la conversación. |
input_type | chat (por defecto), text o any. |
output_type | Qué salidas devuelve: chat (por defecto, los Chat Output), text, any (todas las salidas) o debug (todos los componentes). |
Consultar el estado
Haz un GET a la statusurl, por ejemplo cada segundo o cada pocos segundos, hasta que llegue a un estado final:
curl "https://TU-SERVIDOR/api/v1/background_run/98bd2e8a-0539-46a2-9e97-665a286d4351/status"| Estado | Qué significa | ¿Final? |
|---|---|---|
| queued | En cola: ningún servidor la ha empezado todavía. | No |
| running | Se está ejecutando. | No |
| paused | Está esperando a que termine una llamada o a que alguien responda una aprobación. Después continúa sola, con el mismo identificador. | No |
| done | Terminó. El resultado va en result. | Sí |
| error | Falló. El motivo va en message. | Sí |
| cancelled | Se canceló. | Sí |
| not found | No existe ninguna ejecución con ese identificador. | Sí |
El estado va en el campo status. Así evoluciona una ejecución normal:
{ "status": "queued", "message": "Task is waiting in the queue for a worker" }{ "status": "running" }{ "status": "done", "result": { "session_id": "cliente-42", "outputs": [ … ] } }Una en pausa trae lo que el flujo ha devuelto hasta ese momento y qué está esperando:
{ "status": "paused", "paused": { "kind": "approval", "pause_id": "0ce2cdac-2e14-4b97-ba9c-7424c4790e55", "component_id": "AdvancedAgent-pq02" }, "result": { "session_id": "…", "outputs": [ … ] }}kind es approval (o tool_approval) cuando espera una aprobación, y outbound_call cuando espera a que termine una llamada saliente. Al reanudarse vuelve a pasar por queued y running, y termina en done.
Una que ha fallado dice qué componente falló y por qué:
{ "status": "error", "message": "Error building Component OpenAI: Error code: 401 - Incorrect API key provided", "traceback": "…" }El resultado
Cuando el estado es done, result trae lo que devolvió el flujo:
{ "status": "done", "result": { "session_id": "cliente-42", "outputs": [ { "inputs": { "input_value": "Hola, ¿tenéis hueco para un corte el viernes por la tarde?", "files": [] }, "outputs": [ { "results": { "message": { "text": "Claro, para un corte el viernes por la tarde tenemos hueco; llama al 960 000 000 y te confirmamos la hora exacta.", "sender": "Machine", "sender_name": "AI", "session_id": "cliente-42", "files": [] } }, "artifacts": { "message": "Claro, para un corte el viernes por la tarde tenemos hueco; llama al 960 000 000 y te confirmamos la hora exacta.", "sender": "Machine", "sender_name": "AI", "files": [], "type": "object" }, "component_display_name": "Chat Output", "component_id": "ChatOutput-uc3ue" } ] } ] }}La respuesta del flujo está en result.outputs[0].outputs[0].results.message.text. Hay un elemento en outputs[0].outputs por cada componente de salida devuelto, y component_id indica cuál es cada uno.
Respuesta en stream
Para ir mostrando el texto mientras el modelo lo escribe:
-
Activa el streaming en el componente que genera la respuesta: es el campo Stream, en las opciones avanzadas de los modelos y del Agent. También puedes activarlo solo en esta llamada con un tweak:
"tweaks": {"AdvancedAgent-2jhmg": {"use_stream": true}}en un Agent, o{"stream": true}en un modelo. -
Lanza la ejecución y consulta su estado como siempre. Pasa a done en cuanto empieza a escribirse la respuesta, sin el texto: en su lugar trae
"type": "stream"y una dirección enstream_url."artifacts": {"message": "","stream_url": "/api/v1/build/895da449-…_e55d7896-…/ChatOutput-uc3ue/streamv2","type": "stream"} -
Abre esa dirección con un
GET, añadiendo delante tu servidor. Devuelve un stream de eventos (text/event-stream):event: messagedata: {"message":"Streaming vertex ChatOutput-uc3ue"}event: messagedata: {"chunk":"Tenemos corte de pelo por 18 €, color por 35 € y peinado por 15 €."}event: closedata: {"message":"Stream closed"}
| Evento | Qué trae |
|---|---|
message con message | El aviso de que empieza el stream. |
message con chunk | Un trozo del texto. Ve concatenándolos en orden. Según el componente, llegan muchos trozos pequeños o uno solo con todo el texto. |
message con media | Un fichero de la conversación (por ejemplo, una imagen generada). |
| cancelled | La ejecución se canceló. |
| error | Algo falló; el motivo va en error. |
| close | Se acabó el stream. Puede llegar más de una vez: quédate con el primero. |
Si pasan 30 segundos sin datos, llega una línea : keep-alive para que la conexión no se corte; ignórala.
Cancelar una ejecución
curl -X POST "https://TU-SERVIDOR/api/v1/run/TASK_ID/cancel" -H "x-api-key: TU_CLAVE"{ "status": "ok", "task_id": "7e18b6fa-3042-45ba-8b9f-43eaae93dae7", "message": "Cancellation signal sent" }La ejecución se detiene en unos segundos y su estado pasa a cancelled:
{ "status": "cancelled", "message": "Task cancelled by user" }Probar el borrador (test_run)
POST /test_run/{flow_id} ejecuta el borrador, lo que ves ahora en el editor, sin desplegar una versión. Acepta el mismo cuerpo y devuelve un taskid y la misma statusurl, que se consulta igual.
{ "taskid": "1a4f4e91-ca98-4c68-bd89-b7e3a2cd100c", "message": "Test run started.", "statusurl": "/api/v1/background_run/1a4f4e91-ca98-4c68-bd89-b7e3a2cd100c/status" }Para probarlo con un entorno concreto, usa POST /test_run/{environment_id}/{flow_id}. Es lo que genera el modo Test de Acceso a API.
Webhooks
POST /webhook/{flow_id} es la dirección para que otro servicio dispare el flujo. El flujo necesita un componente Webhook Input, que recibe lo que llega en la petición:
{ "headers": { … }, "query_params": { … }, "body": { "cliente": "Ana", "input_value": "Quiero cita el sábado" } }NappAI quita de las cabeceras y de los parámetros la clave API y las cookies antes de pasarlos al flujo.
Lo que recibe el servicio que llama depende de si el flujo tiene un componente Webhook Response:
-
Sin Webhook Response, la respuesta es inmediata (HTTP 202) y el flujo sigue en segundo plano:
{"taskid": "457708c0-e188-4ad5-b428-f77fd6c5ce8c","status": "Task started in the background","message": "Flow execution started.","statusurl": "/api/v1/webhook_task/457708c0-e188-4ad5-b428-f77fd6c5ce8c"}Su estado se consulta en
statusurl, con los mismos estados. -
Con Webhook Response, la petición espera a que el flujo termine y devuelve exactamente lo que le llega a ese componente. Úsalo solo cuando el servicio que llama necesita una respuesta concreta en la misma petición.
Los webhooks de servicios como Gmail, Outlook, Teams o Shopify no se llaman así: se publican desde el propio componente. Ver Publicar un flujo.
Cambiar campos en una llamada (tweaks)
tweaks cambia el valor de campos de los componentes solo para esa llamada, sin tocar la versión desplegada. La clave es el identificador del componente, que ves en el propio componente y en el código de Acceso a API:
{ "input_value": "Hola", "tweaks": { "AdvancedAgent-2jhmg": { "use_stream": true }, "TextInput-entrada": { "input_value": "Valencia" } }}Solo cambian los campos que existen en ese componente. En vez del identificador también puedes poner el nombre visible del componente.
Errores al lanzarla
Si la ejecución ni siquiera empieza, la respuesta trae el motivo en message:
| HTTP | Mensaje | Qué hacer |
|---|---|---|
| 403 | An API key must be passed as query or header | Falta la cabecera x-api-key. |
| 403 | Invalid or missing API key | La clave no existe, se ha regenerado o va sin codificar en la URL. |
| 429 | This flow reached the runs per minute of its execution profile | El flujo ha superado las ejecuciones por minuto de su perfil de ejecución. Espera y reintenta. |
| 500 | Flow … not found | El identificador no existe, el flujo no tiene versión desplegada o tu clave no tiene acceso a él. |
{ "message": "Invalid or missing API key", "type": "http_error", "status_code": 403 }Si la ejecución empieza y luego falla un componente, la petición se acepta igual: el fallo aparece después en el estado error, con el componente y el motivo, y en el registro de ejecuciones.
Buenas prácticas
- Reutiliza el mismo
session_idpara todos los mensajes de un mismo usuario: así el flujo recuerda la conversación. - Trata queued, running y paused como “sigue en marcha”, y deja de consultar en done, error o cancelled.
- Consulta el estado cada uno o pocos segundos; más a menudo no lo hace terminar antes.
- Guarda la clave en el servidor de tu aplicación, nunca en el código que se ejecuta en el navegador.