Waits
Many processes need to wait: two business days before reminding a customer, an invoice’s due date, or the confirmation of a payment coming from another system. With Zoan Flow’s wait steps, the case does exactly that, with no workarounds and no robots spinning in a loop:
- No robots or workers tied up. While it waits, the case is simply stored; your robots stay free for other work and the wait uses no capacity.
- Business time. Durations can count only your organization’s business hours, and dates are read in its time zone.
- Nothing gets lost. Waits survive Zoan Cloud restarts and updates: the case moves on at the right moment.
- Another system speaks up and the case moves on. Your ERP, your payment gateway or a robot sends a signal and the case continues with the data it carries.
- A plan B if the notice never comes. With a time limit and the Vencida (expired) exit, the case escalates or takes another path instead of sitting still.
There are two wait steps:
| Step | Waits for… | Example |
|---|---|---|
| Esperar (wait) | A period of time or a date. | Wait 2 business days before sending a reminder. |
| Esperar evento (wait for event) | A named signal, sent from the portal, the API or a robot. | Wait for the payment confirmation, with a 24-hour limit. |
Both are added from the canvas palette and have exactly one regular exit; Esperar evento can also have the Vencida exit.
Esperar (wait)
Section titled “Esperar (wait)”Esperar stops the case and lets it continue when the time is up. In the properties panel you choose how the time is set:
| Mode | What you set | When the case continues |
|---|---|---|
| A duration | A whole number (1 or more) of minutes, hours or days. Optional: count only business hours. | When that much time has passed since the case reached the step. |
| A fixed date and time | YYYY-MM-DD or YYYY-MM-DD HH:mm. | At that date and time. A date alone falls due at 00:00 that day. |
| A date from a variable | A flow variable of type Fecha (date) or Fecha y hora (date and time). | At the date that variable holds in the case, for example due_date. |
How time is counted:
- Your organization’s time zone. Dates and times, fixed or from a variable, are read in your organization’s time zone. A Fecha y hora value that already carries its own zone is kept as is.
- Business hours. With count only business hours, the wait uses the same business hours as task deadlines (Administración › Organización y SSO › Plazos de atención de tareas (SLA), task service levels): outside working hours the clock stops, and each day counts as a full working day. With a Monday-to-Friday schedule, “2 days” from a Friday afternoon fall due on Tuesday afternoon. If the organization has no business hours set, it counts all 24 hours.
- A date in the past does not hold the case: it continues right away.
- Up to a year. A wait can last up to 366 days; with business hours, up to a working year (250 days, 2,000 hours or 120,000 business minutes). A longer duration cannot be published; if a fixed date or a variable’s date falls further out (or business hours push it past a year), the case stops with the timer_too_far incident.
- Dates and times without a time zone. A date and time without a time zone (for example
2026-12-24T18:00) is read in your organization’s time zone. If it comes with a zone (…Zor-05:00), it is used as is. - A variable with no value or with an unusable date stops the case with the timer_invalid incident. Fix the variable and retry the step.
Example: a reminder after 2 business days
Section titled “Example: a reminder after 2 business days”A flow sends a quote and, if the customer has not replied, reminds them two business days later.
flowchart LR A([Start]) --> E[Integration<br/>Send quote] E --> W[Esperar<br/>2 days, business hours] W --> R[Integration<br/>Send reminder] R --> F([End])
With count only business hours, a quote sent on Thursday at 4:00 p.m. gets its reminder on Monday at 4:00 p.m., and nobody receives emails over the weekend.
Esperar evento (wait for event)
Section titled “Esperar evento (wait for event)”Esperar evento stops the case until a signal with a name you choose arrives, for example payment-confirmed or order-received. The signal is sent by another system, by a person from the portal or by a robot (see Sending a signal), and it can carry data that the case stores in its variables.
| Section | What you set |
|---|---|
| Signal name | Lowercase letters, digits, ., _ and -, up to 100 characters; it starts with a letter or digit. For example, payment-confirmed. |
| Signal data | Which piece of the signal goes to which flow variable. Each row is a path inside data (dots allowed, as in payment.reference) and a declared variable. Mark it optional if the value may be missing. |
| Time limit | Optional: Duración (duration: the longest it waits from when the case reaches the step, in minutes, hours or days, up to 366 days) or Fecha de una variable (a variable’s date: the date in a case variable plus an optional margin). The duration or the margin can count business hours only. |
Data arrives with its type checked
Section titled “Data arrives with its type checked”Each value in the signal is stored in its variable with the type you declared, using the same conversion as a case’s start data: a number that arrives as "1850000" is stored as a number, a date as a date. If a required value is missing or does not match the type, the signal is rejected with a clear message (for example, «Los datos de la señal no sirven: «total» debe ser un número.», the signal data is not usable: “total” must be a number) and the case keeps waiting. Whoever sends the signal knows right away that it needs fixing, and the flow never moves on with half the data.
Time limit based on a date in the case
Section titled “Time limit based on a date in the case”When the deadline depends on the case, choose Fecha de una variable (a variable’s date): the step expires on the date in a Fecha (date) or Fecha y hora (date and time) variable plus an optional margin. For example, “estimated delivery date + 2 days”: each case waits according to its own date, with no extra step to compute it.
- The date is read just like in Esperar until a variable’s date: a date alone counts from 00:00 that day, and a date and time without a zone is read in the organization’s time zone.
- The margin is a whole number of minutes, hours or days. With contar el margen solo en horario laboral (count the margin in business hours only), the margin only runs during working hours, like an Esperar duration. With no margin, it expires right on the variable’s date.
- If the date has already passed when the case reaches the step, the time limit expires right away: the case takes the Vencida exit (or stops with the message_expired incident if there is none).
- If the variable has no value or is not a valid date, the case stops with the timer_invalid incident, which names the variable. No other deadline is used instead: fix the variable with Editar variables (edit variables) and retry the step.
- Up to one year. If the date plus the margin falls more than a year after the case reaches the step, the case stops with the timer_too_far incident.
The monitor, the API and Mis solicitudes (my requests) show how long the case waits, with the date already computed.
Time limit and the Vencida exit
Section titled “Time limit and the Vencida exit”With a Time limit, add a second connection from the step and mark it as the Vencida (expired) exit, just like in person tasks. If the signal does not arrive in time, the case goes that way: you can create a task for someone to review, notify the customer or take another path.
If the step has a time limit but no Vencida exit, validation shows a warning, and when the time runs out the case stops with the message_expired incident so a person can decide. The Vencida exit can only be used when the step has a time limit.
Several branches waiting for the same signal
Section titled “Several branches waiting for the same signal”If several steps in parallel branches of the case are waiting for the same signal, a single signal reaches all of them and each branch moves on independently.
The signal arrives once the case is waiting
Section titled “The signal arrives once the case is waiting”A signal is delivered to the steps waiting for it at that moment: if it arrives before the case reaches the «Esperar evento» step, the response is 409 SIGNAL_NOT_EXPECTED and the sender can retry later (with the same idempotency key, without risk of duplicates). So the external system should notify after the case asked for what it waits for, or retry on that 409.
Example: payment confirmation with a 24-hour limit
Section titled “Example: payment confirmation with a 24-hour limit”An order flow creates the payment link and waits for the gateway to confirm. If there is no confirmation within 24 hours, someone from collections reviews the order.
flowchart LR A([Start]) --> L[Integration<br/>Create payment link] L --> W[Esperar evento<br/>payment-confirmed · max 24 h] W --> D[Robot<br/>Ship order] W -- Vencida --> P[Person<br/>Review pending payment] D --> F([End]) P --> F
The gateway (or your ERP) sends the payment-confirmed signal with { "reference": "PAY-88213", "total": 1850000 }; the step stores reference and total in the case variables and the robot ships the order with that data.
Sending a signal
Section titled “Sending a signal”A signal is a named notice addressed to a case: “this case received payment-confirmed, with this data”. It is accepted only if the case has an open Esperar evento step with that name.
You need the orchestration:signal permission (or orchestration:operate). See Permissions and plans.
From the portal
Section titled “From the portal”In the case detail, while a step is waiting for an event, use Enviar señal (send signal): pick the signal the case is waiting for and, if needed, type its data. It is handy to unblock a case when the notice came some other way (for example, the customer emailed the receipt). To send data you also need Ver datos de flujos (view flow data, orchestration:read_data), because it writes case variables.
With API v1
Section titled “With API v1”Your system sends the signal with a service account key:
curl -s -X POST "https://api.cloud.zoansoftware.com/v1/environments/$ENV/cases/$CASE/signals" \ -H "Authorization: Bearer zk_0123456789ab_EXAMPLExxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: payment-PAY-88213" \ -d '{ "name": "payment-confirmed", "data": { "reference": "PAY-88213", "total": 1850000 } }'{ "case_id": "3b7f2c10-8e4d-4a91-b6c5-0d2e9f7a1c38", "signal": "payment-confirmed", "delivered_to": [ { "step_id": "a1d5e7c2-4b90-4f38-9e61-7c2b0d8f5a14", "element_id": "wait_payment" } ], "status": "running", "received_at": "2026-10-19T15:04:22Z", "duplicate": false}With the same idempotency key (Idempotency-Key header or idempotency_key field), you can resend safely: if the gateway retries its notice, it gets the same response with "duplicate": true and the case does not move forward twice. The endpoint and its errors are described in Zoan Cloud API.
From a robot
Section titled “From a robot”A robot running inside the case (a robot step of the flow) notifies it with the «Send Signal to Case» activity of the Human Tasks package: give the signal name and, optionally, the data and an idempotency key. It uses the identity of its own execution, with no keys to store, and only reaches the case it runs in (for example, so a parallel branch waiting for documentos-listos continues as soon as the robot finishes that part).
To notify another case (for example, a robot watching a mailbox that notifies the right case when the payment receipt arrives), call API v1 with a service account key stored as a credential.
Responses
Section titled “Responses”This is how the API responds; the portal shows the same reasons in a message:
| Response | Meaning |
|---|---|
200 | The signal arrived; delivered_to says which steps got it. |
200 with "duplicate": true | It was already received with that idempotency key; it was not applied again. |
404 | The case does not exist or is in another environment. |
409 SIGNAL_NOT_EXPECTED | The case is not waiting for that signal. |
409 CASE_ENDED | The case has already ended. |
409 IDEMPOTENCY_CONFLICT | The same idempotency key was used with another name or other data. |
409 INSTANCE_BUSY | The case is busy right now; retry in a few seconds. |
422 SIGNAL_DATA_INVALID | The data does not fit the step’s variables; the case keeps waiting. |
Waits and loops
Section titled “Waits and loops”A loop in the diagram (for example, “check the status → if it is not ready, check again”) can only be published if it goes through at least one task: a robot, a person, an AI step or an integration, so the case never spins without waiting for anyone. If the task in the loop is automatic and fast, add a wait so the case checks every so often instead of repeating nonstop.
In the monitor
Section titled “In the monitor”While it only has open waits, the case is En espera (waiting) and the step reads Esperando hasta… (waiting until…) or Esperando el evento… (waiting for the event…), with its due time. See Monitor and incidents.
Cancelar caso (cancel case) also cancels its waits: the case will not move on when the time is up and will not accept signals.
Next steps
Section titled “Next steps”- Design on the canvas: the other steps.
- Zoan Cloud API: service accounts, keys and the signals endpoint.
- Monitor and incidents: follow and unblock cases.