Skip to main content

API Contract Testing

API contracts define the expected structure, behavior, and constraints of your APIs. SureStage validates mock responses against contracts to ensure they match real API specifications, catching integration issues before they reach production.

Why Use Contract Testing

  • Prevent breaking changes - Ensure mocks match production API contracts
  • Catch drift early - Detect when mocks diverge from real APIs
  • Enforce standards - Require specific response formats or headers
  • Document expectations - Contracts serve as executable API documentation
  • Enable parallel development - Frontend teams trust mocks match production

How It Works

  1. Define a contract specifying expected API behavior (schema, status codes, headers)
  2. Attach the contract to a Sandbox
  3. SureStage validates mock responses against the contract when routes are created or modified
  4. Violations are logged and can trigger alerts or block changes

Creating a Contract

API Request

curl -X POST https://api.surestage.com/v1/simulations/sandbox_abc123/contracts \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "User API Contract",
"version": "1.0",
"rules": [
{
"path": "/users/:id",
"method": "GET",
"expectedStatus": 200,
"responseSchema": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"email": { "type": "string", "format": "email" }
},
"required": ["id", "name", "email"]
},
"requiredHeaders": ["Content-Type"]
}
],
"enforcement": "warn"
}'

Response 201 Created

{
"id": "contract_xyz789",
"name": "User API Contract",
"version": "1.0",
"rules": [ /* ... */ ],
"enforcement": "warn",
"createdAt": "2026-03-21T10:00:00Z"
}

Parameters

FieldTypeRequiredDescription
namestringYesContract name
versionstringYesContract version (semantic versioning recommended)
rulesarrayYesArray of contract rules (see below)
enforcementstringNowarn or block (default: warn)

Rule Structure

FieldTypeRequiredDescription
pathstringYesAPI path (supports params like :id)
methodstringYesHTTP method
expectedStatusnumberYesExpected response status code
responseSchemaobjectNoJSON Schema for response body
requiredHeadersarrayNoRequired response headers
forbiddenHeadersarrayNoHeaders that must not be present

Enforcement Modes

Warn Mode

Violations are logged but do not block route creation:

{
"enforcement": "warn"
}

When a route violates the contract, you see a warning in the response:

{
"routeId": "route_123",
"created": true,
"warnings": [
{
"contractId": "contract_xyz789",
"rule": "/users/:id GET",
"violation": "Response schema missing required field: email"
}
]
}

Block Mode

Violations prevent route creation:

{
"enforcement": "block"
}
{
"error": "CONTRACT_VIOLATION",
"message": "Route violates contract: User API Contract",
"violations": [
{
"rule": "/users/:id GET",
"issue": "Response schema missing required field: email"
}
]
}

Response Schema Validation

Use JSON Schema to define expected response structure:

Example Schema

{
"responseSchema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"status": { "type": "string", "enum": ["active", "inactive"] }
},
"required": ["id", "status"]
}
},
"pagination": {
"type": "object",
"properties": {
"page": { "type": "integer", "minimum": 1 },
"total": { "type": "integer", "minimum": 0 }
},
"required": ["page", "total"]
}
},
"required": ["data", "pagination"]
}
}

This validates that responses include:

  • A data array with objects containing id and status
  • A pagination object with page and total fields

Contract Exceptions

Temporarily bypass contract validation for specific routes using exceptions.

Create Exception

curl -X POST https://api.surestage.com/v1/simulations/sandbox_abc123/contracts/contract_xyz789/exceptions \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"routeId": "route_456",
"reason": "Legacy route uses deprecated format",
"expiresAt": "2026-06-01T00:00:00Z"
}'

Response 201 Created

{
"id": "exception_abc123",
"contractId": "contract_xyz789",
"routeId": "route_456",
"reason": "Legacy route uses deprecated format",
"expiresAt": "2026-06-01T00:00:00Z",
"createdAt": "2026-03-21T10:30:00Z"
}

Routes with active exceptions bypass contract validation until the exception expires.

List Exceptions

curl https://api.surestage.com/v1/simulations/sandbox_abc123/contracts/contract_xyz789/exceptions \
-H "Authorization: Bearer $TOKEN"

Delete Exception

curl -X DELETE https://api.surestage.com/v1/simulations/sandbox_abc123/contracts/contract_xyz789/exceptions/exception_abc123 \
-H "Authorization: Bearer $TOKEN"

Managing Contracts

List Contracts

curl https://api.surestage.com/v1/simulations/sandbox_abc123/contracts \
-H "Authorization: Bearer $TOKEN"

Get Contract

curl https://api.surestage.com/v1/simulations/sandbox_abc123/contracts/contract_xyz789 \
-H "Authorization: Bearer $TOKEN"

Update Contract

curl -X PATCH https://api.surestage.com/v1/simulations/sandbox_abc123/contracts/contract_xyz789 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"enforcement": "block",
"version": "1.1"
}'

Delete Contract

curl -X DELETE https://api.surestage.com/v1/simulations/sandbox_abc123/contracts/contract_xyz789 \
-H "Authorization: Bearer $TOKEN"

Deleting a contract removes validation but does not affect existing routes.

Importing Contracts from OpenAPI

Generate contracts automatically from OpenAPI specs:

curl -X POST https://api.surestage.com/v1/simulations/sandbox_abc123/contracts/import \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source": "openapi",
"spec": {
"openapi": "3.0.0",
"paths": {
"/users/{id}": {
"get": {
"responses": {
"200": {
"description": "User object",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" }
}
}
}
}
}
}
}
}
}
}
}'

SureStage converts the OpenAPI spec into contract rules automatically.

Security

  • All contract operations are protected by JwtAuthGuard and TenantGuard
  • Contracts are scoped to Sandboxes — you cannot apply a contract across Tenants
  • Contract violations are logged for audit purposes

Common Issues

Problem: Contract validation passes but real API fails

Solution: Verify the contract schema matches the actual API response. Use a tool like Postman to capture a real response and compare it to your schema.

Problem: Too many false positives in warn mode

Solution: Refine your schemas to be less strict, or add exceptions for known outlier routes.

Problem: Cannot create route due to contract violation

Solution: Check the violation message to see which field is missing or incorrect. Update the route response or create a temporary exception if needed.