The idea
A single-binary CLI that takes two OpenAPI (or GraphQL SDL) specs — old vs. new, or staging vs. prod — and produces a structured diff classified as breaking, additive, or cosmetic. Removed endpoints, tightened request validation, changed response types, and dropped enum values get flagged as breaking; new optional fields and new endpoints don't. Drop it into CI as a step that runs on every PR touching the API layer and exits non-zero on any breaking change, with a rendered summary posted as a PR comment.
Why build this
Teams that version APIs for external consumers (or just have multiple internal services on independent deploy schedules) routinely ship breaking changes by accident — a field goes from optional to required, a 200 becomes a 204, an enum loses a value some client still depends on. Nobody catches it because nobody manually diffs specs, and generic API testing tools check behavior, not contract shape. Spec-driven development is now common enough (most services already generate an OpenAPI doc) that a tool can hook into that artifact directly instead of asking teams to write new tests.
Stack sketch
- CLI in Go for a single static binary, easy to drop into any CI image
- OpenAPI parsing via
libopenapiorkin-openapi; GraphQL SDL diffing as a stretch goal viagraphql-go-tools - Diff engine walks both spec trees and classifies each change against a rule table (removed path, changed required-ness, narrowed type, removed enum value, etc.)
- Output: JSON for machine consumption, plus a Markdown renderer for PR comments
- GitHub Action wrapper that posts the Markdown table as a PR comment via the checks API
- Config file (
.apidiff.yml) to mark specific breaking-change classes as warnings instead of hard failures, and to exclude deprecated/sunset paths
Scope for v1
- OpenAPI 3.x support only, JSON and YAML input
- Local file-to-file and file-to-git-ref diffing (
apidiff diff old.yaml HEAD:new.yaml) - Fixed set of breaking-change rules, not user-extensible yet
- GitHub Actions integration; other CI providers just get the CLI and JSON output
- No hosted service, no dashboard — this is a CLI and a CI step, full stop
Where it could go
A hosted mode could track spec history over time per repo, giving teams a changelog of every API version and a searchable record of when a given field was added or removed — useful for support teams debugging "which client version still expects the old shape." From there, a client-SDK generator that only regenerates on additive changes (and warns on breaking ones before regenerating) would close the loop between spec and consumer.
The GraphQL side is also a real opportunity: schema diffing is a known pain point in that ecosystem and existing tools (like Apollo's) are tied to a hosted registry, so a local-first, GraphQL-and-REST CLI would stand out.
Watch out for
Breaking-change classification is genuinely subtle — a field becoming optional-to-required is breaking for request bodies but the reverse is breaking for response bodies, and getting these rules wrong either cries wolf constantly or misses real breaks, either of which kills trust in the tool fast.