I’ve shipped APIs that looked perfect in code review and still broke in production because nobody tested the right things. Testing an API isn’t just about hitting an endpoint and checking that you got a 200 response back. There’s a whole layer of behavior, edge cases, and non-functional requirements that need attention before you can call an API “production ready.” Let me walk you through exactly which features and behaviors you should be testing, and why each one matters.
1. Functional Correctness
This is the obvious starting point, but it goes deeper than most people think.
- Happy path testing — does the endpoint return the correct data for valid, expected input?
- CRUD completeness — for every resource, test create, read, update, and delete separately, including partial updates (PATCH vs PUT behavior).
- Response schema validation — check that field names, data types, and nesting match the documented contract exactly, not just that “some JSON came back.”
- Pagination behavior — verify page size limits, cursor or offset correctness, and that the last page correctly signals there’s no more data.
- Filtering and sorting — test that query parameters actually filter and sort as documented, including combinations of multiple filters.
2. Input Validation and Edge Cases
This is where a huge number of bugs hide.
- Empty strings, null values, and missing required fields.
- Extremely long strings or oversized payloads.
- Special characters, emoji, and different Unicode encodings.
- Boundary values — zero, negative numbers, maximum integers, decimal precision issues.
- Wrong data types sent on purpose (a string where a number is expected).
- Duplicate requests (idempotency) — does calling the same POST twice create two records when it shouldn’t?
3. Authentication and Authorization
Security-related tests deserve their own dedicated pass:
- Requests with no token at all.
- Requests with an expired or malformed token.
- Requests with a valid token but insufficient permissions (testing authorization, not just authentication).
- Attempting to access another user’s data by guessing or manipulating IDs (an “IDOR” — Insecure Direct Object Reference — check).
- Token refresh flows and what happens when a refresh token is reused after rotation.
4. Error Handling
A well-tested API should fail predictably and helpfully:
- Correct HTTP status codes for every failure scenario (400 for bad input, 401 for unauthenticated, 403 for unauthorized, 404 for not found, 409 for conflicts, 429 for rate limiting, 500 for server errors).
- Consistent, well-structured error response bodies (error codes, human-readable messages, and machine-readable identifiers for programmatic handling).
- Making sure error messages don’t leak sensitive internal details like stack traces, database queries, or file paths.
5. Rate Limiting and Throttling
- Verify limits are actually enforced at the documented thresholds.
- Check that rate limit headers (like
X-RateLimit-Remaining) are accurate. - Confirm the correct
429response andRetry-Afterheader behavior when limits are exceeded.
6. Performance and Load
- Response time under normal load — is the API meeting its documented or expected latency targets?
- Load testing — how does the API behave under a realistic spike in traffic (think Black Friday for an e-commerce API)?
- Stress testing — pushing well beyond expected traffic to find the breaking point and how gracefully the system degrades.
- Soak testing — running sustained load over hours to catch memory leaks or slow resource exhaustion.
7. Data Consistency and Concurrency
- What happens when two requests try to update the same resource at the same time?
- Are database transactions used correctly so partial failures don’t leave data in a broken state?
- Test optimistic locking or versioning if your API supports conflict detection (like an
ETagor version field).
8. Versioning and Backward Compatibility
- Confirm that older API versions still behave as documented after new versions are released.
- Test that deprecated fields still appear (if promised) and that deprecation warnings are surfaced correctly.
- Check that breaking changes are actually isolated to new version numbers and don’t leak into existing ones.
9. Third-Party Integrations and Webhooks
If your API sends webhooks or depends on external services:
- Test retry logic when a webhook endpoint is temporarily down.
- Verify signature validation on outgoing webhooks so consumers can trust the payload’s authenticity.
- Simulate slow or failing third-party dependencies to see how your API degrades.
10. Documentation Accuracy
This one is often skipped, but it matters enormously:
- Every example request and response in your documentation should be tested against the real API automatically, ideally as part of your CI pipeline.
- Contract testing tools can validate that your OpenAPI spec matches actual API behavior, catching drift before it reaches consumers.
11. CORS and Cross-Origin Behavior
If your API is called from browsers, test that CORS headers are configured correctly for the domains that should (and shouldn’t) be allowed to call it.
12. Localization and Time Zones
- Test date and time handling across time zones, especially around daylight saving transitions.
- If your API supports multiple languages, verify localized error messages and content actually change based on the
Accept-Languageheader or equivalent.
Putting It All Together: A Testing Strategy
I usually organize API tests into layers:
- Unit tests — fast, isolated tests for business logic within individual functions.
- Integration tests — testing how components (database, cache, external services) work together.
- Contract tests — verifying the API matches its published specification.
- End-to-end tests — simulating real client workflows across multiple endpoints.
- Security tests — dedicated scans and manual checks for authentication, authorization, and injection vulnerabilities.
- Performance tests — load, stress, and soak testing on a schedule, not just before major releases.
Automating as much of this as possible in a CI/CD pipeline means every code change gets checked against this full list before it ever reaches production.
Final Thoughts
Testing an API well means going far beyond “does it return data.” Cover functional correctness, edge cases, security, performance, and documentation accuracy, and you’ll catch the vast majority of issues before your users ever do.