{
  "doc": {
    "id": "cloud/features/smart-orchestration/run-cancellation-api",
    "title": "Cancel a run via API in Cypress Cloud",
    "description": "Cancel a Cypress Cloud run programmatically with the Run Cancellation API, using your project ID and record key, without needing the Cypress Cloud dashboard.",
    "section": "cloud",
    "source_path": "/llm/markdown/cloud/features/smart-orchestration/run-cancellation-api.md",
    "version": "f60251bf707b0077a9535579c9f90d615440cc35",
    "updated_at": "2026-10-16T10:56:58.670Z",
    "headings": [
      {
        "id": "cloud/features/smart-orchestration/run-cancellation-api#run-cancellation-api",
        "text": "Run Cancellation API",
        "level": 1
      },
      {
        "id": "cloud/features/smart-orchestration/run-cancellation-api#why-use-the-run-cancellation-api",
        "text": "Why use the Run Cancellation API",
        "level": 2
      },
      {
        "id": "cloud/features/smart-orchestration/run-cancellation-api#endpoint",
        "text": "Endpoint",
        "level": 2
      },
      {
        "id": "cloud/features/smart-orchestration/run-cancellation-api#request-body",
        "text": "Request body",
        "level": 2
      },
      {
        "id": "cloud/features/smart-orchestration/run-cancellation-api#example-fetch",
        "text": "Example: fetch",
        "level": 3
      },
      {
        "id": "cloud/features/smart-orchestration/run-cancellation-api#example-curl",
        "text": "Example: curl",
        "level": 3
      },
      {
        "id": "cloud/features/smart-orchestration/run-cancellation-api#finding-the-run-url-or-run-number",
        "text": "Finding the run URL or run number",
        "level": 2
      },
      {
        "id": "cloud/features/smart-orchestration/run-cancellation-api#responses",
        "text": "Responses",
        "level": 2
      },
      {
        "id": "cloud/features/smart-orchestration/run-cancellation-api#see-also",
        "text": "See also",
        "level": 2
      }
    ]
  },
  "chunks": [
    {
      "id": "cloud/features/smart-orchestration/run-cancellation-api#why-use-the-run-cancellation-api",
      "doc_id": "cloud/features/smart-orchestration/run-cancellation-api",
      "heading": "Why use the Run Cancellation API",
      "heading_level": 2,
      "content_markdown": "## Why use the Run Cancellation API\n\nThe Run Cancellation API lets you cancel a run with a single authenticated HTTP request, using the same [project ID](/llm/markdown/cloud/account-management/projects.md#Project-ID) and [record key](/llm/markdown/cloud/account-management/projects.md#Record-key) credentials you already use to [record the run](/llm/markdown/cloud/get-started/setup.md#Setup).\n\nCancelling through the API has the same effect as cancelling manually from the dashboard: the run is marked **Canceled**, [`run.completed` webhooks](/llm/markdown/cloud/integrations/webhooks.md) fire, and any in-progress `cypress run --record` calls for the run exit with an error. See [What happens when a run is cancelled?](/llm/markdown/cloud/features/recorded-runs.md#What-happens-when-a-run-is-cancelled) for the full list of effects.\n\nThis is especially useful when:\n\n*   You want to use [Re-run optimization](/llm/markdown/cloud/features/smart-orchestration/rerun-optimization.md) to execute only the tests that did not pass in a previously cancelled run.\n*   You want to trigger [`run.completed` webhooks](/llm/markdown/cloud/integrations/webhooks.md) in a timely manner after your CI has stopped.\n*   You want any other end-of-run integrations like [GitHub](/llm/markdown/cloud/integrations/github.md) or [Slack](/llm/markdown/cloud/integrations/slack.md) to happen at the moment of the CI cancellation, not after the Run Timeout expires.\n*   You want Cypress [Cloud MCP](/llm/markdown/cloud/integrations/cloud-mcp.md) and [CLI](/llm/markdown/cloud/integrations/cloud-cli.md) to reflect the intentional cancelled state immediately when working with results, instead of a partial \"timing out\" state.\n\n**Cypress Run exit code in CI**\n\nCancellation 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.\n\nCypress 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.\n\n**Note:** If you call this API from a step that runs separately from the test job itself, the **cancelled run's own CI job** will report as failed rather than cancelled. This may happen example in deployment-pipeline and orchestrator use cases. You should account for that in the job that ran the cancelled specs, so a run you intentionally cancelled doesn't get treated as a broken build.\n",
      "section": "cloud",
      "anchors": [
        "why-use-the-run-cancellation-api"
      ],
      "path": "/llm/json/chunked/cloud/features/smart-orchestration/run-cancellation-api.json",
      "token_estimate": 428
    },
    {
      "id": "cloud/features/smart-orchestration/run-cancellation-api#request-body",
      "doc_id": "cloud/features/smart-orchestration/run-cancellation-api",
      "heading": "Request body",
      "heading_level": 2,
      "content_markdown": "## Request body\n\nThe request body is JSON. `projectId` and `recordKey` are always required, and the run is identified by **exactly one** of `runUrl` or `runNumber`.\n\n| Property | Type | Required | Description |\n| --- | --- | --- | --- |\n| `projectId` | `string` | Yes | The [project ID](/llm/markdown/cloud/account-management/projects.md#Project-ID) of the run. |\n| `recordKey` | `string` | Yes | A valid [record key](/llm/markdown/cloud/account-management/projects.md#Record-key) for the project. |\n| `runUrl` | `string` | Conditional | The Cypress Cloud run URL (Cypress prints this when a run starts). Provide this **or** `runNumber`. |\n| `runNumber` | `number` | Conditional | The run's sequential number within the project. Provide this **or** `runUrl`. |\n\n### Example: `fetch`\n\n```\nconst response = await fetch('https://api.cypress.io/runs/cancel', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({\n    projectId: 'abc123',\n    recordKey: 'f858a2bc-b469-4e48-be67-0876339ee7e1',\n    runUrl: 'https://cloud.cypress.io/projects/abc123/runs/42',\n    // runNumber: 42, // optional, in lieu of runUrl\n  }),\n})\n\nconst result = await response.json()\nconsole.log(result) // e.g. { runId: 'f858a2bc-b469-4e48-be67-0876339ee7e1', cancelledAt: '2024-01-01T00:00:00.000Z' }\n```\n\n### Example: `curl`\n\n```\ncurl -X POST https://api.cypress.io/runs/cancel \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"projectId\": \"abc123\",\n    \"recordKey\": \"f858a2bc-b469-4e48-be67-0876339ee7e1\",\n    \"runUrl\": \"https://cloud.cypress.io/projects/abc123/runs/42\"\n  }'\n```\n",
      "section": "cloud",
      "anchors": [
        "request-body"
      ],
      "path": "/llm/json/chunked/cloud/features/smart-orchestration/run-cancellation-api.json",
      "token_estimate": 253
    },
    {
      "id": "cloud/features/smart-orchestration/run-cancellation-api#example-fetch",
      "doc_id": "cloud/features/smart-orchestration/run-cancellation-api",
      "heading": "Example: fetch",
      "heading_level": 3,
      "content_markdown": "### Example: `fetch`\n\n```\nconst response = await fetch('https://api.cypress.io/runs/cancel', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({\n    projectId: 'abc123',\n    recordKey: 'f858a2bc-b469-4e48-be67-0876339ee7e1',\n    runUrl: 'https://cloud.cypress.io/projects/abc123/runs/42',\n    // runNumber: 42, // optional, in lieu of runUrl\n  }),\n})\n\nconst result = await response.json()\nconsole.log(result) // e.g. { runId: 'f858a2bc-b469-4e48-be67-0876339ee7e1', cancelledAt: '2024-01-01T00:00:00.000Z' }\n```\n",
      "section": "cloud",
      "anchors": [
        "example-fetch"
      ],
      "path": "/llm/json/chunked/cloud/features/smart-orchestration/run-cancellation-api.json",
      "token_estimate": 68
    },
    {
      "id": "cloud/features/smart-orchestration/run-cancellation-api#finding-the-run-url-or-run-number",
      "doc_id": "cloud/features/smart-orchestration/run-cancellation-api",
      "heading": "Finding the run URL or run number",
      "heading_level": 2,
      "content_markdown": "## Finding the run URL or run number\n\nUse the [`before:run`](/llm/markdown/api/node-events/before-run-api.md) Node event to get the Cypress Cloud `runUrl`. This can be accessed using your cypress config file:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  // setupNodeEvents can be defined in either\n  // the e2e or component configuration\n  e2e: {\n    setupNodeEvents(on, config) {\n      const { defineConfig } = require('cypress')\n\n      module.exports = defineConfig({\n        // setupNodeEvents can be defined in either\n        // the e2e or component configuration\n        e2e: {\n          setupNodeEvents(on, config) {\n            on('before:run', async (details) => {\n              // `results` is undefined in `cypress open` mode, and `runUrl` is only\n              // set when the run was recorded. Bail out otherwise.\n              if (!details?.runUrl) {\n                return\n              }\n\n              console.log(details.runUrl)\n\n              // store the RUN URL where your CI process can access it later for cancellation purposes\n            })\n          },\n        },\n      })\n    },\n  },\n})\n```\n\n```\nimport { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  // setupNodeEvents can be defined in either\n  // the e2e or component configuration\n  e2e: {\n    setupNodeEvents(on, config) {\n      const { defineConfig } = require('cypress')\n\n      module.exports = defineConfig({\n        // setupNodeEvents can be defined in either\n        // the e2e or component configuration\n        e2e: {\n          setupNodeEvents(on, config) {\n            on('before:run', async (details) => {\n              // `results` is undefined in `cypress open` mode, and `runUrl` is only\n              // set when the run was recorded. Bail out otherwise.\n              if (!details?.runUrl) {\n                return\n              }\n\n              console.log(details.runUrl)\n\n              // store the RUN URL where your CI process can access it later for cancellation purposes\n            })\n          },\n        },\n      })\n    },\n  },\n})\n```\n",
      "section": "cloud",
      "anchors": [
        "finding-the-run-url-or-run-number"
      ],
      "path": "/llm/json/chunked/cloud/features/smart-orchestration/run-cancellation-api.json",
      "token_estimate": 341
    },
    {
      "id": "cloud/features/smart-orchestration/run-cancellation-api#responses",
      "doc_id": "cloud/features/smart-orchestration/run-cancellation-api",
      "heading": "Responses",
      "heading_level": 2,
      "content_markdown": "## Responses\n\nA successful cancellation always responds immediately and will end a Cypress run in progress.\n\n**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](/llm/markdown/cloud/features/smart-orchestration/parallelization.md#Run-Completion-API) instead.\n\n| Status | Body | Meaning |\n| --- | --- | --- |\n| `200` | `{ \"runId\": \"...\", \"cancelledAt\": \"...\" }` | The run was cancelled. |\n| `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 cancelled, or timed out. |\n\nMalformed or unauthenticated requests are rejected before a cancellation is attempted: a missing or invalid [record key](/llm/markdown/cloud/account-management/projects.md#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\": \"...\" }`.\n",
      "section": "cloud",
      "anchors": [
        "responses"
      ],
      "path": "/llm/json/chunked/cloud/features/smart-orchestration/run-cancellation-api.json",
      "token_estimate": 221
    },
    {
      "id": "cloud/features/smart-orchestration/run-cancellation-api#see-also",
      "doc_id": "cloud/features/smart-orchestration/run-cancellation-api",
      "heading": "See also",
      "heading_level": 2,
      "content_markdown": "## See also\n\n*   [Auto Cancellation](/llm/markdown/cloud/features/smart-orchestration/run-cancellation.md) - cancel a run automatically once failures cross a threshold\n*   [Manually cancelling a run](/llm/markdown/cloud/features/recorded-runs.md#Run-cancellation) - cancel a run from the Cypress Cloud dashboard\n*   [Run Completion API](/llm/markdown/cloud/features/smart-orchestration/parallelization.md#Run-Completion-API) - mark a run complete early instead of cancelling it\n*   [`run.completed` webhooks](/llm/markdown/cloud/integrations/webhooks.md) - get notified when a run finishes, including by cancellation\n",
      "section": "cloud",
      "anchors": [
        "see-also"
      ],
      "path": "/llm/json/chunked/cloud/features/smart-orchestration/run-cancellation-api.json",
      "token_estimate": 76
    }
  ]
}