APIs fail quietly. A broken UI is obvious the moment someone looks at the screen. A broken API often keeps returning a 200 OK while sending back the wrong data, and nobody notices until a customer does. Most of the API incidents we get called in to help untangle trace back to a small set of avoidable mistakes.
1. Only testing the happy path
It's tempting to write one test per endpoint, confirm it returns a success response, and call it done. That test tells you almost nothing about how the API behaves under real conditions.
Real traffic includes malformed payloads, missing fields, unexpected types, and requests from clients running an older version of your contract. If your test suite only ever sends perfect requests, it's only validating a scenario that barely happens in production.
What to test instead:
- Missing required fields
- Wrong data types (a string where a number is expected)
- Extra/unexpected fields
- Boundary values (empty strings, zero, negative numbers, very large payloads)
2. Skipping authentication and authorization edge cases
A shocking number of production incidents come down to permission checks that were never explicitly tested. It's not enough to confirm that a valid, authenticated user can call an endpoint. You need to confirm:
- An expired token is rejected, not silently accepted
- A user can't access another user's resources by changing an ID in the URL
- Role-based permissions are actually enforced, not just checked in the UI
That last one matters more than teams expect. UI-level restrictions are a suggestion. API-level enforcement is the actual security boundary.
3. Not validating the response schema, only the status code
A 200 response with the wrong shape is still a failure, it's just one that's easy to miss if your tests only check the status code.
// Weak: only checks that the request "worked"
expect(response.status).toBe(200);
// Stronger: validates the actual contract
expect(response.status).toBe(200);
expect(response.body).toMatchSchema(userResponseSchema);
expect(response.body.email).toMatch(/^\S+@\S+\.\S+$/);
Schema validation catches the class of bug that breaks every client silently: a field renamed, a type changed from string to number, a nested object flattened. None of these change the status code. All of them break integrations.
4. Ignoring how the API fails, not just how it succeeds
When a downstream service times out, does your API return a clear error, or does it hang, or worse, return a 200 with an empty body? Failure-mode testing is where the most valuable coverage lives, because it's the scenario your team is least likely to have manually verified.
If you've never deliberately broken a dependency to see how your API responds, you don't actually know how it behaves in an incident. You're finding out live, with users watching.
5. Treating third-party integrations as "not our problem"
If your product depends on a payment provider, a mapping service, or any external API, its failure becomes your failure the moment a user is affected. Testing should cover how your system behaves when that dependency is slow, returns an error, or goes down entirely, not just when it works perfectly, which is usually the only case anyone tested.
Building this into your process
None of these fixes require exotic tooling. They require treating API testing as seriously as you treat the code itself: real schema validation, real edge cases, and real failure scenarios, tested before your customers find them for you.
If your integrations could use a closer look before the next production incident finds them for you, QA Solucity's API testing service is built exactly for this. Get in touch to talk through your integration landscape.


