# Trigger workflows

Start workflows from Stripe events, on a recurring schedule, or on demand.

A trigger is what starts a workflow run. Every workflow has one trigger, which determines when the workflow runs and what data it starts with. You choose the trigger when you [create a workflow](https://docs.stripe.com/workflows/set-up.md) by clicking **Add a trigger**.

## Trigger types

Workflows support three types of triggers:

- **Event triggers** run the workflow when something happens in your Stripe account, such as a payment succeeding, a subscription renewing, or a dispute being created.
- **Recurring schedule triggers** run the workflow automatically at times you set, such as every day at 9:00 AM or on the first day of each month.
- **On-demand triggers** run the workflow when you start it from the Dashboard or call the API, with custom input data.

A workflow uses one trigger type. Create separate workflows if you need the same workflow logic to run in more than one way, such as on demand and automatically on events.

| &nbsp; | **Event triggers** | **Recurring schedule triggers** | **On-demand triggers** |
| --- | --- | --- | --- |
| **Starts when** | A Stripe event fires | A scheduled time arrives | A user or API call initiates it |
| **Input data** | The event payload | None | Custom JSON you provide |
| **Use case** | Automated reactions to Stripe activity | Recurring batch jobs, reports, and checks | On-demand processes, human-initiated actions |
| **Volume** | One run per matching event | One run per scheduled time | One run per invocation |

## Event triggers

Event triggers start a workflow when a specific [Stripe API event](https://docs.stripe.com/api/v2/core/events.md) occurs. The workflow receives the event payload, so later steps can use fields from the object that changed.

Use event triggers when something needs to happen every time a specific change occurs in your account, such as tagging a customer after a successful payment or notifying your team when a dispute is created.

### Set up an event trigger

1. [Create a workflow](https://docs.stripe.com/workflows/set-up.md) or open an existing one in the Dashboard.
2. Click **Add a trigger**.
3. Search for an event, or select a category such as **Transactions**, **Customers**, or **Subscriptions** to browse events.
4. Select the event that starts your workflow.
5. (Optional) Add [trigger conditions](https://docs.stripe.com/workflows/define-workflows.md#trigger-conditions) to run the workflow only for events that meet specific criteria. Trigger conditions are available only for event triggers.
6. Add your workflow steps, then publish the workflow.

Each matching event starts one workflow run. For the list of supported events, see [Supported triggers](https://docs.stripe.com/workflows/define-workflows.md#supported-triggers). To trigger workflows from events on connected accounts, see [Connected account events](https://docs.stripe.com/workflows/define-workflows.md#connected-account-events).

## Recurring schedule triggers

Recurring schedule triggers start a workflow automatically on a schedule you define, such as every hour, every weekday, or on the last day of each month. Each scheduled time starts one workflow run.

Use recurring schedule triggers when:

- A task needs to run at regular intervals (a daily balance check, a weekly report)
- You want to process records in batches instead of one event at a time (loop over open invoices every morning)
- A process depends on the calendar rather than on account activity (month-end reconciliation)

### Set up a recurring schedule trigger

1. [Create a workflow](https://docs.stripe.com/workflows/set-up.md) or open an existing one in the Dashboard.
2. Click **Add a trigger**, then select **Tools**.
3. Choose **Recurring schedule**.
4. Configure the schedule. See [Schedule options](https://docs.stripe.com/workflows/triggers.md#schedule-options).
5. Click **Done**.
6. Add your workflow steps, then publish the workflow.

After you configure the schedule, the trigger shows a summary of it, such as **Every week on Monday and Wednesday at 9:00 AM PT**. Review the summary to confirm the schedule before you publish.

### Schedule options

| **Option** | **Description** |
| --- | --- |
| **Repeat every** | How often the workflow runs. Enter a number and select **Hour**, **Day**, **Week**, or **Month**. For example, enter `2` and select **Week** to run every other week. |
| **Days of the week** | Appears when you select **Week**. Select one or more days, or **Select all**. |
| **Days of the month** | Appears when you select **Month**. Select one or more days from **1st** to **31st**, **Last day of the month**, or **Select all**. |
| **Starting** | The date and time the schedule starts. The first run is the first scheduled time on or after this date and time. |
| **Timezone** | The timezone for the schedule. Search for a region or city, such as **America - Los Angeles**. |
| **Ending (optional)** | Under **Advanced**. The date and time after which the workflow stops running. Leave empty to run the schedule indefinitely. To remove an end date, click **Clear end date**. |

If you select **Week** or **Month** without choosing specific days, the schedule uses the day of the week or day of the month of the start date.

If you change the frequency, your day selections reset. Review **Days of the week** or **Days of the month** after changing the frequency.

If you select a day that doesn’t occur in every month, such as the **31st**, the workflow runs only in months that have that day. To run at the end of every month, select **Last day of the month** instead.

### Interval limits

The smallest interval is one hour. The largest interval is one year:

| **Frequency** | **Allowed values for Repeat every** |
| --- | --- |
| Hour | 1 – 8,760 |
| Day | 1 – 365 |
| Week | 1 – 52 |
| Month | 1 – 12 |

The end date must be after the start date.

### How schedule times work

The schedule runs at the time you set in the timezone you select. If you change the timezone after setting a time, the time stays the same and applies in the new timezone. For example, 9:00 AM in **Etc - UTC** becomes 9:00 AM in **America - Los Angeles**.

#### Daylight saving time

In timezones that observe daylight saving time, schedules follow the local clock. A workflow scheduled for 9:00 AM in **America - Los Angeles** runs at 9:00 AM local time all year, before and after the clocks change.

When the clocks change, some local times are skipped or repeated:

- **Clocks move forward.** Local times in the skipped hour don’t exist that day, so runs scheduled during that hour don’t happen. For example, a daily workflow scheduled for 2:30 AM in **America - New York** doesn’t run on the day the clocks move from 2:00 AM to 3:00 AM. It runs again at 2:30 AM the next day.
- **Clocks move back.** Local times in the repeated hour occur twice that day, but the workflow runs only once, at the first occurrence. For example, a daily workflow scheduled for 1:30 AM in **America - New York** runs at the first 1:30 AM, before the clocks move back.

To avoid a skipped run, schedule workflows outside the hour when the clocks change in your timezone, or use **Etc - UTC**.

### View upcoming and past runs

On the workflow’s page in the Dashboard, **Next run** in the **Details** section shows when the workflow runs next. Completed runs appear in **Recent runs**.

Throughout the Dashboard, **Next run** times display in the timezone set in your Dashboard settings, which can differ from the schedule’s timezone. For example, a workflow scheduled for 6:00 PM in **Asia - Tokyo** shows a **Next run** of 9:00 AM if your Dashboard is set to UTC.

### End or pause a schedule

- **End on a date.** Set **Ending** when you configure the schedule. After the end date and time, the workflow moves to an inactive state and doesn’t run again. If a scheduled run falls exactly on the end time, that run still happens before the workflow becomes inactive.
- **Pause.** [Deactivate the workflow](https://docs.stripe.com/workflows/set-up.md#deactivate-workflow). The workflow doesn’t run while it’s inactive. When you reactivate it, scheduled times that passed while it was inactive are skipped, and the workflow resumes at the next scheduled time. For example, if a daily workflow is inactive from Monday to Thursday, it doesn’t run for Tuesday or Wednesday. Its next run is the next scheduled time after you reactivate it.

### Recurring schedule limitations

- **Hourly minimum**: Schedules can’t run more often than once an hour.
- **Scheduled workflows run only on their schedule**: You can’t start a workflow that uses a recurring schedule trigger from the Dashboard or invoke it through the API. If you also need to run the same logic on demand, create a separate workflow with an [on-demand trigger](https://docs.stripe.com/workflows/triggers.md#on-demand-triggers), which supports both Dashboard runs and API invocation.

## On-demand triggers

On-demand triggers let you start a workflow on demand, either from the Dashboard or through an API call, with custom input data.

Use on-demand triggers when:

- A human needs to initiate a process (support agent processing a refund, ops team running a bulk update)
- An external system needs to invoke Stripe logic (your backend triggering a workflow after an internal event)
- You want to test a workflow with specific input data

### Set up an on-demand trigger

To configure a workflow with an on-demand trigger:

1. [Create a workflow](https://docs.stripe.com/workflows/set-up.md) or open an existing one in the Dashboard.
2. Click **Add a trigger**, then select **Tools**.
3. Choose **On-demand trigger**.
4. Define your input fields (optional). See [Input fields](https://docs.stripe.com/workflows/triggers.md#input-fields) for supported types.
5. Publish the workflow.

### Trigger from the Dashboard

You can trigger a workflow from the Dashboard without writing code.

1. Open the workflow in the Dashboard.
2. Click **Run workflow**.
3. Enter the input data. The input must conform to the workflow’s defined input fields.
4. Click **Run workflow**. The workflow starts immediately.

The run appears in **Recent runs** and run history shows the input data you provided.

### Invoke a trigger through the API

Trigger a workflow programmatically by calling the invoke endpoint with the workflow ID and input fields (if configured).

> Only workflows with a manual trigger and an `active` status can be invoked via API. Attempting to invoke a draft, inactive, or archived workflow returns an error.

#### Create a workflow run

```bash
curl https://api.stripe.com/v2/extend/workflows/{id}/invoke \
  -X POST \
  -H "Authorization: Bearer {{API_SECRET_KEY}}" \
  -H "Stripe-Version: {{API_VERSION}}" \
  -H "Content-Type: application/json" \
  -d '{
    "input_parameters": {
      "charge_id": "ch_1234567890",
      "reason": "customer_request"
    }
  }'
```

The API returns immediately after accepting the request — it doesn’t wait for the workflow to complete. The run may be queued briefly before execution begins. To track progress, [retrieve the run](https://docs.stripe.com/workflows/triggers.md#retrieve-a-workflow-run) or listen for [webhook events](https://docs.stripe.com/workflows/set-up.md#monitor-runs-with-webhook-events).

**Response:**

```json
{
  "id": "wfrun_abc123...",
  "object": "v2.extend.workflow_run",
  "livemode": false,
  "workflow": "wf_XYZ789...",
  "status": "started",
  "trigger": {
    "type": "manual",
    "manual": {
      "input_parameters": {
        "charge_id": "ch_1234567890",
        "reason": "customer_request"
      }
    }
  },
  "created": "2026-03-19T14:05:00.000+0000",
  "status_details": {
    "started": {}
  },
  "status_transitions": {
    "started_at": "2026-03-19T14:05:00.000+0000"
  }
}
```

#### Retrieve a workflow run

Use the run ID from the invoke response to check the status of a run.

```bash
curl https://api.stripe.com/v2/extend/workflow_runs/{id} \
  -H "Authorization: Bearer {{API_SECRET_KEY}}" \
  -H "Stripe-Version: {{API_VERSION}}"
```

The response includes the current status (`started`, `succeeded`, or `failed`) and details about the outcome.

```json
{
  "id": "wfrun_abc123...",
  "object": "v2.extend.workflow_run",
  "livemode": false,
  "workflow": "wf_XYZ789...",
  "status": "succeeded",
  "trigger": {
    "type": "manual",
    "manual": {
      "input_parameters": {
        "charge_id": "ch_1234567890",
        "reason": "customer_request"
      }
    }
  },
  "created": "2026-03-19T14:05:00.000+0000",
  "status_details": {
    "succeeded": {}
  },
  "status_transitions": {
    "started_at": "2026-03-19T14:05:00.000+0000",
    "succeeded_at": "2026-03-19T14:15:00.000+0000"
  }
}
```

If a run fails, `status_details.failed` includes the error message:

```json
{
  "status": "failed",
  "status_details": {
    "failed": {
      "error_message": "During API call to stripe.api_call_post_v1_customers: Field \"name\" is required."
    }
  },
  "status_transitions": {
    "started_at": "2026-03-19T14:05:00.000+0000",
    "failed_at": "2026-03-19T14:10:00.000+0000"
  }
}
```

#### List workflow runs

List runs across all workflows, or filter by workflow ID or status.

```bash
curl "https://api.stripe.com/v2/extend/workflow_runs?workflow=wf_XYZ789&status=failed" \
  -H "Authorization: Bearer {{API_SECRET_KEY}}" \
  -H "Stripe-Version: {{API_VERSION}}"
```

The list endpoint returns runs in descending creation order. You can filter by:

- `workflow` — one or more workflow IDs
- `status` — one or more of `started`, `succeeded`, `failed`

> The list endpoint omits `trigger.manual.input_parameters` and `status_details` for performance. Use the [retrieve endpoint](https://docs.stripe.com/workflows/triggers.md#retrieve-a-workflow-run) to get full run details.

#### Idempotency keys

Include an `Idempotency-Key` header to prevent duplicate runs. If a request with the same idempotency key has already created a run, the API returns the original response. If the key matches but the input differs, the API returns an error.

```bash
curl https://api.stripe.com/v2/extend/workflows/{id}/invoke \
  -X POST \
  -H "Authorization: Bearer {{API_SECRET_KEY}}" \
  -H "Stripe-Version: {{API_VERSION}}" \
  -H "Idempotency-Key: refund-ch_1234567890-20260308" \
  -H "Content-Type: application/json" \
  -d '{
    "input_parameters": {
      "charge_id": "ch_1234567890"
    }
  }'
```

#### Error responses

| **Status** | **Code** | **Meaning** |
| --- | --- | --- |
| 400 | `invalid_workflow_input_parameters` | One or more input field values failed validation. |
| 400 | `workflow_not_invokable` | The workflow doesn’t have a manual trigger, or isn’t in an active state. |
| 401 | — | Invalid or expired API key. |
| 404 | `not_found` | Workflow ID not found. |

### Input fields

Define the input your workflow expects by configuring input fields on the on-demand trigger in the Dashboard. Input fields specify which fields are required, their types, and descriptions.

#### Supported input types

| **Input type** | **Description** |
| --- | --- |
| Text (`string`) | Text values (IDs, names, email addresses) |
| Integer (`integer`) | Numeric values (amounts, counts) |
| Decimal (`decimal`) | Decimal numbers (prices, percentages) |
| True/false (`boolean`) | True/false flags |
| Enum (`enum`) | A predefined set of allowed values |
| Array (`array`) | Lists of values |
| Empty payload | The workflow accepts no input fields |

> In public preview, input field schemas are not exposed in the API response when retrieving a workflow configuration. You can view and configure input fields in the Dashboard.

#### Using Stripe object IDs in input fields

If your input includes Stripe object IDs (for example, `charge_id: "ch_123"` or `customer_id: "cus_456"`), you can add a retrieve action in your workflow to fetch the full object. For example, pass a `charge_id` as an input field, then add a **Retrieve a charge** action that uses that ID. The full object’s fields become available in subsequent workflow steps, the same way event payload fields are available in event-triggered workflows.

### On-demand limitations

- **No webhook ingestion**: Workflows can’t accept arbitrary HTTP POST requests as a generic webhook endpoint. Use the invoke API with the workflow ID.
- **Asynchronous only**: The API returns immediately after starting the run. There’s no synchronous mode that waits for workflow completion. Use the [retrieve endpoint](https://docs.stripe.com/workflows/triggers.md#retrieve-a-workflow-run) or [webhook events](https://docs.stripe.com/workflows/set-up.md#monitor-runs-with-webhook-events) to track outcomes.
- **No third-party event triggers**: You can’t trigger workflows directly from non-Stripe events. Use the invoke API from your backend to bridge external events into Workflows.
- **Event-triggered workflows can’t be invoked via API**: Only workflows configured with a manual trigger support API invocation.

### Permissions

Programmatic invocation requires the workflow invoke permission, which is included in the default Workflows role. You can scope API keys to include or exclude this permission.

## See also

- [Use cases](https://docs.stripe.com/workflows/use-cases.md)
- [Set up workflows](https://docs.stripe.com/workflows/set-up.md)
