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 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!
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
- Catch Breaking Changes Early
By validating the schema and status codes, contract tests identify mismatches between spec and implementation before they hit production. - Reliable Integration in Microservices
In distributed systems, many services consume and provide APIs. Contract testing ensures that downstream clients are safe from unexpected changes. - 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. - 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. - 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)
- In your Apidog project, import your OpenAPI / Swagger spec (JSON or YAML). (more on this at docs.apidog.com)
- Alternatively, build the spec directly in Apidog’s visual schema editor.

This specification defines what your API requests and responses should look like, including the structure, data types, and required fields.
2. Enable Response Validation
- In Apidog, go to Settings → Response Validation Settings.
- Enable Response Validation for the modules you plan to test: API Requests, Debug Cases, Test Cases, or Automation Test Steps.

When activated, Apidog will check every response against the contract.
3. Validate Status Codes and Response Schema
- HTTP Status Code Validation: Apidog ensures that the API returns a status code defined in your spec (e.g., 200, 404, 500).
- Schema Validation: Apidog validates the structure of the response body: required fields, data types, array/object structure, enums, and nullability.

- Additional Properties: You can configure whether unexpected fields are allowed. If
additionalPropertiesis disallowed, Apidog will flag extraneous fields as contract violations.
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:
- Launch Apidog, select the “Demo Pet” project, and navigate to the
/pet/{petId}GET endpoint.

- Set the environment to “petstore env” or “localmock” from the top-left dropdown.

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

c. Add Pre-Processor Logic:
Under Pre-Processors → Custom Script, insert your schema setup and test variables.

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"));

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

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:

Contract Test Result:

f. Simulate a Failure (Optional):
- To see contract validation in action, change your expected status code from
"OK"to200in the validation script.

- Run the test again to observe 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
- Version Your API Spec: Keep your OpenAPI spec under version control so you can track changes and avoid drift. (apidog)
- Integrate in CI/CD: Add contract tests to automated pipelines so you catch regression early. (docs.apidog.com)
- Use Strict vs. Loose Validation: Decide whether to allow extra (unknown) fields via
additionalPropertiesdepending on your risk tolerance. (docs.apidog.com) - Collaborative Workflow: Let both provider (backend) and consumer (frontend) teams work from the same contract specification.
- 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 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!



