How to Build Custom Workflows with Cypress Cloud Webhooks
Route Cypress Cloud run events into Slack, tickets, deployments, or internal systems. Configure payloads, verify signatures, handle retries, and prevent duplicates.
Cypress Cloud webhooks send selected run events as JSON HTTP POST requests to a public endpoint. To build a workflow, choose the event and destination, configure the webhook in Cypress Cloud, map the payload fields in your receiver, then verify delivery, authentication, filtering, and duplicate handling.
Use a custom webhook when you need message formatting, conditions, or destinations that Cypress’s built-in integrations do not cover. If its Slack notifications or GitHub checks already meet your needs, start there and avoid maintaining another delivery path. See the Cypress Cloud Webhooks documentation, Slack integration documentation, and GitHub integration documentation for current product details.
1. Choose the event and workflow
Cypress documents three event types:
run.completed: a run finished. Its status can bepassed,failed,errored,timedOut, orcancelled.run.accessibility.completed: an accessibility report completed.run.uiCoverage.completed: a UI Coverage report completed.
Decide which event should trigger an action and what conditions apply. For example, a deployment gate might require a passed run, while an incident workflow might include failed, errored, and timed-out runs. Do not assume every unsuccessful outcome uses the failed status.
| Need | Starting point |
|---|---|
| Standard Slack run notifications | Use Cypress’s native Slack integration if its channel, status, tag, run-group, and content options fit. |
| Custom message wording or conditional routing | Use a webhook and map the event fields in a Slack workflow or automation tool. |
| Custom action in another system | Send the webhook to a public receiver or a destination’s inbound-webhook trigger, then apply destination-specific conditions. |
Possible patterns include a custom Teams or Slack message; a ticket or incident for failures; a deployment hook that runs only on passing results; or a custom GitHub status using the commit SHA, status, and run URL. Cypress’s guide also describes routing through automation platforms such as Zapier, Make, or n8n. Check each destination’s current prerequisites and plan limits before relying on a particular action.
2. Prepare a receiver
The target must be publicly reachable and accept HTTPS POST requests. Cypress blocks private, loopback, and internal destinations, does not follow redirects, and times out an attempt after 10 seconds. A receiver should validate the request, enqueue or perform the small amount of work needed, and return a success response promptly. Avoid doing slow downstream work synchronously if it could exceed that timeout.
Choose how the receiver will authenticate Cypress. Prefer a signing secret and HMAC verification over the raw request body. If a no-code destination cannot inspect the raw body or verify an HMAC, keep its generated inbound URL secret and use its authentication controls where available; this is weaker than signature verification.
3. Configure the webhook in Cypress Cloud
- Open the project in Cypress Cloud, then go to Settings → General → Webhooks.
- Select Add webhook and enter the receiver’s public HTTPS URL.
- Select one or more event types:
run.completed,run.accessibility.completed, orrun.uiCoverage.completed. - Set a signing secret and, if the receiver requires it, a custom authorization header. A manually entered signing secret must be at least 16 characters. Cypress shows the secret once, so store it securely.
- Save the webhook, send a test delivery, and inspect the receiver and Cypress delivery history.
Project Owners, Admins, and Team Admins can manage webhooks. Cypress documents a limit of five webhooks per project.
4. Map and filter event data
For run.completed, useful top-level fields include status, projectName, runNumber, runUrl, commitBranch, totalTests, and totalFailed. Map only the fields your workflow needs, and link the run URL so recipients can inspect the source result.
For a Slack Workflow Builder flow, create a workflow that starts with a webhook, define variables for the incoming top-level keys, compose the message, and add conditions for the statuses or failure count that should trigger it. Cypress notes that Slack Workflow Builder does not map arrays or nested objects; accessibility and UI Coverage events include nested report data, so use an intermediate transformation when those fields are needed.
For a custom receiver, treat the payload as untrusted input: validate required fields and expected types, allowlist statuses and event names, and avoid using arbitrary payload values to construct commands or URLs. Route separately for passing, failed, errored, timed-out, and cancelled outcomes if their consequences differ.
5. Verify signatures and deduplicate deliveries
When a signing secret is configured, Cypress includes X-Cypress-Signature. Verify its HMAC using the exact raw request body before parsing or reserializing JSON. Use a constant-time comparison and reject stale timestamps using X-Cypress-Timestamp. Follow the current Cypress documentation for the signature format and algorithm rather than guessing from a parsed payload.
Delivery headers also include:
X-Cypress-Event,X-Cypress-Event-Id, andX-Cypress-Event-VersionX-Cypress-Request-IdandX-Cypress-TimestampX-Cypress-Idempotency-KeyX-Cypress-Signaturewhen a secret is configured
Use the stable event ID or idempotency key as a deduplication key. The request ID changes for each delivery attempt, so it is useful for tracing a particular attempt, not for identifying the underlying event. Store the event key before triggering a non-repeatable action such as opening a ticket or starting a deployment.
6. Test the complete path
- Use Cypress Cloud’s Send test control. It sends realistic but fabricated test data through the delivery path.
- Confirm the receiver accepts the request, verifies its signature if configured, parses the expected fields, and returns promptly.
- Confirm the destination renders the intended message or takes the intended action.
- Exercise each important condition, especially statuses other than
failed, using suitable real runs or receiver-level test fixtures. - After a real run, inspect Cypress delivery history and verify the real project fields and downstream result before depending on the workflow.
Test deliveries are not retried. A successful synthetic test confirms connectivity and basic parsing, but it does not prove the workflow handles every real payload or status correctly.
Delivery reliability, performance, and cost
Retries and response behavior
Cypress retries network or transport errors and HTTP 408, 429, and 5xx responses, with exponential backoff and jitter, for up to ten total attempts: the initial request plus as many as nine retries. A completed 3xx response, other 4xx responses, or a blocked destination is a permanent failure. Return a success response only after the receiver has safely accepted responsibility for the event; otherwise a transient failure could be lost. Make processing idempotent because retries and manual redelivery can repeat an event.
Cypress lets an administrator inspect delivery attempts and manually redeliver a failed or exhausted delivery. Redelivery retains the original event ID, so the same deduplication rule must apply.
Keep the path responsive
- Keep receiver work inside the 10-second attempt timeout. Queue longer actions and acknowledge once safely queued.
- Use the event ID to make queue insertion and downstream actions idempotent.
- Record event ID, request ID, response status, and processing outcome for diagnosis; avoid logging signing secrets or full sensitive payloads.
- Alert on exhausted deliveries and monitor the destination’s own workflow history as well as Cypress’s delivery history.
Cost and plan considerations
The Cypress documentation describes delivery behavior and a maximum of five webhooks per project; it does not establish that every destination or automation platform action is included in your subscription. Check current Cypress plan availability and the destination’s pricing, quotas, and plan prerequisites. A webhook receiver also has operational costs if you host it. Keep the workflow narrow so unrelated events do not create unnecessary downstream runs, tickets, or messages.
Common problems and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Destination never receives the request | URL is private, loopback, internal, redirects, or is not publicly reachable. | Use a publicly reachable HTTPS endpoint that accepts POST directly and does not depend on redirects. |
| Delivery fails after roughly 10 seconds | The receiver or a downstream action takes too long. | Validate and enqueue quickly, return a success response, and process the queued action asynchronously. |
| Repeated messages or tickets | Retries or manual redelivery reached a receiver without idempotency. | Deduplicate on X-Cypress-Event-Id or X-Cypress-Idempotency-Key; do not deduplicate on request ID. |
| Signature verification fails | The receiver parsed or changed the body before checking the signature, used the wrong secret, or used an outdated signature format. | Verify against the raw bytes with the configured secret, compare safely, and follow Cypress’s current signature documentation. |
| Test succeeds but real workflow misses a field | Test data is fabricated, or the selected event contains nested/array data the destination cannot map. | Inspect a real event and add an intermediate transformation for nested report payloads. |
| Failure alert misses an errored or timed-out run | The filter matches only failed. |
Define explicit handling for errored, timedOut, and cancelled statuses too. |
| Webhook test control or settings are unavailable | The account lacks a permitted project role. | Ask a Project Owner, Admin, or Team Admin to manage and test the project webhook. |
| Accessibility or UI Coverage fields are unavailable in Slack | The report payload contains nested objects or arrays. | Transform the payload in a small receiver or automation step into flat fields before sending it to Slack. |
Or skip the browser setup
If the workflow also needs a screenshot of a page or test artifact, ScreenshotNeo is a website screenshot API and MCP server for developers. It is separate from Cypress Cloud webhooks: call its API when you need a capture, or connect an MCP client such as Claude or Cursor to use its screenshot tools.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo API documentation for request options. Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots, and the API can return screenshots or PDFs. The Free plan includes 1,000 screenshots a month without a card; paid plans start at $5 for 3,000. Sign up for free and get 1,000 screenshots a month with no card.
FAQ
Can a Cypress webhook send directly to a private service?
No. Cypress requires a publicly reachable destination and blocks private, loopback, and internal addresses. Put a public HTTPS receiver or supported inbound-webhook service in front of the private system.
Does a successful test delivery prove the workflow is production-ready?
No. The test payload is fabricated and test sends are not retried. Confirm a real run, its fields, and the downstream action before relying on the workflow.
Can one webhook handle multiple event types?
You can select one or more documented event types when configuring a webhook. Keep event-specific parsing and filtering explicit because report events can contain nested data that a simple message builder cannot map.
What should I use to trace a delivery?
Use the event ID to correlate retries and redeliveries of the same event, and the request ID to identify an individual attempt.


