Agent Skills

API Contract Testing — validate an OpenAPI spec against expected endpoints

Load this skill when you need to check that a running API (or a spec on disk) actually matches the contract it promises. It is the verification counterpart of api-doc-generator (which writes the spec) and test-generator (which writes the tests): this skill checks the spec against a manifest of expected endpoints and, optionally, against the live API.

The tool is pure Python 3 stdlib — no PyYAML, no requests, no pip install. It reads an OpenAPI 3.x document from a file (.json or .yaml) or a URL, enumerates every declared operation (under paths and webhooks), checks the spec’s internal consistency, and compares it against an optional manifest file. In --offline mode it never touches the network; in live mode it probes each manifest endpoint over HTTP and compares the actual status code with the expected one.

Triggers

Load this skill when the request matches any of these (EN / RU):


The api_contract.py script

scripts/api_contract.py — pure Python 3 stdlib (no dependencies).

Mode Command
Offline, JSON report python3 api_contract.py --spec openapi.json --offline --json
Offline + manifest python3 api_contract.py --spec openapi.yaml --manifest endpoints.txt --offline
Live checks python3 api_contract.py --spec openapi.json --manifest endpoints.txt --base-url https://api.example.com
Spec from URL python3 api_contract.py --spec-url https://example.com/openapi.json --manifest endpoints.txt

Flags

Exit codes

Code Meaning
0 conformant (or offline-ok)
1 contract violations detected (missing endpoints, mismatched statuses)
2 spec/parse/run error (unreadable file, invalid JSON/YAML, bad manifest, live-check network failure)

Report structure

The report is always the same JSON structure; --json prints it verbatim, without --json it is rendered as text.

{
  "endpoints_count": 2,
  "missing_from_spec": [{"method": "DELETE", "path": "/pets", "expected": "204"}],
  "contract_violations": [{"method": "GET", "path": "/pets", "expected": "200", "actual": "404", "severity": "error"}],
  "conformant": false,
  "errors": []
}

Usage example (typical)

# 1. Offline sanity check of a spec: is it internally consistent?
python3 skills/api-contract-testing/scripts/api_contract.py \
  --spec openapi.yaml --offline --json

# 2. Does the spec cover everything the product promised?
python3 skills/api-contract-testing/scripts/api_contract.py \
  --spec openapi.json --manifest endpoints.txt --offline --json

# 3. Live: does the running API actually return the promised statuses?
python3 skills/api-contract-testing/scripts/api_contract.py \
  --spec openapi.json --manifest endpoints.txt --base-url https://api.example.com

# 4. Machine-readable gate for CI (exit code drives the pipeline)
python3 skills/api-contract-testing/scripts/api_contract.py \
  --spec openapi.yaml --manifest endpoints.txt --offline --json \
  | python3 -c 'import json,sys; sys.exit(0 if json.load(sys.stdin)["conformant"] else 1)'

Manifest format

# expected API contract
GET    /pets        200
POST   /pets        201
DELETE /pets/{id}   204
GET    /health      2xx

expected_status is optional — a line without it only asserts that the endpoint exists in the spec. Wildcards (2xx, 4xx) match any code in that class; default matches the spec’s default response key.

Interpretation guidance

Integration notes

Limitations

Canonical analogues

Full source depth — in references/canonical-patterns.md. Backbone:

AnalogWhat we borrow
SchemathesisSpec-driven contract checking, property-based probing of declared responses
DreddManifest/transaction-driven verification of endpoints against a live API
oasdiffSpec internal-consistency and compatibility analysis
SpectralLint-style rules for spec hygiene (warnings vs. errors)
openapi-generatorEndpoint enumeration from paths + operations as the source of truth

Installation

# For opencode
cp -r skills/api-contract-testing ~/.config/opencode/skills/

# For other agents
# Copy the skill folder to your skills directory; requires Python 3 only.

Note: the tool is read-only — it never modifies the spec, the manifest or the API. It reports; you decide what to fix.