testing-api-contracts
Skill118 starsChanged 2 months agoMITView on GitHub
Validates API responses against OpenAPI or JSON Schema, detects breaking changes between spec versions, and builds consumer-driven contract checks. Use when an API has a published spec, when a backend change might break a client, when API tests assert only status codes, or when mocked fixtures need a guard against drifting from the real service.
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 7 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 10
Use this skill when the question is not "does the endpoint work" but "does the endpoint still promise what its consumers were built …
- Distinctive: line 25
The spec is the contract, the implementation is the claim: Test the claim against the contract, in both directions.
- Distinctive: line 44
If the spec is hand-written and the implementation is not generated from it, say so.
- Distinctive: line 75
optional fields absent: - not present rather than present-and-null.
- Very specific: line 83
When a spec has changed, produce a compatibility verdict rather than a list of edits.
- Distinctive: line 95
If the codebase mocks this API anywhere, the spec is also the guard for those fixtures.
- Distinctive: line 98
run this check on the same cadence as the spec changes, not on every commit
- Very specific: line 104
Use ./resources/contract-report-template.md.
- Distinctive: line 147
every spec change carries a safe, risky, or breaking classification with its rationale
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Testing API Contracts
Use this skill when the question is not "does the endpoint work" but "does the endpoint still promise what its consumers were built against".
A contract test checks shape and compatibility, not business behaviour. It answers: did a field disappear, did a type change, did an enum gain a value the client cannot handle, did a required field become optional. Functional API tests answer whether the value is correct. Both are needed and they fail for different reasons, which is the point of keeping them separate.
When to Use
- an API publishes an OpenAPI or JSON Schema document and nothing verifies the implementation matches it
- API tests assert
status === 200and nothing about the body - a backend change is about to ship and no one can say which clients it breaks
- mocked fixtures need a drift guard against the real service
- two teams are arguing about whether a change is breaking
- a spec exists but has visibly diverged from what the service returns
Operating Principles
- The spec is the contract, the implementation is the claim. Test the claim against the contract, in both directions.
- Shape checks and value checks stay separate. Mixing them produces a test that fails for two unrelated reasons and reports one message.
- Additive is safe, subtractive is not. Adding an optional response field breaks nobody. Removing one, or tightening a type, breaks everybody who read it.
- Validate every response, not a sampled one. Schema validation is cheap enough to run on every API call the suite already makes.
- A breaking change is defined by consumers, not by the provider. A field no client reads can be removed freely; the argument is about evidence, not opinion.
- Undocumented behaviour is a finding. A response field absent from the spec is either a spec gap or an accidental leak. Both get reported.
Workflow
Phase 0: Locate the contract
Find the authoritative artifact and record which it is:
- an OpenAPI document in the repository, generated from code or hand-written
- an OpenAPI document served at runtime (
/openapi.json,/swagger.json,/v3/api-docs) - standalone JSON Schema files
- a GraphQL SDL
- none of the above, in which case the first deliverable is a spec derived from observed traffic, marked as derived rather than authoritative
If the spec is hand-written and the implementation is not generated from it, say so. Hand-written specs drift, and the drift is exactly what this skill exists to surface.
Phase 1: Decide which side you are testing
| Side | Question | Typical artifact |
| Provider | Does our service return what our spec promises? | Schema validation over live responses |
| Consumer | Do we still work against what the provider promises? | Fixture validation plus a live sample check |
| Both | Are these two versions of the spec compatible? | Spec diff and breaking-change report |
Choose one per run. A single output that mixes provider defects with consumer risks is unreadable to either team.
Phase 2: Wire validation into requests already being made
The cheapest contract coverage is a validator attached to the existing API test suite. Every request the suite already sends gets its response validated for free.
Recipes for ajv, zod, openapi-response-validator, and a Playwright expect extension are in ./resources/schema-validation-recipes.md.
Rules for the validator:
- Strict by default.
additionalProperties: falsewhen the spec allows it, so undocumented fields surface instead of passing silently. - Validate the error responses too. The 4xx body shape is part of the contract and is where drift is most common.
- Report the path, not just "invalid".
/items/0/price: expected number, got stringis actionable;schema validation failedis not. - Fail the test. A validator that logs a warning gets ignored within a week.
Phase 3: Cover the shape, not the sample
For each endpoint in scope, check the cases in ./resources/contract-coverage-checklist.md. The ones that catch real defects:
- empty collection -
items: []with the pagination envelope intact - nullable fields actually null - the spec says nullable, so make one null
- optional fields absent - not present rather than present-and-null; these are different contracts
- maximum-length and boundary values - the field the spec caps at 255 characters
- every enum member - a client switch statement that has no default breaks on the value you never sent
- error responses - one per documented status code
- pagination edges - first page, last page, past the end
Phase 4: Diff the versions
When a spec has changed, produce a compatibility verdict rather than a list of edits. Classify every change using ./resources/breaking-change-checklist.md:
| Class | Examples | Verdict |
| Safe | New optional response field, new endpoint, new optional request parameter, widened response enum a client treats as opaque | Ship |
| Risky | New enum value in a field clients branch on, tightened validation, changed default, changed ordering, changed pagination size | Ship with a consumer check |
| Breaking | Removed or renamed field, narrowed type, required field added to a request, optional response field made absent, status code change, auth requirement change | Version it or coordinate |
For every Risky and Breaking item, name the affected consumers if they are knowable, and say what evidence supports the claim. "Unknown consumers" is a valid finding and raises the severity.
Phase 5: Guard the mocks
If the codebase mocks this API anywhere, the spec is also the guard for those fixtures. Validate the fixtures against the same schema:
- fixtures that fail validation are stale and are reported as defects in the test suite, not in the API
- run this check on the same cadence as the spec changes, not on every commit
This is the handoff point with mocking-network-and-time.
Phase 6: Report
Use ./resources/contract-report-template.md. A useful report contains:
- which spec, which version, which side was tested
- endpoints covered and endpoints skipped, with the reason for skipping
- validation failures grouped by endpoint, with the JSON path and both values
- the compatibility verdict per change, with severity
- undocumented fields found in responses
- what remains unverified
Common Failure Modes
- asserting only the status code and calling it an API test
- validating the happy path and never the documented error bodies
additionalPropertiesleft permissive, so a leaked internal field passes forever- diffing two specs and reporting every line changed rather than classifying compatibility
- calling a change non-breaking because no test failed, when no test covered it
- treating a generated spec as proof of correctness; a spec generated from the code agrees with the code by construction
- one report that mixes provider bugs, consumer risks, and spec gaps
Resource Map
./resources/schema-validation-recipes.md-ajv,zod,openapi-response-validator, and a reusable Playwright matcher./resources/breaking-change-checklist.md- full classification of spec changes into safe, risky, and breaking, for requests and responses./resources/contract-coverage-checklist.md- the response shapes to force per endpoint./resources/contract-report-template.md- report structure with a worked example
Related Skills
api-playwright-test-developer- when the functional API tests these validators attach to are being writtenmocking-network-and-time- when the spec is being used to guard mocked fixtures against driftanalyzing-regression-scope- when a breaking change needs its retest blast radius mappedverifying-acceptance-criteria- when the question is whether behaviour meets its stated contract rather than its shapeassessing-release-readiness- when a breaking change feeds a go/no-go decisiondocumenting-test-suites- when the spec gaps found here need writing up
Definition of Done
This skill is complete when:
- the authoritative spec is identified and its trustworthiness stated
- the side under test (provider, consumer, or version diff) is declared
- validation runs on every response the suite produces, including error responses, and fails the test on mismatch
- the shape cases from the coverage checklist are forced rather than hoped for
- every spec change carries a safe, risky, or breaking classification with its rationale
- undocumented response fields are reported
- mocked fixtures for this API are validated against the same schema, or their absence is noted
- the report says what was not covered
In this repository51 other files it gives its agents.
- analyzing-quality-metricsSkill
- analyzing-regression-scopeSkill
- api-playwright-test-developerSkill
- assessing-comprehension-debtSkill
- assessing-release-readinessSkill
- attesting-manual-verificationSkill
- auditing-accessibilitySkill
- code-review-advancedSkill
- code-reviewSkill
- communicating-quality-findingsSkill
- creating-custom-agentsSkill
- creating-hooksSkill
- creating-instructionsSkill
- creating-orchestration-packsSkill
- creating-pluginsSkill
- creating-promptsSkill
- creating-skillsSkill
- deriving-a-quality-contractSkill
- designing-functional-testsSkill
- designing-test-dataSkill
- documenting-test-suitesSkill
- generating-quality-gate-workflowsSkill
- governing-quality-waiversSkill
- handling-sensitive-test-dataSkill
- migrating-tests-to-playwrightSkill
- mocking-network-and-timeSkill
- planning-exploratory-testingSkill
- prd-generatorSkill
- recording-change-intentSkill
- reporting-bugsSkill
- requirements-test-coverage-mapperSkill
- reviewing-ai-output-groundednessSkill
- running-visual-regression-testsSkill
- scoping-change-relevanceSkill
- static-code-analysis-typescriptSkill
- tech-debt-analysisSkill
- test-driven-development-quickSkill
- test-driven-developmentSkill
- testing-agent-skillsSkill
- testing-application-securitySkill
- testing-llm-featuresSkill
- testing-llm-guardrailsSkill
- testing-performance-and-loadSkill
- tracing-requirements-to-codeSkill
- tracking-quality-trendsSkill
- unslop-answersSkill
- unslop-testsSkill
- verifying-acceptance-criteriaSkill
- verifying-change-coverageSkill
- writing-unit-tests-quickSkill
- writing-unit-testsSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

