Postman Contract Testing

A contract is a written agreement between an API provider and the apps that use it. The contract states which endpoints exist, which fields appear, and which types those fields carry. Contract testing checks that the real API still keeps its promises, so a change on the server never breaks a mobile app by surprise.

The Restaurant Menu Promise

A restaurant prints a menu. Customers order from it and expect the dishes to match the descriptions. If the kitchen quietly swaps chicken for fish, customers get unhappy. The menu is the contract, and the kitchen is the provider. Contract tests act as the inspector who compares served dishes with the menu.

  CONTRACT (OpenAPI file)           REAL API RESPONSE
  ───────────────────────           ─────────────────
  GET /users/{id}                   GET /users/1
    id    : integer                   "id": 1                  ✅
    name  : string                    "name": "Asha"           ✅
    email : string                    "email": 12345           ❌ type changed

Who Depends on the Contract

  • Provider: the team that builds and runs the API.
  • Consumers: mobile apps, websites, and partner systems that call the API.

Consumers write code that expects a certain shape. A silent change breaks that code. Contract tests protect consumers and give providers confidence to release faster.

Breaking and Safe Changes

ChangeImpact
Remove a fieldBreaking, consumers may need it
Rename a fieldBreaking
Change a field type, such as number to textBreaking
Make an optional field requiredBreaking for requests
Add a new optional fieldUsually safe
Add a new endpointSafe

Create the Contract

Postman stores contracts as API definitions in OpenAPI format. Import an existing OpenAPI file through the Import button, or write a new definition in the API builder. The definition lists every path, method, parameter, request body, and response schema.

Build Contract Tests with Schemas

Copy the response schema from the contract into a test script. Use one schema per response type.

const userContract = {
  type: "object",
  required: ["id", "name", "email"],
  properties: {
    id:    { type: "integer" },
    name:  { type: "string" },
    email: { type: "string" }
  }
};

pm.test("User response follows the contract", function () {
    pm.response.to.have.jsonSchema(userContract);
});

Add checks for status codes and headers listed in the contract.

pm.test("Contract status is 200", function () {
    pm.response.to.have.status(200);
});

pm.test("Content-Type matches the contract", function () {
    pm.expect(pm.response.headers.get("Content-Type")).to.include("application/json");
});

Test Error Responses Too

Contracts describe failures as well as successes. A 404 response should follow the documented error shape.

const errorContract = {
  type: "object",
  required: ["error"],
  properties: { error: { type: "string" } }
};

pm.test("Missing user returns the documented error", function () {
    pm.response.to.have.status(404);
    pm.response.to.have.jsonSchema(errorContract);
});

Contract Test Workflow

  1. Agree on the contract (OpenAPI file)
        │
  2. Write schema tests for every endpoint
        │
  3. Run tests in a pipeline after each code change
        │
        ├── Pass ──► Release safely
        └── Fail ──► Fix the code or update the contract together with consumers

Link the Pipeline

Run the contract collection with Newman or Postman CLI on every code change. A failing contract test stops the release before consumers notice. Store the OpenAPI file in the same repository as the server code, so the contract changes together with the implementation.

Good Contract Habits

  • Update the contract first, then change the code.
  • Announce breaking changes to consumers well before release.
  • Version the API, such as /v1 and /v2, so old consumers keep working.
  • Test both required and optional fields.
  • Keep example data in the contract realistic and free of personal details.

Key Points

  • A contract states what an API promises to its consumers.
  • Contract tests compare real responses with the agreed schema.
  • Removing, renaming, or retyping fields breaks consumers.
  • Automated runs catch contract drift before release.
  • Versioning lets providers evolve APIs safely.