Saltar al contenido principal

Resumen de la API de Canvas

Gestiona los journeys de Canvas - automatizaciones de varios pasos creadas en el constructor visual de journeys - mediante la API REST.

Todos los endpoints de esta página son relativos a la URL base: https://api-eu1.joryio.com/api. Consulta el resumen de la API.

La ruta es /journeys

Los endpoints de Canvas se encuentran bajo la ruta /journeys: el nombre del recurso de API para un canvas es «journey». canvasId y el ID de journey se refieren al mismo identificador.

Autenticación​

Todas las solicitudes requieren autenticación mediante clave de API:

Authorization: Bearer jry_live_your_api_key_here
Content-Type: application/json

Scopes necesarios por grupo de endpoints:

ScopeEndpoints
canvas:readListar, obtener, ejecuciones, estadísticas, analítica de nodos, versiones
canvas:writeCrear, actualizar, duplicar, archivar, etiquetas, variantes, experimentos
canvas:activateActivar, pausar, reanudar, publicar, ejecutar de nuevo, introducir usuario, revertir
canvas:enterIntroducir usuario (disparador API) - y nada más. Incluido en canvas:activate
canvas:deleteEliminar, eliminar en bloque

Listar journeys​

GET /journeys

Parámetros de consulta​

ParámetroTipoPredeterminadoDescripción
statuscadenaFiltra por estado
tagscadenaFiltra por etiquetas, separadas por comas
qcadenaBúsqueda de texto libre
createdBy / editedBycadenaFiltra por creador o último editor; ID de usuario separados por comas
pagenúmero1Número de página
limitnúmeroResultados por página, máximo 100

Solicitud de ejemplo​

curl -X GET "https://api-eu1.joryio.com/api/journeys?status=active&limit=20" \
-H "Authorization: Bearer jry_live_your_api_key"

Respuesta​

{
"data": [
{ "id": "3c9d2f1a-5e8b-4a7c-9f0d-1b2a3c4d5e6f", "name": "Welcome journey", "status": "active" }
],
"pagination": {
"total": 8,
"page": 1,
"limit": 20,
"offset": 0,
"totalPages": 1,
"hasMore": false
}
}

Crear un journey​

POST /journeys

Cuerpo de la solicitud​

CampoTipoObligatorioDescripción
namecadenaSíNombre del journey, máximo 255 caracteres
descriptioncadenaNoDescripción, máximo 1000 caracteres
nodesmatrizNoNodos del grafo, máximo 500. Un borrador creado por el asistente puede comenzar vacío
edgesmatrizNoConexiones del grafo, máximo 1000
entryTriggerobjetoNoCómo entran los usuarios; consulta más abajo
variantsmatrizNoVariantes A/B/n de todo el journey; consulta más abajo
settingsobjetoNotimezone, quietTime, conversionTracking, reEntryPolicy, personalizedVariants y su configuración
sendTypecadenaNoimmediate, scheduled, recurring o trigger
scheduledAtcadenaNoFecha ISO 8601 para sendType: "scheduled"
recurringScheduleobjetoNofrequency (daily/weekly/monthly/custom), cron, dayOfWeek, dayOfMonth, timeOfDay, timezone, endDate, maxOccurrences timeOfDay es HH:MM en formato de 24 horas (09:00, 17:30); cualquier otro valor se rechaza con 400.
targetingobjetoNoAudiencia para journeys programados o inmediatos: userIds, filterGroups, excludeFilterGroups, filterOperator, subscriptionPreference
exitCriteriaobjetoNoMisma estructura de filtros que targeting; los usuarios activos que coincidan salen
tagscadena[]NoEtiquetas

Estructura de los nodos​

Cada entrada de nodes tiene id, type, config (específica del tipo) y una position opcional (x/y para el editor). Valores válidos de type:

trigger, message, in_app_message, delay, condition, behavior_split,
context, update_user, update_wallet, connector, experiment,
ai_decision, ai_agent

Hay un solo nodo message; el canal es config.channel (email, sms, push, whatsapp, viber, in_app, webhook). Los antiguos tipos de nodo por canal - email, sms, push, whatsapp, whatsapp_message, wallet, webhook y el alias in_app - se eliminaron y ahora se rechazan al crear y al actualizar.

Cada entrada de edges tiene id, source, target y sourceHandle / targetHandle / label opcionales. sourceHandle selecciona el puerto de salida de los nodos con varias salidas (grupos de ramificación, behavior-split did / timed_out).

Disparador de entrada​

entryTrigger tiene un type y una config específica del tipo. Tipos válidos: event, api, entity_change, whatsapp_inbound, sms_inbound, viber_inbound, attribute_change, subscription_status, schedule.

La entrada en segmento no es un desencadenante. Para entradas causadas por algo que hizo la persona, usa un desencadenante de evento con un filtro; para entradas causadas por el paso del tiempo, usa un recorrido recurrente sobre el segmento.

Variantes de todo el journey​

Cada entrada de variants incluye id, name, percentage (de 0 a 100; todas las variantes deben sumar 100), isControlGroup (una variante de control es un grupo de control medido sin flujo) y triggerNodeId (el nodo disparador desde el que comienza esta variante de tratamiento). Consulta analítica de journeys para saber cómo se presentan los resultados de las variantes. El campo se llamaba antes isControl; esa forma se sigue aceptando al escribir y se normaliza a isControlGroup.

Solicitud de ejemplo​

curl -X POST https://api-eu1.joryio.com/api/journeys \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Welcome journey",
"sendType": "trigger",
"entryTrigger": {
"type": "event",
"config": { "eventName": "signed_up" }
},
"nodes": [
{ "id": "n1", "type": "trigger", "config": { "type": "event", "eventName": "signed_up" } },
{ "id": "n2", "type": "delay", "config": { "delayType": "duration", "value": 1, "unit": "days" } },
{ "id": "n3", "type": "email", "config": { "subject": "Welcome!", "html": "<p>Hi {{ user.firstName }}</p>" } }
],
"edges": [
{ "id": "e1", "source": "n1", "target": "n2" },
{ "id": "e2", "source": "n2", "target": "n3" }
]
}'

Devuelve el objeto journey creado, con estado draft.


Obtener un journey​

GET /journeys/:canvasId
curl -X GET https://api-eu1.joryio.com/api/journeys/3c9d2f1a-5e8b-4a7c-9f0d-1b2a3c4d5e6f \
-H "Authorization: Bearer jry_live_your_api_key"

Devuelve el journey completo, incluidos nodes, edges, entryTrigger, variants y settings.


Actualizar un journey​

PUT /journeys/:canvasId

El cuerpo acepta los mismos campos que Crear un journey; todos son opcionales y solo se actualizan los campos enviados.

curl -X PUT https://api-eu1.joryio.com/api/journeys/3c9d2f1a-5e8b-4a7c-9f0d-1b2a3c4d5e6f \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "name": "Welcome journey v2" }'

Eliminar un journey​

DELETE /journeys/:canvasId

Devuelve 204 No Content. Los journeys con historial de ejecuciones deben archivarse en su lugar (POST /journeys/:canvasId/archive): así se detienen las inscripciones y los envíos, pero se conserva la analítica.


Endpoints de estado​

MétodoRutaScopeDescripción
POST/journeys/:canvasId/activatecanvas:activateActivar: los usuarios pueden empezar a entrar
POST/journeys/:canvasId/pausecanvas:activatePausar: detiene nuevas entradas y avances
POST/journeys/:canvasId/resumecanvas:activateReanudar un journey pausado
POST/journeys/:canvasId/archivecanvas:writeArchivar: detiene inscripciones y envíos, conserva el historial
POST/journeys/:canvasId/unarchivecanvas:writeRestaurar a un estado no activo; actívalo explícitamente para reanudarlo
POST/journeys/:canvasId/publishcanvas:activatePublicar el borrador actual como nueva versión. Cuerpo: changeSummary opcional, userTransition (keep_on_version / force_exit / migrate_to_new). Solo para un recorrido que ya está en directo (status: active); si no, 409 con code: "journey_not_live" - la puesta en marcha se hace con POST /journeys/:canvasId/activate.
POST/journeys/:canvasId/reruncanvas:activateVolver a ejecutar la versión publicada actual sin crear una nueva
curl -X POST https://api-eu1.joryio.com/api/journeys/3c9d2f1a-5e8b-4a7c-9f0d-1b2a3c4d5e6f/activate \
-H "Authorization: Bearer jry_live_your_api_key"

Introducir un usuario (disparador de API)​

Inscribe a un usuario concreto en un journey: es la ruta de entrada de entryTrigger.type: "api".

POST /journeys/:canvasId/enter/:userId

Permiso: canvas:enter (incluido en canvas:activate), para que una integración como Zapier pueda añadir personas a un recorrido sin poder iniciarlo, pausarlo ni editarlo.

Cuerpo opcional: context, un objeto JSON disponible para la ejecución y que puede leerse en mensajes y condiciones como variables de contexto del journey.

curl -X POST https://api-eu1.joryio.com/api/journeys/3c9d2f1a-5e8b-4a7c-9f0d-1b2a3c4d5e6f/enter/user_123 \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "context": { "source": "crm-sync", "priority": "high" } }'

Listar los recorridos en los que puede entrar una persona​

GET /journeys/enterable?q=

Los journeys activos (active), como { "data": [{ "id", "name", "activatedAt" }] }, ordenados por nombre, como máximo 100; q filtra por parte del nombre. Permiso: canvas:enter (o canvas:read): una integración que puede añadir personas a recorridos elige uno sin leer los propios journeys.


Ejecuciones y analítica​

MétodoRutaDescripción
GET/journeys/:canvasId/executionsLista ejecuciones (status, limit máximo 100, offset)
GET/journeys/:canvasId/executions/:executionIdObtiene una ejecución. Cada paso de webhook en history incluye webhook (estado, correcto, duración, intentos, error, campos guardados); una llamada fallida (no 2xx) añade webhook.response ({ status, contentType, body, truncated }) - con los secretos ocultos, los primeros 2 KB del cuerpo, conservada 30 días, devuelta solo a quien tiene pii:view (una clave de API solo con ese permiso; los demás reciben webhook.responseHidden: true). El cuerpo de una respuesta correcta nunca se guarda
GET/journeys/:canvasId/executions/:executionId/contextVariables de contexto de la ejecución con tipos inferidos
GET/journeys/:canvasId/statsEstadísticas del journey (startDate, endDate)
GET/journeys/:canvasId/node-analyticsAnalítica por nodo (startDate, endDate)
GET/journeys/:canvasId/variant-statsRendimiento de las variantes de todo el journey (A/B/n y control)
GET/journeys/:canvasId/recovered-cartsLos carritos abandonados que recuperó el recorrido: la lista detrás de revenue.recoveredCarts en /stats, de la misma consulta, así que total es igual a ese recuento para los mismos startDate/endDate (carritos recuperados en el intervalo; un final solo con fecha incluye el día entero, zona horaria del espacio de trabajo). limit 1-100 (25 por defecto), offset; los más recientes primero. Filas: orderNumber (el de la tienda), placedAt, recoveredAt, match (recovery_link, order = mismo carrito, reported), cartValue/cartCurrency, creditedRevenue/creditedCurrency (neto de reembolsos), contact (el dueño del carrito) y buyer (solo cuando el pedido se guardó a nombre de otra persona); los nombres de contacto se ocultan sin pii:view. Devuelve { data, total, limit, offset, summary }
GET/journeys/:canvasId/experiments/:nodeId/statsEstadísticas del nodo de experimento con prueba de significancia
POST/journeys/:canvasId/experiments/:nodeId/declare-winnerDeclara un ganador (cuerpo: pathId)
POST/journeys/:canvasId/experiments/:nodeId/resetRestablece un experimento a recopilación
GET/journeys/:canvasId/personalization-statusEstado de la fase de variantes personalizadas

Endpoints adicionales​

MétodoRutaDescripción
PUT/journeys/:canvasId/variantsDefine las variantes de todo el journey (cuerpo: matriz variants)
GET/journeys/:canvasId/versionsLista versiones
GET/journeys/:canvasId/versions/compare?v1=&v2=Compara dos versiones
GET/journeys/:canvasId/versions/compare-draftCompara el borrador actual con la última versión publicada
GET/journeys/:canvasId/versions/migration-previewPrevisualiza la compatibilidad de ejecuciones antes de publicar una migración
GET/journeys/:canvasId/versions/:versionIdObtiene una versión
POST/journeys/:canvasId/versions/:versionId/rollbackRevierte a una versión. Solo recorridos en directo; si no, 409 journey_not_live.
GET/journeys/:canvasId/versions/:versionId/statsEstadísticas específicas de la versión
GET/journeys/:canvasId/versions/:versionId/executionsEjecuciones de una versión concreta
GET/journeys/:canvasId/version-execution-countsRecuentos de ejecuciones por versión
POST/journeys/:canvasId/versions/:versionId/migrateFuerza la migración de ejecuciones compatibles a una versión
GET/journeys/:canvasId/historyHistorial del registro de auditoría (limit, máximo 200)
POST/journeys/bulk-delete / bulk-duplicate / bulk-archive / bulk-unarchiveAcciones en bloque; cuerpo { "ids": [...] }, devuelve { succeeded, failed }
POST/journeys/bulk-tagEtiquetado en bloque; cuerpo { "ids": [...], "tags": [...] }
POST/journeys/webhook/testEjecuta una vez la configuración de un nodo webhook y devuelve la respuesta en vivo junto con la solicitud enviada (credenciales ocultas). user.userId procesa un contacto real del espacio de trabajo exactamente como un envío real; si no, se usan valores de ejemplo, con límite de frecuencia
POST/journeys/preview-context-valueRenderiza una expresión Liquid contra un ámbito de ejemplo
POST/journeys/preview-user-updatesSimula las filas de un nodo Update User frente a un usuario de ejemplo
POST/journeys/preview-user-update-jsonSimula el JSON personalizado de un nodo Update User: entra { json, sample }, sale { errors, preview: { errors, result } }. Los errors bloquean guardar o activar; preview es el JSON renderizado con el ejemplo. No escribe nada
POST/journeys/:canvasId/nodes/:nodeId/send-test-email / send-test-sms / send-test-whatsapp / send-test-pushEnvía una prueba desde un nodo de mensaje
POST/journeys/:canvasId/cleanup-stuck-executionsLimpia ejecuciones bloqueadas
GET/journeys/:canvasId/executions/:executionId/rendered-message/:nodeIdMensaje renderizado de una ejecución y un nodo

Revisión de lanzamiento​

La misma revisión previa al envío que reciben las campañas (ver la guía de Revisión de lanzamiento), ejecutada sobre cada nodo de mensaje: enlace de baja, campos de combinación, verificación del remitente, enlaces inutilizables, longitud del asunto, falta de texto plano, horas de silencio, más node_unreachable para los nodos a los que ningún disparador llega, cart_variable_no_cart_trigger para un mensaje que lee cart en un recorrido que no empieza con un evento de carrito, y channel_not_set_up para un canal que usa el recorrido sin proveedor ni remitente (params.channel; un bloqueo, o una recomendación con params.sandbox: 1 en un espacio de trabajo de demostración, donde los envíos se simulan para todos). La activación y la publicación también la ejecutan.

GET /journeys/{canvasId}/launch-review

Alcance: canvas:read. La respuesta tiene la forma documentada en la API de campañas; un hallazgo de nodo lleva scope.kind = "node", scope.id = el id del nodo y fix.nodeId.

Cuando el espacio de trabajo exige una lista limpia (settings.launchReview.requireClean, por defecto true) y hay bloqueos, POST /journeys/{canvasId}/activate y POST /journeys/{canvasId}/publish responden 409 con code: "launch_review_blocked" y los bloqueos en el cuerpo.

Respuestas de error​

Todos los errores comparten la estructura estándar. Consulta respuesta de error en el resumen de la API para ver el formato, los códigos de estado y el comportamiento de límite de frecuencia.

{
"statusCode": 404,
"message": "Canvas with ID 8f14e45f-ceea-467f-a11d-2f4b6a1c9e3b not found",
"timestamp": "2026-07-12T09:00:00.000Z",
"path": "/journeys/8f14e45f-ceea-467f-a11d-2f4b6a1c9e3b"
}

Contenido relacionado​