Variables e interpolación
Variables e interpolación
Interpola valores del contexto de la ejecución dentro de los campos de texto de un bloque. Así una misma configuración sirve para cada ejecución: la URL, el correo o la razón de rechazo se arman con los datos que llegaron al workflow.
Sintaxis
Envuelve la ruta del dato en dobles llaves y separa los niveles con puntos:
{{data_subject_request.contact_information.email}}
Reglas que conviene tener presentes:
- no dejes espacios dentro de la ruta:
{{ event.payload.id }}sí funciona, pero{{event.payload .id}}no - accede a elementos de un arreglo por índice con
[0]o.0:{{event.payload.validation_attempts[0].status}} - si la ruta no existe en el contexto, Soyio deja el texto literal
{{...}}en el campo
Dónde puedes interpolar
Solo estos campos resuelven {{ }}:
| Bloque | Campos |
|---|---|
Enviar solicitud HTTP | URL, valores de los headers y body |
Enviar correo | asunto y cuerpo |
Transición DSR | razón de rechazo y contenido del correo |
Solicitud de formulario | título y descripción del formulario |
En los headers de Enviar solicitud HTTP solo interpola el valor, no la clave.
El destinatario de Enviar correo debe ser un correo literal válido. El editor te permite insertar una variable ahí, pero el workflow no se guarda: la validación del bloque exige una dirección con formato de correo. Deja el destinatario fijo y usa variables en el asunto y el cuerpo.
Las condiciones no usan llaves. En Filtro, Si / No y Selector escribe la ruta desnuda dentro de la expresión:
http_requests.check-status-1.parsed.status == "awaiting_verification"
Si escribes {{http_requests.check-status-1.parsed.status}} == "awaiting_verification", la condición no evalúa el dato: la compara como texto y el resultado es siempre falso.
Qué hay disponible según el trigger
Las rutas disponibles dependen del trigger que inicia la ejecución. No existe una raíz universal.
| Trigger | Raíces disponibles |
|---|---|
Evento generado | event.id, event.name y event.payload.*. Si el evento es de la familia data_subject_request.*, Soyio agrega además la raíz normalizada data_subject_request.* |
Webhook recibido | las claves del payload que envías, en la raíz y sin prefijo. Si envías {"ticket": {"id": "T-1"}}, la ruta es ticket.id |
Solicitud de derecho recibida | data_subject_request.* |
Inicio programado | schedule.frequency, schedule.slot, schedule.timezone y schedule.triggered_at |
Con Solicitud de derecho recibida siempre tienes estas 12 rutas:
data_subject_request.id
data_subject_request.humanized_identifier
data_subject_request.kind
data_subject_request.status
data_subject_request.origin
data_subject_request.request_reference
data_subject_request.user_reference
data_subject_request.contact_information.email
data_subject_request.contact_information.names
data_subject_request.contact_information.last_names
data_subject_request.contact_information.nin
data_subject_request.contact_information.phone
Rutas que se agregan durante la ejecución
Estas raíces no existen al inicio: aparecen cuando el bloque que las produce ya corrió.
| Raíz | Qué contiene |
|---|---|
http_requests.<step_id>.parsed.<key> | valores declarados en las extracciones de respuesta de un bloque Enviar solicitud HTTP |
http_requests.<step_id>.status | código HTTP de la respuesta |
http_requests.<step_id>.body | cuerpo de la respuesta, parseado si es JSON válido |
http_requests.<step_id>.headers | headers de la respuesta |
form_responses.<step_id>.values.<key> | respuestas de un bloque Solicitud de formulario |
resolved_delay_minutes_by_step.<step_id> | minutos que resolvió un bloque Acción diferida |
branches.<split_step_id>.<branch_slot_id>.… | resultados producidos dentro de una rama paralela, con la misma forma de las raíces anteriores |
workflow.variables.<key> | variables globales de la compañía |
workflow.secrets.<key> | secrets globales de la compañía |
<step_id> es el identificador del bloque que produjo el dato, no un token generado por Soyio.
workflow.secrets.* solo resuelve en los campos interpolables listados en Dónde puedes interpolar. Dentro de una condición no está disponible, así que no puedes comparar contra un secret.
Gestiona variables y secrets globales desde la configuración de workflows del dashboard o vía Actualizar configuración de workflows.
Ejemplo 1: notifica un DSR nuevo a tu CRM
Este workflow avisa a un CRM externo cada vez que se crea una solicitud de derecho, usando el ID, el correo del titular y un secret global con la API key del CRM.
Configura el trigger
Agrega un bloque Evento generado con el evento:
data_subject_request.created
Configura la solicitud HTTP
Conecta un bloque Enviar solicitud HTTP con:
-
Método:
POST -
URL:
https://crm.example.com/api/privacy-requests/{{event.payload.id}} -
Header: clave
Authorization, valor:Bearer {{workflow.secrets.crm_api_key}} -
Body:
{"request_id": "{{event.payload.id}}","reference": "{{event.payload.humanized_identifier}}","kind": "{{event.payload.kind}}","email": "{{event.payload.contact_information.email}}","opened_at": "{{event.payload.created_at}}"}
Como el evento pertenece a la familia data_subject_request.*, {{data_subject_request.contact_information.email}} resuelve el mismo correo. Elige una de las dos raíces y mantenla en todo el workflow para que sea fácil de leer.
Payload equivalente vía API
{
"name": "Notificar DSR nuevo al CRM",
"description": "Al crearse una solicitud de derechos, la registra en el CRM externo.",
"starting_step_id": "trigger-1",
"steps_attributes": [
{
"id": "trigger-1",
"_type": "EventTriggerBlock",
"event_name_pattern": "data_subject_request.created",
"next_step_id": "notify-crm-1"
},
{
"id": "notify-crm-1",
"_type": "HttpRequestActionBlock",
"method": "POST",
"url": "https://crm.example.com/api/privacy-requests/{{event.payload.id}}",
"headers": [
{ "key": "Authorization", "value": "Bearer {{workflow.secrets.crm_api_key}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"body": "{\"request_id\":\"{{event.payload.id}}\",\"reference\":\"{{event.payload.humanized_identifier}}\",\"kind\":\"{{event.payload.kind}}\",\"email\":\"{{event.payload.contact_information.email}}\",\"opened_at\":\"{{event.payload.created_at}}\"}"
}
]
}
Ejemplo 2: avisa por correo el resultado de un webhook
Este workflow recibe un ticket desde tu sistema, consulta su estado en tu API y avisa por correo al equipo de soporte. Combina tres orígenes de datos: el payload del webhook, la respuesta HTTP y una variable global.
Configura el trigger
Agrega un bloque Webhook recibido y declara el esquema de payload esperado:
| Ruta | Tipo | Requerido |
|---|---|---|
ticket.id | string | Sí |
ticket.requester_email | string | Sí |
Guarda el workflow para que Soyio genere la URL pública del bloque y envíale una solicitud con el payload dentro de la clave payload:
{
"payload": {
"ticket": {
"id": "T-4821",
"requester_email": "ana@example.com"
}
}
}
Revisa el contrato completo del endpoint en Disparar o reanudar workflow mediante webhook.
El envoltorio payload es parte de la solicitud, no del contexto. Dentro del workflow las claves quedan en la raíz: usa {{ticket.id}}, no {{payload.ticket.id}} ni {{event.payload.ticket.id}}. La raíz event solo existe cuando el trigger es Evento generado.
Consulta el estado del ticket
Conecta un bloque Enviar solicitud HTTP con id fetch-ticket-1:
-
Método:
GET -
URL:
https://support.example.com/api/tickets/{{ticket.id}} -
Extracciones de respuesta: agrega una con Ruta en respuesta
ticket.status, Variable destinostatusy Tipostring, marcada como requerida
Envía el correo
Conecta un bloque Enviar correo con:
-
Destinatario:
soporte@example.com, un correo literal -
Asunto:
Ticket {{ticket.id}} quedó en estado {{http_requests.fetch-ticket-1.parsed.status}} -
Cuerpo:
Hola,El ticket {{ticket.id}} de {{ticket.requester_email}} está en estado{{http_requests.fetch-ticket-1.parsed.status}}.Revísalo en {{workflow.variables.support_portal_url}}.
El asunto y el cuerpo combinan las tres fuentes: el payload del webhook, la extracción de la respuesta HTTP y una variable global. Cambiar la URL del portal de soporte no requiere editar el workflow.
Payload equivalente vía API
{
"name": "Avisar estado de ticket a soporte",
"description": "Recibe un ticket por webhook, consulta su estado y avisa por correo al equipo.",
"starting_step_id": "trigger-1",
"steps_attributes": [
{
"id": "trigger-1",
"_type": "WebhookTriggerBlock",
"expected_payload_schema": [
{ "path": "ticket.id", "type": "string", "required": true },
{ "path": "ticket.requester_email", "type": "string", "required": true }
],
"next_step_id": "fetch-ticket-1"
},
{
"id": "fetch-ticket-1",
"_type": "HttpRequestActionBlock",
"method": "GET",
"url": "https://support.example.com/api/tickets/{{ticket.id}}",
"response_extractors": [
{ "path": "ticket.status", "key": "status", "type": "string", "required": true }
],
"next_step_id": "notify-1"
},
{
"id": "notify-1",
"_type": "EmailActionBlock",
"to": "soporte@example.com",
"subject": "Ticket {{ticket.id}} quedó en estado {{http_requests.fetch-ticket-1.parsed.status}}",
"body": "Hola,\n\nEl ticket {{ticket.id}} de {{ticket.requester_email}} está en estado {{http_requests.fetch-ticket-1.parsed.status}}.\n\nRevísalo en {{workflow.variables.support_portal_url}}."
}
]
}
Cuando la interpolación no resuelve
Soyio no falla la ejecución al encontrar una ruta inexistente: deja el texto {{...}} tal cual y sigue. El síntoma depende del bloque.
En Enviar solicitud HTTP, un placeholder sin resolver dentro de la URL rompe la ejecución con este mensaje:
HTTP request failed: Invalid URL
El error no menciona la interpolación, pero la causa casi siempre es esa: las llaves quedaron literales en la URL y dejó de ser una dirección válida. Revisa la ruta antes de revisar el servicio externo.
En headers, body, correos y templates de DSR no hay error: el mensaje sale con el texto {{...}} visible. En Enviar correo, Soyio además registra una alerta interna por cada ruta que no resolvió.
Causas frecuentes:
| Síntoma | Causa | Corrección |
|---|---|---|
Invalid URL con trigger de webhook y ruta {{event.payload.id}} | la raíz event solo existe con Evento generado | usa la ruta del payload en la raíz, por ejemplo {{ticket.id}} |
Invalid URL con una raíz de recurso inventada, por ejemplo {{consent_action.id}} | esa raíz no está en el contexto de ese trigger | revisa Qué hay disponible según el trigger y usa una ruta que exista |
| el placeholder queda literal en un correo | la ruta está bien escrita pero el dato es null en esa ejecución | valida el dato con una condición antes de usarlo |
http_requests.<step_id>.parsed.<key> no resuelve | el bloque HTTP aún no corrió, el step_id no coincide o la extracción usa otra key | mueve el bloque antes en el flujo y confirma id y key de la extracción |
| una condición toma siempre la rama falsa | la ruta de la expresión no existe en el contexto; el bloque devuelve falso sin fallar la ejecución | en Si / No y Selector verás el error en el detalle de la ejecución; en Filtro revisa la ruta contra el selector de variables |
| una condición que compara un secret toma siempre la rama falsa | workflow.secrets.* no está disponible en condiciones | mueve la comparación a tu servicio externo o usa una variable global |
| la ruta no resuelve aunque exista | hay un espacio en medio de la ruta, como {{event.payload .id}} | escríbela sin espacios internos: {{event.payload.id}} |
Descubre las rutas disponibles
Tienes dos caminos:
- En el editor: al configurar un campo interpolable, el selector de variables lista las rutas del trigger elegido y las que producen los bloques anteriores. Es la forma más rápida de evitar errores de tipeo
- Vía API: Obtener contratos de eventos devuelve, por cada evento, todas las rutas
event.payload.*con su tipo y descripción. Úsalo cuando construyas workflows programáticamente
Referencias útiles
- Revisa qué contexto entrega cada trigger en Componentes
- Elige el bloque adecuado en Tipos de bloques
- Aplica la sintaxis a un flujo completo en Rechaza automáticamente solicitudes sin verificación de identidad
- Diagnostica otros problemas en Solución de problemas