What is API Contract Testing and How to Use Apidog for API Contract Testing

API contract testing verifies that your API implementation matches its documented contract. Learn how to use Apidog to validate response schemas, run contract tests, and generate mock servers for reliable API integration.

Ashley Goolam

Ashley Goolam

20 November 2025

What is API Contract Testing and How to Use Apidog for API Contract Testing

When building APIs—especially in microservices environments—changes to endpoints or data structures can easily lead to integration breakages. API contract testing helps prevent those by verifying that the implemented API still matches the agreed-upon “contract” or specification. In this post, we’ll explain what API contract testing is, why it’s important, and how to use Apidog to run contract tests seamlessly within your API development workflow.

💡
Want a great API Testing tool that generates beautiful API Documentation?

Want an integrated, All-in-One platform for your Developer Team to work together with maximum productivity?

Apidog delivers all your demands, and replaces Postman at a much more affordable price!
button

What Is API Contract Testing?

API contract testing is a testing approach that focuses on the interface of an API rather than its internal business logic. A contract defines how consumers (clients) and providers (servers) agree to communicate: the valid paths, expected HTTP methods, headers, request payloads, and response schemas (including status codes and data shapes). Contract tests check that the API’s actual behavior conforms to this specification.

Rather than testing full end-to-end behavior, contract testing validates the “agreement” — ensuring that the API implementation always returns data in the correct shape and respects error conditions. This helps safeguard consumers from breaking changes as the API evolves.

Why API Contract Testing Matters

  1. Catch Breaking Changes Early
    By validating the schema and status codes, contract tests identify mismatches between spec and implementation before they hit production.
  2. Reliable Integration in Microservices
    In distributed systems, many services consume and provide APIs. Contract testing ensures that downstream clients are safe from unexpected changes.
  3. Parallel Development
    With a shared API contract, front-end and back-end teams can work in parallel. The front-end uses mock servers based on the contract, while the back-end implements the spec.
  4. Automated CI/CD Validation
    Contract tests can be integrated into CI/CD pipelines to automatically reject builds when the API no longer respects the contract.
  5. Living Documentation
    The contract (typically an OpenAPI spec) serves as a source of truth. Combined with mock servers and test results, it provides up-to-date documentation and API validation.

How to Use Apidog for API Contract Testing

Apidog is an all-in-one API platform that supports designing, mocking, testing, and documenting APIs. It has built-in features for contract testing, making it easier to validate API behavior against a contract.

Here’s a step-by-step guide:

1. Import or Define Your API Contract (OpenAPI)

import openapi spec in Apidog

This specification defines what your API requests and responses should look like, including the structure, data types, and required fields.

2. Enable Response Validation

turn on response validation in Apidog

When activated, Apidog will check every response against the contract.

3. Validate Status Codes and Response Schema

status code/schema validation in Apidog

4. Create and Run Test Scenarios (Hands-On Example)

To better understand how Apidog performs API contract testing, here’s a simplified hands-on walkthrough using the built-in Demo Pet Store project.

a. Open the Demo Project:

creating a new project in Apidog
selecting an environment

b. Create a Test Case:

Go to the Test Cases tab and click “Add Case” to create a new test suite.

add test cases
-

c. Add Pre-Processor Logic:

Under Pre-Processors → Custom Script, insert your schema setup and test variables.

creating a custom test script in Apidog

Pre-Processor Validation Script:

// Set petId if not set (as string)
if (!pm.environment.get("petId")) {
  pm.environment.set("petId", "1");
}

// Define JSON schema for the pet response
const petSchema = {
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": { "type": "integer" },
    "category": {
      "type": "object",
      "properties": {
        "id": { "type": "integer" },
        "name": { "type": "string" }
      },
      "required": ["id", "name"],
      "additionalProperties": true
    },
    "name": { "type": "string" },
    "photoUrls": {
      "type": "array",
      "items": { "type": "string", "format": "uri" },
      "minItems": 0
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" }
        },
        "required": ["id", "name"],
        "additionalProperties": true
      },
      "minItems": 0
    },
    "status": {
      "type": "string",
      "enum": ["available", "pending", "sold"]
    }
  },
  "required": ["id", "name", "photoUrls", "status"],
  "additionalProperties": true
};

// Store the schema in an environment variable (stringify it)
pm.environment.set("pet_schema", JSON.stringify(petSchema));

// (Optional) log to console for debugging
console.log("Pre-processor: petId =", pm.environment.get("petId"));
adding custom js test script code in Apidog

d. Add Post-Processor Validation:

In Post-Processors, paste your AJV-based validation script that checks the API response against your schema contract.

add a custom post processors script

Post-Processor Validation Script:

// Use AJV for schema validation
var Ajv = require('ajv');
var ajv = new Ajv({ allErrors: true, logger: console });

// Retrieve schema from environment
var raw = pm.environment.get("pet_schema");
var schema;
try {
  schema = (typeof raw === 'string') ? JSON.parse(raw) : raw;
} catch (err) {
  pm.test('Schema is valid JSON', function() {
    pm.expect(false, 'pet_schema is not valid JSON: ' + err.message).to.be.true;
  });
  // Stop further tests
  return;
}

// Parse the response body as JSON
var responseData;
try {
  responseData = pm.response.json();
} catch (err) {
  pm.test('Response is valid JSON', function() {
    pm.expect(false, 'Response body is not JSON: ' + err.message).to.be.true;
  });
  return;
}

// Test status code
pm.test('Status code is 200', function() {
  pm.expect(pm.response.status).to.eql("OK");
});

// Validate schema
pm.test('Response matches pet schema', function() {
  var valid = ajv.validate(schema, responseData);
  if (!valid) {
    console.log('AJV Errors:', ajv.errors);
  }
  pm.expect(valid, 'Response does not match schema, see console for errors').to.be.true;
});

// Additional assertions
pm.test('Returned id matches requested petId', function() {
  var requested = pm.environment.get("petId");
  // petId is stored as string, but id in response is integer
  var requestedNum = Number(requested);
  if (!isNaN(requestedNum)) {
    pm.expect(responseData.id).to.eql(requestedNum);
  } else {
    pm.expect(String(responseData.id)).to.eql(String(requested));
  }
});

pm.test('Name is a string', function() {
  pm.expect(responseData.name).to.be.a('string');
});

pm.test('Status is one of expected values', function() {
  pm.expect(responseData.status).to.be.oneOf(['available', 'pending', 'sold']);
});

// Optional: more detailed checks (category, photoUrls, tags)
pm.test('Category has id and name', function() {
  pm.expect(responseData.category).to.have.property('id');
  pm.expect(responseData.category).to.have.property('name');
});

pm.test('At least one photo URL', function() {
  pm.expect(responseData.photoUrls).to.be.an('array').that.is.not.empty;
});

pm.test('Tags are valid objects', function() {
  pm.expect(responseData.tags).to.be.an('array');
  if (responseData.tags.length > 0) {
    responseData.tags.forEach(function(tag) {
      pm.expect(tag).to.have.property('id');
      pm.expect(tag).to.have.property('name');
    });
  }
});

e. Run the Test:

Click Run to execute. Apidog will show a Passed or Failed result on the right-hand panel, with expandable logs for debugging.

API Response:

API response

Contract Test Result:

View api contract test results

f. Simulate a Failure (Optional):

change js test script
the assertion error

Once you’re satisfied with the test flow, save the case for regression runs. Apidog’s visual workflow and built-in AJV validator make API contract testing accessible—even for teams without deep testing expertise.

5. Use Mock Servers for Consumer Testing

Apidog can generate mock servers based on your OpenAPI contract. These mock endpoints respond with schema-valid data.

Front-end or consumer teams can integrate against this mock server while the back-end implementation is still being built. This enables consumer-driven development.

You can define different mock examples (success, error, edge cases) so consumers can test how their code behaves under varied scenarios.

Best Practices for API Contract Testing with Apidog

  1. Version Your API Spec: Keep your OpenAPI spec under version control so you can track changes and avoid drift. (apidog)
  2. Integrate in CI/CD: Add contract tests to automated pipelines so you catch regression early. (docs.apidog.com)
  3. Use Strict vs. Loose Validation: Decide whether to allow extra (unknown) fields via additionalProperties depending on your risk tolerance. (docs.apidog.com)
  4. Collaborative Workflow: Let both provider (backend) and consumer (frontend) teams work from the same contract specification.
  5. Monitor Contract Drift: Regularly review contract test failures to detect unintended breaking changes.

Frequently Asked Questions

Q1. What exactly is an API contract?
Ans: An API contract is a formal definition of request/response expectations, typically defined in OpenAPI: endpoints, methods, request bodies, headers, response structure, and status codes. (apidog)

Q2. How does contract testing differ from functional testing?
Ans: Functional testing checks business logic (does the API do what it's supposed to do). Contract testing checks that the structure of the API (schema, status codes, headers) remains consistent with the specification.

Q3. Can Apidog contract testing work without an OpenAPI spec?
Ans: While Apidog’s contract testing is deeply integrated with OpenAPI, you can generate a spec manually or via tools and then import it into Apidog. (docs.apidog.com)

Q4. How strict should I make the schema validation (regarding extra fields)?
Ans: It depends: if your API must be very stable and backward-compatible, you may disable additional properties and enforce strict schema. For more flexibility, you can allow extra fields (additionalProperties). (docs.apidog.com)

Q5. Will contract tests slow down my CI/CD pipeline?
Ans: Not significantly. Contract tests are lightweight and focus on structure, not business logic. Running them in the pipeline gives high-value feedback with relatively low overhead. (docs.apidog.com)

Conclusion

API contract testing is a powerful strategy for reducing integration risks, maintaining API stability, and ensuring that both provider and consumer teams remain aligned around a shared specification. Using Apidog for contract validation, mock server generation, and automated test scenarios offers an elegant, unified solution — enabling development teams to catch breaking changes early, document their APIs reliably, and collaborate more productively.

If your team is building APIs—especially in a distributed or microservices architecture—implementing contract testing with Apidog is a smart investment in long-term resilience and developer confidence.

💡
Want a great API Testing tool that generates beautiful API Documentation?

Want an integrated, All-in-One platform for your Developer Team to work together with maximum productivity?

Apidog delivers all your demands, and replaces Postman at a much more affordable price!
button

Explore more

How to Keep Claude Code Continuously Running Non-Stop (This Plugin is Magic)

How to Keep Claude Code Continuously Running Non-Stop (This Plugin is Magic)

A developer-focused guide to keeping Claude Code continuously running non-stop through autonomous loop plugins and agent workflows with CLI commands and automation patterns.

30 December 2025

How to Generate API Test Collections from OpenAPI Specs

How to Generate API Test Collections from OpenAPI Specs

Learn how to generate API test collections from OpenAPI specs using Apidog. This step-by-step guide shows how to import specs and use AI to automatically create structured API test cases.

30 December 2025

Which Tool for Data-driven API Testing with CSV or JSON

Which Tool for Data-driven API Testing with CSV or JSON

Looking for a tool for data-driven API testing with CSV or JSON? Learn how Apidog enables scalable, data-driven API tests with a step-by-step guide.

30 December 2025

Practice API Design-first in Apidog

Discover an easier way to build and use APIs