Skip to main content
Cypress CloudFree Trial

Run Cancellation API

caution

This API is experimental. Breaking changes are unlikely, but may be made if necessary.

A run can be canceled manually by opening Cypress Cloud and clicking Cancel on the run, or configuring Auto Cancellation to stop a run automatically once failures cross a threshold.

Neither helps when the decision to stop a run is made somewhere else entirely, for example:

  • A deployment pipeline that cancels in-flight test runs for a commit that has already been superseded by a newer push.
  • A separate CI job or orchestrator that determines the tests are no longer needed and frees up CI machines immediately.
  • An internal tool that lets a developer cancel a run without needing Cypress Cloud dashboard access.

In these cases, your CI process will cancel the jobs that are running Cypress, and the Cypress Cloud run will be left in an in-progress state, awaiting further communication from your CI, until your Project's configured Run Timeout expires.

Why use the Run Cancellation API​

The Run Cancellation API lets you cancel a run with a single authenticated HTTP request, using the same project ID and record key credentials you already use to record the run.

Canceling through the API has the same effect as canceling manually from the dashboard: the run is marked Canceled, run.completed webhooks fire, and any in-progress cypress run --record calls for the run exit with an error. See What happens when a run is canceled? for the full list of effects.

This is especially useful when:

  • You want to use Re-run optimization to execute only the tests that did not pass in a previously canceled run.
  • You want to trigger run.completed webhooks in a timely manner after your CI has stopped.
  • You want any other end-of-run integrations like GitHub or Slack to happen at the moment of the CI cancellation, not after the Run Timeout expires.
  • You want Cypress Cloud MCP and CLI to reflect the intentional canceled state immediately when working with results, instead of a partial "timing out" state.
caution

Cypress Run exit code in CI

Cancellation of a run does not change its exit code. Any cypress run --record process that's still executing specs for that run exits non-zero (1), the same as it would if tests had actually failed.

Cypress prints Exiting with non-zero exit code because the run was canceled. to the console when this happens, but the exit code itself doesn't distinguish a cancellation from a real test failure.

Note: If you call this API from a step that runs separately from the test job itself, the canceled run's own CI job will report as failed rather than canceled. This may happen example in deployment-pipeline and orchestrator use cases. You should account for that in the job that ran the canceled specs, so a run you intentionally canceled doesn't get treated as a broken build.

Endpoint​

POST https://api.cypress.io/runs/cancel

Requests are authenticated with your project ID and record key, the same credentials used to record the run.

Request body​

The request body is JSON. projectId and recordKey are always required, and the run is identified by exactly one of runUrl or runNumber.

PropertyTypeRequiredDescription
projectIdstringYesThe project ID of the run.
recordKeystringYesA valid record key for the project.
runUrlstringConditionalThe Cypress Cloud run URL (Cypress prints this when a run starts). Provide this or runNumber.
runNumbernumberConditionalThe run's sequential number within the project. Provide this or runUrl.

Example: fetch​

const response = await fetch('https://api.cypress.io/runs/cancel', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
projectId: 'abc123',
recordKey: 'f858a2bc-b469-4e48-be67-0876339ee7e1',
runUrl: 'https://cloud.cypress.io/projects/abc123/runs/42',
// runNumber: 42, // optional, in lieu of runUrl
}),
})

const result = await response.json()
console.log(result) // e.g. { runId: 'f858a2bc-b469-4e48-be67-0876339ee7e1', cancelledAt: '2024-01-01T00:00:00.000Z' }

Example: curl​

curl -X POST https://api.cypress.io/runs/cancel \
-H 'Content-Type: application/json' \
-d '{
"projectId": "abc123",
"recordKey": "f858a2bc-b469-4e48-be67-0876339ee7e1",
"runUrl": "https://cloud.cypress.io/projects/abc123/runs/42"
}'

Finding the run URL or run number​

Use the before:run Node event to get the Cypress Cloud runUrl. This can be accessed using your cypress config file:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
// setupNodeEvents can be defined in either
// the e2e or component configuration
e2e: {
setupNodeEvents(on, config) {
const { defineConfig } = require('cypress')

module.exports = defineConfig({
// setupNodeEvents can be defined in either
// the e2e or component configuration
e2e: {
setupNodeEvents(on, config) {
on('before:run', async (details) => {
// `results` is undefined in `cypress open` mode, and `runUrl` is only
// set when the run was recorded. Bail out otherwise.
if (!details?.runUrl) {
return
}

console.log(details.runUrl)

// store the RUN URL where your CI process can access it later for cancellation purposes
})
},
},
})
},
},
})

Responses​

A successful cancellation always responds immediately and will end a Cypress run in progress.

Note: If you are looking for a less-immediate signal that allows the queued tests to complete before ending the run, use the Run Completion API instead.

StatusBodyMeaning
200{ "runId": "...", "cancelledAt": "..." }The run was canceled.
409{ "message": "Run is not currently running and cannot be canceled.", "code": "RUN_NOT_RUNNING" }The run is not currently running. It may have already completed, already been canceled, or timed out.

Malformed or unauthenticated requests are rejected before a cancellation is attempted: a missing or invalid record key returns 401, a missing projectId or run identifier returns 400, and a runUrl or runNumber that doesn't resolve to a run in the project returns 404. Every error response is a JSON body of the form { "message": "...", "code": "..." }.

See also​