What This Is
API testing is the work of verifying that the contracts your API exposes behave correctly across every condition that callers will encounter. That means the endpoints, request shapes, response shapes, status codes, headers, and error formats. It is testing the API as a product in its own right, not just as a layer behind a UI.
This matters because APIs almost always have callers you do not control. A mobile app, a partner integration, a third-party tool, a JavaScript front-end, an internal microservice: each of them has assumptions baked into how it calls your API. A change that looks innocuous from inside (rename a field, change a status code, add a required header) can silently break every consumer the moment it deploys.
API testing finds those breakages before deploy. The work covers contract validation (does the response match the documented schema), behaviour validation (does the API do the right thing for valid input), error validation (does it fail correctly for invalid input), and version compatibility (does v1 still work the way v1 callers expect, even after v2 has shipped).
We design and operate seven distinct product APIs across the Beacon ecosystem: WP Beacon, Lens, Pulse, Workbench, Bits, Agents, and the public website. Each has its own contract, its own auth scheme, and its own consumer base. That experience shapes how we approach client API testing. Every breaking change has a downstream cost, so the test suite must catch them before the release notes do.
When You Need This
API testing is essential when:
- You have a public or partner-facing API with consumers you cannot redeploy in lockstep: mobile apps, third-party integrations, customer scripts
- You maintain multiple API versions simultaneously and need confidence that v1 still works after every v2 change
- Your mobile app depends on API stability, and an unintended change to the API breaks every installed copy
- You are building an API as a product, where the API is the deliverable and contract drift would damage the relationship with paying customers
- Your team has had a breaking change reach production and now wants a way to make sure it cannot happen again
This is not the right service if you only have one consumer (your own front-end) and you can deploy them together. In that case, integration tests over the controllers cover the same ground without the additional layer of contract assertions. For that scenario, see our integration testing service.
How We Work
API testing engagements start with the contract, not the implementation. We document what the API is supposed to do (in OpenAPI, in markdown, in whatever format you have), and the test suite asserts the implementation matches the contract. If the contract changes, the tests fail. If the implementation drifts from the contract, the tests fail. Either way, the team finds out before consumers do.
We test happy paths and error paths with equal weight. Most API bugs in the wild are not in the happy path. They are in how the API responds to malformed input, missing fields, invalid auth, expired tokens, rate limits, and the long tail of error conditions. We test the error format, the status codes, and the consistency of error responses across endpoints, because consumers handle errors based on those.
We version-test explicitly. When v2 ships, the v1 tests do not get deleted. They keep running against the v1 routes. The day v1 stops behaving the way v1 consumers expect is the day a customer’s app breaks. We make that day visible by failing CI instead.
We test authentication exhaustively. Public APIs are attacked. Token expiry, token revocation, scope enforcement, rate limits, CORS, and authentication failure responses all need explicit tests. The cost of getting any of these wrong is much higher than the cost of getting a feature wrong.
We integrate with consumer test suites where possible. When a consumer is something we control (a mobile app, a browser extension), we run contract tests from both sides: the API asserts it produces the documented shape, and the consumer asserts it expects the documented shape. If either drifts, both fail.
What You Get
- Contract test suite asserting the documented API shape against the running implementation
- Behaviour tests for happy paths, edge cases, and error conditions
- Authentication and authorisation tests for every endpoint and role combination
- Version compatibility tests ensuring older API versions remain stable as newer versions ship
- Rate limit and throttling tests verifying limits are enforced and communicated correctly
- OpenAPI or Postman collections kept in sync with the test suite where useful
- CI integration so contract drift fails the pipeline before merge
Technologies We Use
- PHPUnit feature tests for Laravel APIs, with direct framework testing and full request and response coverage
- Pest where preferred for the syntax
- Postman / Newman for collection-based testing that doubles as living documentation
- k6 for combined functional and load testing of API endpoints
- OpenAPI / Swagger as the contract source of truth
- Sanctum and API key auth helpers for testing the various authentication patterns
Related Systems
API testing applies to any system that exposes endpoints to callers outside the same deploy unit. A customer self-service portal with a mobile app needs API stability to survive App Store review cycles. An outbound automation system called by external tools cannot afford to break the integrations its callers depend on. If your API is part of a broader API integrations project, the testing layer is what keeps those integrations reliable after go-live. For APIs under load, performance testing can run alongside contract tests to reveal behaviour under concurrent traffic.
Talk to Us About Testing Your API
API testing is part of our software testing services. If your API is consumed by anything you cannot redeploy at the same time (mobile, partners, customer scripts), get in touch and we will scope a contract testing engagement that prevents breaking changes from reaching consumers.
Why This Matters More Than It Looks
An API is a promise to other software. Break it and you break somebody else’s system, frequently without them finding out until a customer complains.
That is what makes API testing different from testing an interface. When a screen changes, users adapt. When a response shape changes, integrations stop working silently, and the people affected are not in the room.
If anything consumes your API, a mobile app, a partner, a customer’s integration, an internal service, that promise needs enforcing automatically rather than remembered.
What Should Be Covered
The contract. Field names, types, whether something can be null, what the response looks like. This is the bit that breaks integrations, and it breaks through ordinary refactoring by somebody who did not know the field was consumed.
Authentication and authorisation on every route. Especially that a caller cannot reach another customer’s data by changing an identifier. This is the most common serious flaw in business APIs and automated scanners rarely find it, because the request is perfectly valid.
Error responses. What comes back on bad input, missing permission, or a downstream failure. Consumers depend on these as much as the success case.
Behaviour under repetition. Whether the same call twice creates two of something. For anything taking payments or creating orders, this is where the expensive bugs live.
Where Teams Under-Test
Exports and reports, which frequently bypass the permission checks applied elsewhere because they were added later.
Old versions. Anything still consumed has to keep working, and it is easy to test only the current one.
Webhooks you send. Outbound messages are part of the promise too, and duplicate or out-of-order delivery is where consumers break.
Rate limits, which are rarely tested until somebody hits them.
What Moves The Price
How many consumers there are, and whether they are internal or external. External raises the bar considerably.
Whether a specification exists. A documented contract can be tested against automatically. An undocumented one has to be pinned down first, which is useful work in itself.
Number of routes, and how many need permission testing rather than just functional testing.
Whether third parties are involved, requiring fakes for the routine suite plus a smaller set running against the real thing.
Where This Goes Wrong
Testing only the happy path. Real consumers send malformed data, expired tokens and unexpected values.
No contract enforcement. A rename that looks harmless internally breaks every consumer.
Permissions tested once at the front door rather than on every route.
Nothing checks the real provider. Fakes test your assumption about how a third party behaves, which is precisely the assumption most likely to be wrong.
Questions To Ask Whoever Builds It
- Is the contract enforced by a test, or by convention?
- Does every route check what the caller is allowed to see? Including exports.
- What happens if the same request arrives twice?
- Are old versions still tested?
- How would a consumer find out we changed something?
A Brief You Can Send Anyone
Who consumes the API: [internal, partners, customers]
How many routes: [roughly]
What it does: [reads, writes, takes payments]
Whether a specification exists: [OpenAPI, docs, or nothing]
What breaking would cost: [and to whom]
Third parties it depends on:
How consumers are notified of changes: [today]
How We Approach It
Contract first, because that is what protects the people depending on you. Then permissions on every route, then the error paths, then the awkward cases like repetition and rate limits.
Fast fakes for the routine suite so it stays quick, plus a smaller scheduled set against the real providers so their changes are discovered by you.
The wider picture is on the testing page.