
Most testers assume Cypress is only meant for UI or end-to-end testing. As a result, API testing is often handled separately, even though many test failures originate at the API layer long before the UI is involved.
Cypress supports direct API testing through HTTP requests and network interception, allowing testers to validate status codes, response payloads, and error scenarios without relying on the UI.
When used correctly, this approach provides faster feedback, clearer failures, and stronger confidence in backend behavior.
This article explores how API testing works in Cypress, covering setup, core request handling, assertions, advanced scenarios, and best practices to help testers build reliable API tests that integrate seamlessly into CI/CD pipelines.
API testing in Cypress refers to validating backend endpoints directly by sending HTTP requests and asserting their responses, without relying on any UI interaction. It allows testers to verify that APIs return the correct status codes, data, headers, and error responses.
In Cypress, API testing is performed using built-in capabilities to make network requests and inspect responses. This enables testers to validate API behavior early and independently, making it easier to identify backend issues before they impact the user interface.
Cypress API testing supports common use cases such as:
Because API tests run faster and are less prone to flakiness than UI tests, they are often used to complement end-to-end testing and to prepare application state for UI validation.
By incorporating API testing into Cypress, testers can use a single framework to validate both backend and frontend behavior, simplifying test maintenance and improving overall test reliability.
Cypress offers several advantages that make it a practical choice for API testing, especially for teams already using it for UI or end-to-end automation.
Using Cypress for API testing helps testers validate backend behavior efficiently while maintaining a simple, consistent automation workflow built on Cypress.
A reliable Cypress API testing setup is mostly about having a clean Node project, installing Cypress correctly, and keeping URLs/secrets configurable across environments. Cypress can send HTTP requests out of the box, so you don’t need extra libraries just to start API testing.
1. Create a project workspace
Create a new folder (or use your existing repo), then initialize a Node project so dependencies and scripts are managed via package.json.
mkdir cypress-api-tests
cd cypress-api-tests
npm init -y
2. Install Cypress
Install Cypress as a development dependency and ensure it launches correctly. This confirms the base setup is working before adding API tests.
npm install --save-dev cypress
npx cypress open
Once Cypress opens successfully, you can close the Test Runner and proceed with configuration.
3. Configure API Base URLs
API endpoints should never be hardcoded in test files. Instead, define base URLs using Cypress environment configuration so tests can run against different environments without code changes.
cypress.config.js
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
env: {
apiBaseUrl: 'https://api.example.com'
}
}
})
You can then access this value inside tests using:
Cypress.env('apiBaseUrl')
4. Organize API Test Files
Keep API tests separate from UI or component tests to maintain clarity as the test suite grows. A dedicated folder structure makes API coverage easier to manage and scale.
Example:
cypress/
└── e2e/
└── api/
5. Use Fixtures for Test Data
Request payloads and reusable response data should be stored as fixtures. This keeps tests readable and avoids duplication when validating multiple scenarios.
6. Manage Authentication and Secrets Securely
If API tests require tokens or credentials, pass them through environment variables rather than hardcoding them in tests. This is especially important for CI pipelines and shared repositories.
With this environment in place, Cypress is ready to send API requests, validate responses, and support reliable API testing across different stages of the delivery pipeline.
Your first Cypress API test focuses on sending an HTTP request to an endpoint and validating the response. Since API tests do not involve the UI, they are fast to write, easy to debug, and ideal for early validation.
1. Create an API Test Spec
Start by creating a new spec file under your API test folder, for example:
cypress/e2e/api/get-user.cy.js
This keeps API tests organized and separate from UI tests.
2. Send an API Request
Cypress provides a built-in command to make HTTP requests. You can use it to send a request to an endpoint and capture the response.
describe('Get User API', () => {
it('returns user details successfully', () => {
cy.request({
method: 'GET',
url: `${Cypress.env('apiBaseUrl')}/users/1`
})
})
})
At this stage, the test only sends a request. Assertions are added next to validate the response.
3. Validate the API Response
Assertions confirm whether the API behaves as expected. Common checks include status codes and response data.
cy.request({
method: 'GET',
url: `${Cypress.env('apiBaseUrl')}/users/1`
}).then((response) => {
expect(response.status).to.eq(200)
expect(response.body).to.have.property('id')
})
This verifies that the API returns a successful response and contains expected data.
Cypress allows testers to send HTTP requests directly to an API without involving the UI. This makes it easy to validate backend behavior, prepare test data, and verify responses quickly and reliably.
The primary way to make HTTP requests in Cypress is through the cy.request() command. It supports all common HTTP methods and returns the full response for validation.
cy.request('GET', `${Cypress.env('apiBaseUrl')}/users`)
For more control, requests can be sent using an options object. This allows you to specify the HTTP method, headers, query parameters, and request body.
cy.request({
method: 'POST',
url: `${Cypress.env('apiBaseUrl')}/users`,
body: {
name: 'John Doe',
role: 'tester'
}
})
Headers such as authorization tokens or content types can be included as part of the request configuration.
cy.request({
method: 'GET',
url: `${Cypress.env('apiBaseUrl')}/profile`,
headers: {
Authorization: `Bearer ${Cypress.env('authToken')}`
}
})
Query parameters can be passed directly in the URL or included as part of the request options.
cy.request({
method: 'GET',
url: `${Cypress.env('apiBaseUrl')}/users`,
qs: {
page: 2
}
})
By default, Cypress fails the test if the response status code is not successful. This behavior can be overridden when testing negative or error scenarios.
cy.request({
method: 'GET',
url: `${Cypress.env('apiBaseUrl')}/users/999`,
failOnStatusCode: false
})
Using cy.request() effectively allows testers to validate APIs, control test data, and speed up automation while staying within the same testing framework provided by Cypress.
Assertions in Cypress API testing are used to verify that an API behaves as expected by validating response status codes, headers, and payload data. Strong assertions ensure API failures are detected early and reported clearly.
1. Asserting HTTP Status Codes
Status code assertions confirm whether an API request succeeds or fails as intended.
cy.request('/users/1').then((response) => {
expect(response.status).to.eq(200)
})
2. Validating Response Body Data
Response bodies can be asserted to check for specific properties, values, or data structures returned by the API.
cy.request('/users/1').then((response) => {
expect(response.body).to.have.property('id')
expect(response.body.name).to.eq('John')
})
3. Asserting Response Headers
Headers can be validated to ensure the API returns the correct content type or security-related values.
cy.request('/users/1').then((response) => {
expect(response.headers).to.have.property('content-type')
})
4. Handling Error Responses
When testing negative scenarios, Cypress allows assertions on error responses by disabling automatic failure on non-success status codes.
5. Combining Assertions for Strong Validation
Multiple assertions can be applied to a single response to fully validate API behavior, ensuring both correctness and reliability.
Clear, focused assertions help Cypress API tests remain fast, stable, and meaningful while validating backend behavior independently of the UI using Cypress.
As API test coverage grows, Cypress can be used to handle more complex scenarios that
go beyond basic request–response validation. These advanced patterns help testers build realistic, scalable, and reliable API test suites.
1. Chaining Multiple API Requests
Some scenarios require using data from one API response in subsequent requests. Cypress allows responses to be captured and reused to validate dependent workflows.
cy.request('POST', '/users', { name: 'Alice' })
.then((createRes) => {
const userId = createRes.body.id
cy.request('GET', `/users/${userId}`)
})
2. Testing Authenticated APIs
APIs that require authentication can be tested by dynamically generating or reusing tokens and passing them in request headers. This avoids hardcoding credentials and keeps tests secure.
3. Validating Error and Edge Cases
Advanced testing includes validating boundary conditions, invalid inputs, and unexpected responses. These checks help ensure APIs fail gracefully and return meaningful error messages.
4. Working with Dynamic Data
Cypress API tests can handle dynamic data by generating values at runtime or extracting them from previous responses, making tests flexible and repeatable.
5. Using API Calls for Test Setup and Cleanup
API requests can be used to create test data before a test run and clean it up afterward. This reduces dependency on the UI and keeps tests fast and deterministic.
6. Handling Rate Limits and Timeouts
Advanced scenarios may require validating API behavior under throttling or delayed responses. Cypress allows testers to assert timeout handling and fallback behavior explicitly.
Using these advanced techniques, Cypress API testing can support complex workflows, realistic system behavior, and reliable validation in modern CI/CD pipelines built with Cypress.
Running Cypress API tests in CI/CD helps teams catch backend regressions early and keep releases stable. Because API tests do not depend on UI rendering, they are typically faster and more reliable as an automated quality gate.
1. Run API tests headlessly
Execute Cypress in headless mode for CI to keep runs faster and more resource-efficient than interactive execution.
npx cypress run --spec "cypress/e2e/api/**/*.cy.js"
2. Use environment variables for configuration
Pass base URLs, tokens, and environment-specific values through CI variables so tests can run against staging, QA, or test environments without code changes.
npx cypress run --env apiBaseUrl=https://api.example.com,authToken=$AUTH_TOKEN
3. Keep secrets out of source control
Store credentials, API keys, and tokens in your CI secret manager and inject them at runtime, avoiding hardcoding in test code or config files.
4. Make tests deterministic and independent
API tests should not rely on state created by other tests. Use setup and cleanup requests so each test can run in isolation and in parallel.
5. Generate useful debugging output
When a pipeline fails, clear assertions and logged request/response details help diagnose whether the failure is caused by environment issues, authentication, or real API regressions.
6. Run API tests early in the pipeline
Place API tests before slower UI suites so regressions are detected quickly and expensive test stages are not triggered unnecessarily.
With a stable configuration and deterministic test design, Cypress API tests become an effective CI/CD gate that provides fast feedback and improves confidence in backend behavior.
Cypress API testing is often compared with dedicated API testing tools and frameworks. Each option has strengths, and the right choice depends on how API testing fits into your overall test strategy.
1. Cypress vs Dedicated API Tools
Dedicated API tools are designed specifically for creating, sending, and exploring API requests, making them great for manual testing and quick validation.
Cypress, on the other hand, focuses on automated testing and integrates API validation directly into test suites that also cover UI and workflows.
2. Cypress vs API-Only Test Frameworks
API-only frameworks are optimized for large-scale backend validation and may offer advanced features like schema enforcement or extensive reporting out of the box.
Cypress trades some of that specialization for simplicity and a unified testing approach within the same framework.
3. Unified testing workflow
With Cypress, API tests can be written alongside UI or component tests using the same syntax, assertions, and tooling. This reduces context switching and maintenance overhead for testers.
4. Speed and feedback
Cypress API tests run quickly and provide clear failure messages, making them well suited for early pipeline checks and regression detection.
5. When Cypress is the right choice
Cypress works best when API testing is part of a broader automation strategy that includes UI or component testing and when teams want a single framework for multiple test layers.
6. When other tools may be better
If your focus is exclusively on deep API validation, contract testing, or large-scale schema enforcement, a dedicated API testing tool may be a better fit.
These common mistakes often lead to unstable tests and misleading failures if not addressed early.
The following best practices help ensure Cypress API tests remain reliable, maintainable, and easy to scale.
Cypress API testing provides testers with a fast and reliable way to validate backend behavior without depending on the UI.
By testing APIs directly, teams can catch issues earlier, write more deterministic tests, and reduce flakiness across their automation suites. When combined with clear assertions, proper environment setup, and CI/CD integration, Cypress API tests become a strong foundation for scalable test automation.
Get visual proof, steps to reproduce and technical logs with one click
Try Bird on your next bug - you’ll love it
“Game changer”
Julie, Head of QA
Try Bird later, from your desktop