Contracts, schemas and validating responses
An API is a contract: it promises that a given request returns a response of a given shape — these
fields, these types, this structure. The app on the other side is built trusting that promise. When the API
quietly breaks it — renames a field, changes a type, drops a field, returns null where the app expects a
number — the app breaks, often in a way that is hard to trace back. A large part of API testing is checking
that the response matches its contract, every time. This lesson is contracts, schemas and validating
responses.
The API as a contract, and why it breaks
The app and the API agree on a shape. A transaction response is promised to look like:
{ "id": 42, "amount": 500, "status": "success", "createdAt": "2026-09-28T10:00:00Z" }
The mobile app reads amount as a number and status as one of a known set of strings. If a change on the
server renames amount to value, or starts returning it as a string "500", or sends status: null,
the request still returns 200 OK — but the app, trusting the old shape, shows a blank, a wrong value, or
crashes. The status code is fine; the contract is broken. These are among the most damaging API bugs
precisely because the response looks successful, so a QA only checking status codes misses them entirely.
Contracts break for ordinary reasons: a developer refactors, a field is added or removed, a type changes, an
optional field starts arriving as null. None of it shows up as an error — only as a mismatch a QA must
deliberately check for.
Validating a response beyond the status code
So for every response, you validate the body against the contract, not just the status. By hand, you check:
- Structure — all the promised fields are present, and no expected one is missing.
- Types — each field is the right type:
amounta number (not"500"),statusa string,itemsan array, a nested object where one is promised. - Values and formats —
statusis one of the allowed values (success/pending/failed, not a surpriseSUCCESSor2); a date is in the promised format; an id is positive; an amount is not negative. - Nullability — a field that must never be null is not null; an optional field is handled whether present or absent.
- Correctness — beyond shape, the values are right for what you asked (the api-test-design lesson).
Doing this by eye for one response is easy; doing it reliably for every response, every release, is not — which is why you move to schemas.
Schema validation: checking the shape automatically
A schema is a written description of the contract — the fields, their types, which are required, the
allowed values — that a tool can check a response against automatically. The common standard is JSON
Schema. A small schema for the transaction might say: an object with required fields id (integer),
amount (number), status (one of success/pending/failed), createdAt (a date-time string).
With the schema written, you validate any response against it in one step: does this body match the contract — yes or no — and if not, exactly which field is wrong. This turns "eyeball every field" into an automatic, exhaustive check, and it catches the quiet contract breaks (a renamed field, a type change, a stray null) the moment they appear. In Postman you can assert a response against a JSON Schema in a test script; in the api-automation module you will do the same in code.
Schema validation is the highest-leverage habit in API testing: one check per endpoint that catches a whole category of damaging, hard-to-spot bugs on every run.
Contract testing, and where OpenAPI fits
Many teams write their API's contract up front in an OpenAPI (formerly Swagger) specification — a formal document of every endpoint, its parameters, and its response shapes. Where it exists, it is gold for a QA:
- It is the source of truth for what each endpoint should return — you test against it rather than guessing the shape.
- Response schemas can be derived from it, so your schema validation checks the real agreed contract.
- Contract testing is the discipline of verifying the API still honours its spec — that the implementation and the OpenAPI document have not drifted apart. A mismatch is a bug in one or the other, and finding it before the app does is exactly the QA's job.
Even without a formal OpenAPI file, the idea is what matters: know the promised shape, and check every response against it.
Why this matters most for the apps you test
Tie it back to the real work. A mobile app in the field, on a mid-range Android on patchy mobile data, cannot easily be fixed the moment an API breaks its contract — the user has an old app version, the bad response crashes their screen, and the report that comes back is "the app is broken", with no clue that a field changed type on the server that morning. Catching the contract break at the API, before release — with a schema check that fails loudly — is far cheaper than tracing it from a field crash later. That is the whole argument for validating the contract, not just the status code.
Check your work
The API is a contract. It promises a response shape (fields, types, structure) the app is built to trust. Breaking it (rename, type change, dropped field, unexpected null) still returns 200 — so the status looks fine while the app breaks. These are among the most damaging and most-missed API bugs.
Validate the body, not just the status. Check structure (all promised fields, none missing), types
(number vs "500"), values/formats (allowed enum values, date format, non-negative), nullability, and
actual correctness — for every response.
Schema validation. A schema (JSON Schema) describes the contract so a tool checks a response against it automatically — one exhaustive check per endpoint that catches the quiet contract breaks on every run. The highest-leverage API-testing habit; assert it in Postman now, in code later.
Contracts and OpenAPI. An OpenAPI/Swagger spec is the source of truth for response shapes; derive schemas from it, and do contract testing to catch the implementation drifting from the spec. Even without a formal spec, know the promised shape and check against it.
Why it matters. A fielded mobile app cannot be fixed the instant an API breaks its contract; catching the break at the API before release, with a loud schema failure, is far cheaper than tracing a field crash from the wild.
Practice
- Take one API response and write down its contract: every field, its type, whether it is required, and the allowed values for any enum-like field.
- List four ways that contract could break while still returning
200 OK, and what each would do to the app. - Write a small JSON Schema for that response (object, required fields, types, an
enumfor status) and validate a good and a deliberately broken response against it. - Add a schema-validation assertion to a request in Postman and confirm it fails when a field's type is wrong.
- If the API has an OpenAPI/Swagger doc, find one endpoint's response schema in it and compare it to what the endpoint actually returns.
- Explain why a contract break is especially costly for a mobile app already installed on users' phones.
Official documentation
- JSON Schema — Getting started — Writing a schema to validate response shapes.
- OpenAPI Specification — The formal contract many APIs are described with.
- Postman — Validating responses against a schema — Asserting a JSON Schema in a Postman test.
Next: the automation-strategy module — when to automate, the test pyramid, and why flaky tests destroy trust.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.
About the internship