Skip to main content
Private beta. This feature is only available to some organizations right now.Request access and we’ll turn webhooks on for your organization and send you the prerelease packages. Webhooks are open source, so they work self-hosted too. APIs may change before general availability.
A waiter pauses a run until a matching delivery arrives on an endpoint. Use it when your task starts something in another system and needs to know when that system reports back: a payment that settles, a build that finishes, a document that gets signed.
/trigger/checkout.ts
While the run waits it is suspended, so it uses no compute. The endpoint’s other subscribers still receive the delivery.

Create before you act

A waiter only matches deliveries that arrive after it was created. Create it before the call that makes the provider send the webhook, as above, or a fast provider can deliver the event before anything is waiting for it. Match on values you control, such as your own order id in the provider object’s metadata. Two runs waiting for the same values are both resumed by the delivery.

Matching

match maps paths to the scalar each must equal. Paths use the same namespaces as a filter: A waiter can match up to five paths, and each value is a string, number or boolean. Paths are checked against the endpoint’s event type at build time: an unknown field on a typed event, a path to an object, or a path without a namespace is a type error. The API refuses the same paths at create time. For conditions that aren’t equality, add a filter. It is checked after match:

The result

webhooks.waiter.wait(waiter) returns a result you can check, and .unwrap() returns the output or throws:
timeout accepts a duration such as "30m" or a Date. It defaults to 24 hours and can be up to 90 days. A waiter that times out fails the wait with WaitpointTimeoutError. A waiter is a waitpoint: its id starts with waitpoint_ and it is tagged webhook:<endpoint id> plus any tags you pass (up to 10).

Providers that take a callback URL

Some providers accept a webhook URL per request instead of one account-wide URL, such as Replicate’s webhook parameter. Omit match and the waiter gets its own URL:
A delivery to waiter.url is verified with the endpoint’s source, resumes only that waiter, and is not sent to the endpoint’s subscribers.

Creating from your backend

webhooks.waiter.create also works outside a run, for example in the API route that starts a checkout. Pass the waiter, or its id, to a task that waits on it:
The same operations are on the REST API: POST /api/v1/webhooks/endpoints/{endpointId}/waiters with match, filter, timeout, tags and idempotencyKey, and POST /api/v1/webhooks/waiters/{waiterId}/cancel. endpointId is the endpoint’s declared id or its wh_ id.

Retries and idempotency

Pass an idempotencyKey so a task can be retried without losing its webhook. A create with a key it has seen returns the original waiter, with isCached: true, even if it has already completed, and waiting on a completed waiter returns its event straight away. Inside a task a string key is scoped to the run, as it is for trigger(), so a retried attempt gets the waiter (and the event) the attempt before it created:
Use idempotencyKeys.create(key, { scope }) for a key scoped to one attempt or shared across runs, and idempotencyKeyTTL to set how long the key lasts. Without a key every call creates a new waiter, and a waiter only matches deliveries that arrive after it. If an attempt fails after its webhook arrived, the retry’s new waiter waits for an event the provider already sent.

Cancelling

webhooks.waiter.cancel(waiter) frees the waiter’s slot and fails its wait with WebhookWaiterCancelledError. If a delivery has already claimed the waiter, the cancel is too late and the run resumes with that delivery:

Errors

webhooks.waiter.create throws a typed error when nothing was created:

Limits

On Trigger.dev Cloud the per-endpoint and per-environment limits depend on your plan. Self-hosted installs can change them with WEBHOOK_WAITER_MAX_PER_ENDPOINT, WEBHOOK_WAITER_MAX_PER_ENVIRONMENT and WEBHOOK_WAITER_MAX_SHAPES. A delivery that resumes waiters shows one Waiting runs row on its delivery page with how many matched, resumed and failed. A delivery that arrives while runs are waiting but matches none of them, and no subscriber takes, is UNMATCHED.