Wait Event Step
Use the wait_event step to pause a workflow until a matching external event arrives, then resume with the submitted payload. This feature is currently in Beta.
The wait_event step pauses a workflow until an external system submits a matching event, then resumes the workflow with the submitted event payload.
Use it to hold a payout until a fraud check passes, gate a downstream transfer until a buyer confirms delivery, or wait for an external partner's webhook before proceeding. If the event does not arrive within the timeout, the step either fails the workflow or continues, depending on the on_timeout setting.
The
wait_eventstep and its related submission and wait-state endpoints are currently in Beta. Behavior and endpoint availability may change before general availability.
Parameters
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
event_name | string | Yes | None | Name of the event the step waits for. Allowed characters: ^[a-zA-Z][a-zA-Z0-9_.:-]{0,63}$. Used as the event_name field on the submission call. |
timeout | string | No | PT24H | ISO 8601 duration for how long to wait per attempt. Examples: PT15M, PT24H, P3D. Maximum total wait is 7 days, regardless of max_retries. |
on_timeout | string | No | fail | What to do when the timeout elapses. fail ends the workflow with status failed. continue lets the workflow proceed past the step. |
max_retries | int | No | 0 | Number of additional wait windows after the first timeout. 0 means a single window. Maximum 10. Total wait = timeout × (1 + max_retries), capped at 7 days. |
payload_schema | object | No | None | A JSON Schema document. When set, the event submission's payload is validated against it before the workflow continues. |
description | string | No | None | Free-form description, useful for ops dashboards. |
Outputs
| Field | Description |
|---|---|
status | completed if the event arrived; timed_out if the timeout elapsed and on_timeout: continue was set. |
event_received | true if an event arrived; false if the step continued past a timeout. |
attempt | Which retry window the event arrived in (1-indexed). |
max_attempts | The configured 1 + max_retries. |
timed_out | true if the step timed out at least once. |
event_payload | The full payload submitted with the event. Available downstream as ${steps.<name>.output.event_payload.<field>}. |
event_name | Echo of the configured event_name. |
message | Human-readable status message. |
How an event reaches your workflow
sequenceDiagram
participant W as Workflow (running)
participant DB as wait_states
participant E as External system
participant API as Workflow API
W->>DB: insert wait_state, status=waiting
W->>W: open signal channel + start timer
E->>API: POST /v1/instances/:id/events
API->>DB: status=completed
API->>W: deliver signal
W->>W: continue with event_payload
When the workflow reaches a wait_event step:
- A
wait_staterow is created withstatus=waiting. It surfaces via Observing Workflow Runs. - The workflow opens a signal channel and starts the timeout timer.
- An external system calls
POST /v1/instances/:id/eventswith{ "event_name": "...", "payload": {...} }. If apayload_schemawas declared, the payload is validated against it. - On success the wait state moves to
status=completed, the workflow receives the signal, and it continues. - On timeout, behaviour follows
on_timeoutandmax_retries.
The submission endpoint, the wait-state listing, and the waiting-instance discovery endpoints are all currently in Beta.
Example
A two-leg payout where the second leg is held until a confirmation event arrives.
version: 1
name: "marketplace-payout"
description: "Hold the merchant's share until the buyer confirms delivery"
steps:
- name: "send_to_escrow"
send_money:
source:
type: "wallet"
account: "${platform_wallet}"
destination:
type: "wallet"
account: "${escrow_wallet}"
account_name: "Escrow Holding"
bic: "PAEYPHM2XXX"
provider: "paymongo"
amount: "${input.gross_amount}"
currency: "PHP"
- name: "wait_for_confirmation"
wait_event:
event_name: "delivery.confirmed"
timeout: "P3D"
on_timeout: "fail"
payload_schema:
type: "object"
required: ["order_id"]
properties:
order_id:
type: "string"
- send_money:
source:
type: "wallet"
account: "${escrow_wallet}"
destination:
type: "wallet"
account: "${merchant_wallet}"
account_name: "${merchant_name}"
bic: "PAEYPHM2XXX"
provider: "paymongo"
amount: "${input.merchant_share}"
currency: "PHP"
notes: "Confirmed: ${steps.wait_for_confirmation.output.event_payload.order_id}"When the buyer confirms delivery, your application calls:
curl --request POST 'https://workflow-api.paymongo.com/v1/instances/${INSTANCE_ID}/events' \
--header 'Authorization: Basic ${YOUR_BASIC_TOKEN}' \
--header 'Organization-Id: ${YOUR_ORG_ID}' \
--header 'Content-Type: application/json' \
--data '{
"event_name": "delivery.confirmed",
"payload": {
"order_id": "ord_abc123"
}
}'See Also
- Observing Workflow Runs: find waiting instances and inspect wait states.
- Hold a Payout Until Confirmed: the production-grade marketplace pattern.
- Send Money Step: the typical step bracketing a
wait_event.
Updated about 5 hours ago