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_event step and its related submission and wait-state endpoints are currently in Beta. Behavior and endpoint availability may change before general availability.

Parameters

KeyTypeRequiredDefaultDescription
event_namestringYesNoneName 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.
timeoutstringNoPT24HISO 8601 duration for how long to wait per attempt. Examples: PT15M, PT24H, P3D. Maximum total wait is 7 days, regardless of max_retries.
on_timeoutstringNofailWhat to do when the timeout elapses. fail ends the workflow with status failed. continue lets the workflow proceed past the step.
max_retriesintNo0Number 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_schemaobjectNoNoneA JSON Schema document. When set, the event submission's payload is validated against it before the workflow continues.
descriptionstringNoNoneFree-form description, useful for ops dashboards.

Outputs

FieldDescription
statuscompleted if the event arrived; timed_out if the timeout elapsed and on_timeout: continue was set.
event_receivedtrue if an event arrived; false if the step continued past a timeout.
attemptWhich retry window the event arrived in (1-indexed).
max_attemptsThe configured 1 + max_retries.
timed_outtrue if the step timed out at least once.
event_payloadThe full payload submitted with the event. Available downstream as ${steps.<name>.output.event_payload.<field>}.
event_nameEcho of the configured event_name.
messageHuman-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:

  1. A wait_state row is created with status=waiting. It surfaces via Observing Workflow Runs.
  2. The workflow opens a signal channel and starts the timeout timer.
  3. An external system calls POST /v1/instances/:id/events with { "event_name": "...", "payload": {...} }. If a payload_schema was declared, the payload is validated against it.
  4. On success the wait state moves to status=completed, the workflow receives the signal, and it continues.
  5. On timeout, behaviour follows on_timeout and max_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