Workflows API
Use the workflows API to create and manage workflows for a Buildkite Test Engine test suite. Each workflow has one monitor, optional execution tag filters, and actions to run when a test alarms or recovers.
In every endpoint, {org.slug} is the organization slug, {suite.slug} accepts a suite slug or UUID, and {workflow.id} is a workflow UUID.
These endpoints require an API access token. OIDC tokens are not accepted.
Create a workflow
This example creates a transition count workflow that adds the flaky label when a test alarms and removes it when the test recovers:
curl -H "Authorization: Bearer $TOKEN" \
-X POST "https://api.buildkite.com/v2/analytics/organizations/{org.slug}/suites/{suite.slug}/workflows" \
-H "Content-Type: application/json" \
-d '{
"monitor": {
"type": "transition_count",
"window_size": 100,
"alarm_threshold": 0.1,
"recover_threshold": 0.05
},
"filters": [
{ "key": "scm.branch", "operator": "is", "value": "main" }
],
"alarm_actions": [
{ "type": "add_label", "label": "flaky" }
],
"recover_actions": [
{ "type": "remove_label", "label": "flaky" }
]
}'
{
"id": "01234567-89ab-4cde-8fab-0123456789ab",
"url": "https://api.buildkite.com/v2/analytics/organizations/example-org/suites/example-suite/workflows/01234567-89ab-4cde-8fab-0123456789ab",
"web_url": "https://buildkite.com/organizations/example-org/analytics/suites/example-suite/workflows/01234567-89ab-4cde-8fab-0123456789ab/events",
"monitor": {
"type": "transition_count",
"window_size": 100,
"alarm_threshold": 0.1,
"recover_threshold": 0.05
},
"filters": [
{ "key": "scm.branch", "operator": "is", "value": "main" }
],
"alarm_actions": [
{ "type": "add_label", "label": "flaky" }
],
"recover_actions": [
{ "type": "remove_label", "label": "flaky" }
],
"created_at": "2026-10-19T01:00:00.000Z",
"updated_at": "2026-10-19T01:00:00.000Z",
"created_by": null
}
Required request body properties:
| Property | Description | ||
|---|---|---|---|
| Property | monitor |
Description | An object containing a type and all configuration fields for that monitor type. The API does not supply monitor defaults. |
Optional request body properties:
| Property | Description | ||
|---|---|---|---|
| Property | filters |
Description | An array of up to four tag filters. Defaults to []. The API does not add a default branch filter. |
| Property | alarm_actions |
Description | An array of up to seven actions to run when a test alarms. Defaults to []. |
| Property | recover_actions |
Description | An array of up to seven actions to run when a test recovers. Defaults to []. Must be empty for a new_test monitor. |
Required scope: write_suites
Success response: 201 Created
List workflows
Returns a paginated list of a suite's workflows, newest first. Each item has the workflow data model fields.
curl -H "Authorization: Bearer $TOKEN" \
-X GET "https://api.buildkite.com/v2/analytics/organizations/{org.slug}/suites/{suite.slug}/workflows"
Required scope: read_suites
Success response: 200 OK
Get a workflow
Returns a single workflow with the workflow data model fields.
curl -H "Authorization: Bearer $TOKEN" \
-X GET "https://api.buildkite.com/v2/analytics/organizations/{org.slug}/suites/{suite.slug}/workflows/{workflow.id}"
Required scope: read_suites
Success response: 200 OK
Update a workflow
Updates the supplied fields and returns the updated workflow. All request body properties are optional. Omitted properties keep their current values, including individual fields within monitor. The monitor's type cannot be changed.
curl -H "Authorization: Bearer $TOKEN" \
-X PATCH "https://api.buildkite.com/v2/analytics/organizations/{org.slug}/suites/{suite.slug}/workflows/{workflow.id}" \
-H "Content-Type: application/json" \
-d '{
"monitor": {
"alarm_threshold": 0.2
},
"recover_actions": []
}'
This example changes only the alarm threshold and removes all recovery actions. The remaining monitor settings, filters, and alarm actions stay unchanged.
Each supplied filters, alarm_actions, or recover_actions array replaces that entire list. Send [] to clear a list. Include every entry you want to retain when replacing a list. Use the same monitor, filter, and action fields as for creation. Only fields belonging to the workflow's current monitor type are accepted.
Required scope: write_suites
Success response: 200 OK
Delete a workflow
Deletes the workflow. A subsequent request for the deleted workflow returns 404 Not Found.
curl -H "Authorization: Bearer $TOKEN" \
-X DELETE "https://api.buildkite.com/v2/analytics/organizations/{org.slug}/suites/{suite.slug}/workflows/{workflow.id}"
Required scope: write_suites
Success response: 204 No Content
Monitor configuration
The monitor.type selects the monitor and its configuration fields. All fields listed for a type are required on creation. Thresholds must be JSON numbers, not strings. Recovery thresholds must be strictly lower than alarm thresholds.
The probabilistic flakiness monitor is only available on Enterprise plans.
| Type | Configuration fields | ||
|---|---|---|---|
| Type | transition_count |
Configuration fields |
window_size: integer from 2 to 1000. alarm_threshold and recover_threshold: numbers from 0 to 1, with up to three decimal places. Requires a nonempty scm.branch filter. |
| Type | probabilistic_flakiness |
Configuration fields |
alarm_threshold: number from 0.025 to 1. recover_threshold: number from 0 to 1. |
| Type | duration_threshold |
Configuration fields |
aggregation: "p50". evaluation_window: integer from 1 to 100. alarm_threshold_ms and recover_threshold_ms: integers from 0 to 3600000, in milliseconds. |
| Type | passed_on_retry |
Configuration fields | No additional configuration fields. |
| Type | new_test |
Configuration fields | No additional configuration fields. The suite must have at least one run before creation, and recover_actions must be empty. |
The REST API uses milliseconds for duration thresholds. The workflow interface uses seconds.
Filter configuration
Each entry in filters selects execution tags to include in the monitor's input. All three fields are required:
| Field | Description | ||
|---|---|---|---|
| Field | key |
Description | A nonempty tag key, such as "scm.branch". Must start with a letter, contain only letters, digits, underscores, periods, or hyphens, and be at most 64 bytes. Mutable tags cannot be used for new or changed filters. |
| Field | operator |
Description | One of "is", "is_not", or "starts_with". |
| Field | value |
Description | A nonempty tag value, at most 128 bytes. |
A workflow accepts up to four filters. Keys and values have leading and trailing whitespace removed. Unlike workflows configured in the interface, API-created workflows do not automatically receive a default branch filter. Supply a scm.branch filter explicitly when you want to monitor only your default branch.
Action configuration
Each entry in alarm_actions or recover_actions requires a type and all fields listed for that type. See Alarm and recover actions for action behavior and notification templates.
| Type | Configuration fields | ||
|---|---|---|---|
| Type | add_label |
Configuration fields |
label: a normalized label name, from one to 25 characters. Use lowercase words separated by hyphens. A missing label is created in the suite. |
| Type | remove_label |
Configuration fields |
label: the same format as add_label. |
| Type | change_state |
Configuration fields |
state: "enabled", "muted", or "skipped". Requires test state management and access to the requested state on the suite. |
| Type | send_webhook_notification |
Configuration fields |
endpoint: an HTTP or HTTPS URL, up to 2048 characters. For example, "https://example.com/webhook". |
| Type | send_slack_notification |
Configuration fields |
slack_workspace_id: the UUID of an enabled Slack workspace notification service in your organization. channel: a nonempty channel string. message_template: a nonempty Liquid template, up to 1000 characters. |
| Type | create_linear_issue |
Configuration fields |
linear_team_id: the UUID of a team accessible to your organization's Linear integration. title_template and description_template: nonempty Liquid templates. Requires an enabled Linear integration. |
Each action list accepts up to seven entries. The new_test monitor accepts alarm actions only.
The workflow actions available to you depend on your billing plan.
Workflow data model
Create, get, and update operations return a workflow object. List operations return an array of these objects. The create example shows the response shape.
| Field | Description | ||
|---|---|---|---|
| Field | id |
Description | Workflow UUID. Read-only. |
| Field | url |
Description | Canonical API URL. Read-only. |
| Field | web_url |
Description | Workflow events URL in the Buildkite interface. Read-only. |
| Field | monitor |
Description | Monitor type and configuration. |
| Field | filters |
Description | Array of tag filters. |
| Field | alarm_actions |
Description | Array of alarm actions. |
| Field | recover_actions |
Description | Array of recovery actions. |
| Field | created_at |
Description | Creation timestamp in ISO 8601 format. Read-only. |
| Field | updated_at |
Description | Last update timestamp in ISO 8601 format. Read-only. |
| Field | created_by |
Description | Creator object with id, graphql_id, name, and email, or null. Read-only. |
All fields are present in every workflow response. Send only writable fields in create and update requests. Monitor and action types may be extended, so clients should ignore unknown response fields and handle unknown types.
Webhook endpoints are returned in full only when the caller can edit the suite. Otherwise, the endpoint is masked after the host, for example, https://example.com/[REDACTED].
Error responses
Requests reject unknown fields and incorrect JSON types. Validation failures return 422 Unprocessable Entity, with a JSON Pointer in each error's field identifying the invalid request value:
{
"message": "Validation Failed",
"errors": [
{
"field": "/monitor/recover_threshold",
"code": "must be less than alarm threshold"
}
]
}
| Status | Description | ||
|---|---|---|---|
| Status | 400 Bad Request |
Description | The request is malformed or pagination values are invalid. |
| Status | 401 Unauthorized |
Description | Authentication failed. |
| Status | 403 Forbidden |
Description | The token lacks the required scope, the caller lacks suite permissions, or the plan does not include the requested feature. |
| Status | 404 Not Found |
Description | The organization, suite, or workflow was not found. |
| Status | 422 Unprocessable Entity |
Description | Validation failed, or the suite has reached its workflow limit. |
| Status | 503 Service Unavailable |
Description | Linear could not be reached while validating a new Linear action. Retry the request later. |