Catch breaking OpenAPI changes before your clients do.
SpecDiff compares two OpenAPI 3.x documents and classifies every contract change as breaking, warning, safe or info, so API changes can be gated in pull requests instead of being discovered by clients after a deploy.
The Playground runs the comparison in your browser. Your documents are not uploaded.
The problem
A pull request that removes a response field, makes a query parameter required or narrows
an enum is hard to spot in a large YAML diff. SpecDiff reads both documents, resolves
every $ref (including recursive schemas and relative files in the CLI), and
tells you which changes can break existing clients, with the rule that fired and where in
each document it happened.
Direction-aware by design
A schema describes data flowing in one direction, and what counts as compatible differs in each. The same edit can be safe in a request and breaking in a response.
| Edit | In a request | In a response |
|---|---|---|
| integer widened to number | fine | breaking |
| new required field | breaking | not a break |
| field removed | not a break | breaking |
Why: the server consumes requests, so a request change breaks clients when the server accepts less than before. The server produces responses, so a response change breaks clients when the server may send more than they were promised or less than they relied on. The rules and their rationale are in SPEC.md.
What it does
Everything listed here is described in the project README and covered by its tests.
Four severities
breaking, warning, safe and info, each change tagged with a rule ID from a documented rule table.
OpenAPI 3.0.x and 3.1.x
Compared against each other. nullable: true and type: [T, "null"] are treated as the same thing.
Recursive references
Resolves every $ref, including recursive schemas, and compares shared schemas once.
Text, JSON, Markdown
Reports with deterministic ordering: no timestamps, sorted by path, method and rule.
Built for CI
Exit codes you can gate on, configurable with --fail-on, plus --ignore and --include-safe.
Honest about limits
Constructs it does not analyze, such as oneOf and anyOf, are reported as info instead of ignored.
A realistic run
Two versions of a small Orders API, compared from the command line. This is the CLI's
real output for the example that is preloaded in the
Playground; the exit code is 1 because breaking
changes exist.
$ specdiff orders-v1.yaml orders-v2.yaml
specdiff 0.1.0
base: orders-v1.yaml (Orders API 1.0.0, OpenAPI 3.0.3)
head: orders-v2.yaml (Orders API 2.0.0, OpenAPI 3.0.3)
GET /orders
BREAKING PARAM_BECAME_REQUIRED query parameter "status" is now required
BREAKING RESP_PROPERTY_REMOVED 200 application/json: property "value[].note" removed
BREAKING TYPE_CHANGED 200 application/json: type of "value[].total" changed from integer to number
POST /orders
BREAKING REQ_PROPERTY_REQUIRED_ADDED request body application/json: property "currency" added as required
BREAKING REQ_CONSTRAINT_TIGHTENED request body application/json: maximum of "quantity" tightened from 100 to 50
BREAKING RESP_PROPERTY_REMOVED 201 application/json: property "note" removed
BREAKING TYPE_CHANGED 201 application/json: type of "total" changed from integer to number
GET /orders/{orderId}
BREAKING RESP_PROPERTY_REMOVED 200 application/json: property "note" removed
BREAKING TYPE_CHANGED 200 application/json: type of "total" changed from integer to number
WARNING RESP_STATUS_REMOVED response status 404 removed
DELETE /orders/{orderId}
BREAKING OP_REMOVED operation DELETE /orders/{orderId} removed
Summary: 10 breaking, 1 warning, 0 info (2 safe hidden, use --include-safe to list them)
Get started
Install SpecDiff from npm (Node.js 22.19 or newer), or run it once with
npx:
npm install --global specdiff
specdiff --version
# or without installing
npx specdiff base.yaml head.yaml
specdiff <base> <head> \
[--format text|json|markdown] \
[--fail-on breaking|warning|never] \
[--include-safe] [--ignore RULE_ID,...]
Exit 0 means nothing at or above the --fail-on threshold,
1 means changes at or above it, and 2 means a usage or input
error. The package is on
npm; to build from source, see the
README. A GitHub Actions recipe is in the
README.
CLI and Playground
The CLI is the product and the thing to put in CI. The Playground is a way to try it without installing anything.
Same engine
The Playground imports the CLI's normalization and diff modules and its report renderers unchanged and runs them in your browser. Only the loading step differs: the CLI reads files, the Playground parses editor text. A test suite compares the two on the project's own fixtures.
Differences
Playground documents are limited to 1 MB each, and $refs must point
inside the same document: relative file references work in the CLI only. Nothing is
uploaded, saved or placed in the URL.