API testing validates that an application programming interface (API) correctly handles requests, returns expected responses, and maintains data integrity across services and workflows. To fully cover an API, you must validate the status code, response body, headers, schema, authentication, performance, and error handling for every endpoint, plus the data flow and state transitions across multi-step workflows. This article breaks down each validation layer with concrete examples and common pitfalls.
What to Validate: The Core Layers
Every API test should cover these layers, regardless of whether you’re testing a single endpoint or a multi-service workflow:
- Status code – The HTTP status code (200, 404, 500) tells you if the request succeeded or failed at the transport level.
- Response body – The actual data returned. Validate the structure, types, and values against the contract.
- Headers – Content-Type, Cache-Control, authentication tokens, and custom headers often carry critical information.
- Schema – The response must conform to a defined JSON Schema or OpenAPI specification. This catches missing fields or type changes.
- Authentication & Authorization – Verify that unauthenticated requests are rejected, and that different user roles get appropriate access.
- Performance – Response time and throughput under normal and peak load. Set thresholds based on your SLA.
- Error handling – How the API responds to invalid input, missing parameters, or server errors. The error message should be informative and consistent.
- Data integrity – For workflows, ensure that data is not corrupted or lost as it flows through multiple services.
Validating Across Services (Microservices)
In a microservices architecture, a single user action often triggers calls to multiple services. For example, an e-commerce checkout might call the cart service, payment service, inventory service, and notification service. When testing across services, you must validate:
- Contract compatibility – Each service must send and receive data that matches the other’s expectations. Use consumer-driven contract testing (e.g., Pact) to catch mismatches early.
- Distributed tracing – Ensure that a unique request ID (e.g., correlation ID) is propagated across services so you can trace the entire workflow in logs.
- Idempotency – When a service retries a request (e.g., payment), the same request should not create duplicate orders or charges. Validate that retrying with the same ID returns the same result.
- Consistency – If services use separate databases, check that data is eventually consistent. For example, after a successful order, the inventory should be decremented, but there may be a delay.
- Failure handling – What happens when one service is down? The workflow should fail gracefully, with a clear error message, and not leave the system in an inconsistent state.
Validating Workflows (Multi-Step Processes)
A workflow is a sequence of API calls that together achieve a business goal. For example, a user registration workflow might be: POST /users, POST /verification-email, GET /users/{id}. To validate a workflow, you need to check not just each step, but the state transitions:
- Define the happy path – The expected sequence of calls with valid inputs. Verify that each response contains the necessary data for the next call (e.g., an ID from a POST response used in a GET).
- Test alternative paths – What if a step fails? For example, if payment fails, the order should not be created. Validate that the workflow handles this without leaving partial data.
- Check state changes – After each step, the system’s state should change as expected. For example, after POST /orders, the order status should be “pending”, and after payment, it should be “paid”.
- Validate rollback – If a later step fails, does the system roll back earlier changes? For example, if inventory is decremented but payment fails, is the inventory restored?
- Concurrency – Test what happens when two users perform the same workflow simultaneously. For example, two users buying the last item in stock—only one should succeed.
Common Pitfalls and Misconceptions
One common mistake is only testing the happy path and ignoring error cases. Another is checking only the status code and not the response body—a 200 OK with the wrong data is still a bug. Also, many testers forget to validate response headers, especially when they carry security tokens. A misconception is that contract tests replace end-to-end tests; they don’t—contract tests verify service-to-service communication, but end-to-end tests validate the entire user journey.
How to Choose What to Validate
Prioritize based on risk and business impact. Start with the critical business workflows (e.g., login, checkout) and endpoints that handle sensitive data. Use a risk-based approach:
- High risk: authentication, payment, data modification endpoints.
- Medium risk: read-only endpoints that serve data to users.
- Low risk: internal health checks or metrics endpoints.
Also, consider the API’s maturity. If the API is in early development, focus on schema and contract validation. If it’s in production, focus on performance and error handling.
Tools and Techniques
Popular tools include Postman for manual testing and collection-based automation, REST Assured for Java, pytest with requests for Python, and JMeter for load testing. For contract testing, Pact is widely used. For workflow testing, you can use orchestration tools like Karate or write custom scripts that chain API calls. Regardless of tool, the key is to make assertions on every layer mentioned above.
Frequently Asked Questions
What is the difference between API testing and unit testing?
Unit testing tests a single function or method in isolation, often mocking external dependencies. API testing tests the entire endpoint, including the HTTP layer, serialization, authentication, and the actual integration with databases or other services. API tests are typically slower but cover more of the system.
Should I test the response body for every field?
Yes, but not necessarily every value. You should validate the structure and types of all fields, and validate the values of fields that are critical to the business logic. For example, in a user object, you should check that “email” is a string and matches a regex, but you might not need to assert the exact value of a “created_at” timestamp unless it’s part of a workflow.
How do I handle dynamic data in API tests?
Use dynamic assertions that check the format or type rather than exact values. For example, assert that an ID is a positive integer, or that a timestamp matches ISO 8601 format. For values that are generated at runtime (like tokens), capture them from a previous response and use them in subsequent requests.
What is a good response time for an API?
It depends on the use case. For internal services, under 200 ms is often acceptable. For user-facing APIs, aim for under 500 ms for the 95th percentile. However, always set thresholds based on your business requirements and test under realistic load.
How often should I run API tests?
Run smoke tests (critical paths) on every deployment, and run full regression suites at least once per day or before each release. For performance tests, run them on a schedule (e.g., weekly) and also after significant code changes.
What is contract testing and do I need it?
Contract testing verifies that a service’s responses match the expectations of its consumers. It’s especially useful in microservices with many consumers. If you have more than two services communicating, contract testing can catch breaking changes early and reduce the need for full end-to-end tests. It’s not a replacement for end-to-end tests, but it’s a valuable addition.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- O2 PUK Code and PIN Code Explained
- How to Host a Space Engineers Server
- Schedule Ride in Advance Uber: How It Works
- Optimize WordPress Themes for Mobile Performance
- Can AI Assistants Access Your Carrier Account?5.00 min/km
- Choosing Communication Tools for Distributed Teams