API testing 101: the contract-first approach for modern teams
Most teams test their APIs by clicking buttons in a UI. There's a better way that costs almost nothing to set up.
If you're testing your API by clicking buttons in your frontend and watching the network tab, you're doing it the hard way. You're also coupling your API correctness to your UI correctness, which means a frontend regression silently masks an API regression.
The fix is contract-first API testing, and it's both faster and cheaper than what you're probably doing today.
The basic idea, in one paragraph
For each public-ish endpoint, write a small set of tests that:
- Make the request directly to the API (not through the UI).
- Assert against the response shape and a few key values.
- Run on every PR, in CI, in seconds.
That's it. No UI, no browsers, no flaky end-to-end runs.
What "contract-first" means in practice
A contract test is a small, deterministic check that says "this endpoint, given this input, returns this shape". It doesn't test the entire surface of the API — it locks down the part your consumers depend on.
- name: Returns 200 + the new bug
method: POST
url: /api/v1/bugs
body:
title: "Test bug from CI"
severity: "high"
assertions:
- status == 201
- body.title == "Test bug from CI"
- body.id matches uuid
- duration_ms < 500
A contract test is not:
- A unit test (those live in your codebase, not a separate tool).
- A load test (those need different infrastructure).
- A test of "all the business rules" (those should live close to the code that implements them).
It's a behavioral promise to the outside world, locked down.
The four kinds of contract assertions worth writing
For every endpoint you care about, write all four:
- Status + shape. "200 OK, response has these fields."
- One happy-path value check. "Created bug's title matches what I sent."
- One auth/permissions check. "Without my token, I get 401."
- One performance budget. "p95 < 500ms on this endpoint."
That's typically 4 × N assertions where N is the number of endpoints you actually care about — usually under 30 for most teams.
How Lepta QA does this
In Lepta QA, an API test is a declarative spec — request, assertions, optional setup steps. You write it once, save it as a test case, and it runs:
- On every push, in CI.
- On a schedule against staging and production.
- Every time someone changes the underlying schema (we hook into your OpenAPI spec).
When something fails, you get the full request, response, headers, timing, and a diff against the last green run. No "I'll just curl it locally to see what's wrong" — the run report has everything.
The trick that gets your team to actually write them
Don't write them upfront. Write them after a bug ships in production.
Every API-side bug you fix gets a contract test that would have caught it. Six months later, you have a meaningful suite. Two years later, you have a regression net that catches breaking changes before they ship.
The cheapest contract test is the one you write the day after a bug bites you. Don't try to predict; just don't repeat.
What to skip
You can confidently not write contract tests for:
- Internal-only endpoints with one consumer (test those at the consumer).
- Admin-only debug routes.
- Endpoints whose only consumer is your own backend.
Focus on the surface that other systems — your frontend, your mobile app, your customers' integrations — actually depend on. That's where breaks cost real money.
Stop juggling tabs. Ship with confidence.
Run live testing rooms, capture bugs, and let AI summarize the work — all in one workspace.