Trigger workflows programmaticallyPublic preview
Run a workflow on demand from the Dashboard or via the API.
By default, workflows trigger on Stripe events: when a payment succeeds, a subscription renews, or a dispute is created. Programmatic triggers let you start a workflow on demand, either from the Dashboard or through an API call, with custom input data.
Use programmatic 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
When to use programmatic vs. event-based triggers
A workflow uses one trigger type — either event-based or programmatic, not both. If you need the same workflow logic to run both automatically (on events) and on demand, create separate workflows.
| Event-based triggers | Programmatic triggers | |
|---|---|---|
| Starts when | A Stripe event fires | A user or API call initiates it |
| Input data | The event payload | Custom JSON you provide |
| Use case | Automated reactions to Stripe activity | On-demand processes, human-initiated actions |
| Volume | One run per matching event | One run per invocation |
Set up an on-demand trigger
To configure a workflow with a programmatic trigger:
- Create a workflow or open an existing one in the Dashboard.
- Click Add a trigger, then select Tools.
- Choose On-demand trigger.
- Define your input fields (optional). See Input fields for supported types.
- Publish the workflow.
Trigger from the Dashboard
You can trigger a workflow from the Dashboard without writing code.
- Open the workflow in the Dashboard.
- Click Run workflow.
- Enter the input data. The input must conform to the workflow’s defined input fields.
- 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
activestatus can be invoked via API. Attempting to invoke a draft, inactive, or archived workflow returns an error.
Create a workflow run
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 or listen for webhook events.
Response:
{ "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.
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.
{ "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_ includes the error message:
{ "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.
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 IDsstatus— one or more ofstarted,succeeded,failed
The list endpoint omits
trigger.andmanual. input_ parameters status_for performance. Use the retrieve endpoint to get full run details.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.
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_ | One or more input field values failed validation. |
| 400 | workflow_ | The workflow doesn’t have a manual trigger, or isn’t in an active state. |
| 401 | — | Invalid or expired API key. |
| 404 | not_ | Workflow ID not found. |
Webhook events
Stripe emits webhook events when workflow runs change status. You can listen for these events to trigger downstream actions or monitor run outcomes without polling. These events fire for both API-invoked and event-triggered workflow runs.
| Event | Fires when | Notes |
|---|---|---|
v2. | A workflow run begins executing | Fires for both API-invoked and event-triggered runs. |
v2. | A workflow run completes successfully | Output values are not included (they can contain PII). |
v2. | A workflow run fails | Pull model includes failure details (error_, dashboard_). Push model omits error details (PII risk). |
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) |
Number (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 |
Public preview
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_ or customer_), you can add a retrieve action in your workflow to fetch the full object. For example, pass a charge_ 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.
Limitations
- One trigger type per workflow. A workflow uses either event-based triggers or programmatic triggers, not both.
- No scheduled or recurring triggers. Programmatic triggers are on-demand only. There’s no cron, interval, or calendar-based scheduling.
- 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 or 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.