Events and parameters
When a Workflow is triggered, it can receive an optional event. This event can include data that your Workflow can act on, including request details, user data fetched from your database (such as D1 or KV) or from a webhook, or messages from a Queue consumer.
Events are a powerful part of a Workflow, as you often want a Workflow to act on data. Because a given Workflow instance executes durably, events are a useful way to provide a Workflow with data that should be immutable (not changing) and/or represents data the Workflow needs to operate on at that point in time.
You can pass parameters to a Workflow in three ways:
- As an optional argument to the
create
method on a Workflow binding when triggering a Workflow from a Worker. - Via the
--params
flag when using thewrangler
CLI to trigger a Workflow. - Via the
step.waitForEvent
API, which allows a Workflow instance to wait for an event (and optional data) to be received while it is running. Workflow instances can be sent events from external services over HTTP or via the Workers API for Workflows.
You can pass any JSON-serializable object as a parameter.
export default { async fetch(req, env) { let someEvent = { url: req.url, createdTimestamp: Date.now() }; // Trigger our Workflow // Pass our event as the second parameter to the `create` method // on our Workflow binding. let instance = await env.MY_WORKFLOW.create({ id: await crypto.randomUUID(), params: someEvent, });
return Response.json({ id: instance.id, details: await instance.status(), });
return Response.json({ result }); },};
export default { async fetch(req: Request, env: Env) { let someEvent = { url: req.url, createdTimestamp: Date.now() } // Trigger our Workflow // Pass our event as the second parameter to the `create` method // on our Workflow binding. let instance = await env.MY_WORKFLOW.create({ id: await crypto.randomUUID(), params: someEvent });
return Response.json({ id: instance.id, details: await instance.status(), });
return Response.json({ result }); },};
To pass parameters via the wrangler
command-line interface, pass a JSON string as the second parameter to the workflows trigger
sub-command:
npx wrangler@latest workflows trigger workflows-starter '{"some":"data"}'
🚀 Workflow instance "57c7913b-8e1d-4a78-a0dd-dce5a0b7aa30" has been queued successfully
A running Workflow can wait for an event (or events) by calling step.waitForEvent
within the Workflow, which allows you to send events to the Workflow in one of two ways:
- Via the Workers API binding: call
instance.sendEvent
to send events to specific workflow instances. - Using the REST API (HTTP API)'s Events endpoint.
Because waitForEvent
is part of the WorkflowStep
API, you can call it multiple times within a Workflow, and use control flow to conditionally wait for an event.
Calling waitForEvent
requires you to specify an type
, which is used to match the corresponding type
when sending an event to a Workflow instance.
For example, to wait for billing webhook:
export class MyWorkflow extends WorkflowEntrypoint { async run(event, step) { // Other steps in your Workflow let event = await step.waitForEvent( "receive invoice paid webhook from Stripe", { type: "stripe-webhook", timeout: "1 hour" }, ); // Rest of your Workflow }}
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> { async run(event: WorkflowEvent<Params>, step: WorkflowStep) { // Other steps in your Workflow let event = await step.waitForEvent<IncomingStripeWebhook>("receive invoice paid webhook from Stripe", { type: "stripe-webhook", timeout: "1 hour" }) // Rest of your Workflow }}
The above example:
- Calls
waitForEvent
with atype
ofstripe-webhook
- the correspondingsendEvent
call would thus beawait instance.sendEvent({type: "stripe-webhook", payload: webhookPayload})
. - Uses a TypeScript type parameter ↗ to type the return value of
step.waitForEvent
as ourIncomingStripeWebhook
. - Continues on with the rest of the Workflow.
Workflow instances that are waiting on events using the waitForEvent
API can be sent events using the instance.sendEvent
API:
export default { async fetch(req, env) { const instanceId = new URL(req.url).searchParams.get("instanceId"); const webhookPayload = await req.json();
let instance = await env.MY_WORKFLOW.get(instanceId); // Send our event, with `type` matching the event type defined in // our step.waitForEvent call await instance.sendEvent({ type: "stripe-webhook", payload: webhookPayload, });
return Response.json({ status: await instance.status(), }); },};
export default { async fetch(req: Request, env: Env) { const instanceId = new URL(req.url).searchParams.get("instanceId") const webhookPayload = await req.json<Payload>()
let instance = await env.MY_WORKFLOW.get(instanceId); // Send our event, with `type` matching the event type defined in // our step.waitForEvent call await instance.sendEvent({type: "stripe-webhook", payload: webhookPayload})
return Response.json({ status: await instance.status(), }); },};
- Similar to the
waitForEvent
example in this guide, thetype
property in ourwaitForEvent
andsendEvent
fields must match. - To send multiple events to a Workflow that has multiple
waitForEvent
calls, callsendEvent
with the correspondingtype
property set. - Events can also be sent using the REST API (HTTP API)'s Events endpoint.
By default, the WorkflowEvent
passed to the run
method of your Workflow definition has a type that conforms to the following, with payload
(your data), timestamp
, and instanceId
properties:
export type WorkflowEvent<T> = { // The data passed as the parameter when the Workflow instance was triggered payload: T; // The timestamp that the Workflow was triggered timestamp: Date; // ID of the current Workflow instance instanceId: string;};
You can optionally type these events by defining your own type and passing it as a type parameter ↗ to the WorkflowEvent
:
// Define a type that conforms to the events your Workflow instance is// instantiated withinterface YourEventType { userEmail: string; createdTimestamp: number; metadata?: Record<string, string>;}
When you pass your YourEventType
to WorkflowEvent
as a type parameter, the event.payload
property now has the type YourEventType
throughout your workflow definition:
// Import the Workflow definitionimport { WorkflowEntrypoint, WorkflowStep, WorkflowEvent} from 'cloudflare:workers';
export class MyWorkflow extends WorkflowEntrypoint { // Pass your type as a type parameter to WorkflowEvent // The 'payload' property will have the type of your parameter. async run(event: WorkflowEvent<YourEventType>, step: WorkflowStep) { let state = step.do("my first step", async () => { // Access your properties via event.payload let userEmail = event.payload.userEmail let createdTimestamp = event.payload.createdTimestamp })
step.do("my second step", async () => { /* your code here */ ) }}
You can also provide a type parameter to the Workflows
type when creating (triggering) a Workflow instance using the create
method of the Workers API. Note that this does not propagate type information into the Workflow itself, as TypeScript types are a build-time construct. To provide the type of an incoming WorkflowEvent
, refer to the TypeScript and type parameters section of the Workflows documentation.
Was this helpful?
- Resources
- API
- New to Cloudflare?
- Products
- Sponsorships
- Open Source
- Support
- Help Center
- System Status
- Compliance
- GDPR
- Company
- cloudflare.com
- Our team
- Careers
- 2025 Cloudflare, Inc.
- Privacy Policy
- Terms of Use
- Report Security Issues
- Trademark