← SpecCaster · Blog

How to catch breaking API changes automatically in CI

SpecCaster blog · 2026-09-11 · 4 min read

A "minor" refactor that renames a field on a widely used endpoint is a breaking change. Your tests still pass, because nobody updated them to the new shape either. Your CI is green. Production is silently incompatible.

Detecting breaking changes is usually a separate diffing step — compare two evolved versions of the spec and fail when schemas tighten. That works, but it has a blind spot: it detects changes between spec versions, not changes the spec no longer describes. The code can break while the spec stays frozen.

Two gates are cheaper than one archaeology session

Contract testing closes that gap differently. Make the committed test suite derived from the spec, and add a freshness gate:

# Gate 1 — the drift gate (fails on every PR)
# the committed suite must match the spec; regenerate & diff
npx speccaster drift --spec openapi.yaml --out speccaster/contract.test.js

# Gate 2 — the contract run (fails when the API violates the spec)
SPECCASTER_BASE_URL=https://api.example.com/v1 \
  node --test speccaster/contract.test.js

Both gates are generated by one command, live in your repo as normal test files, and run anywhere node does — there is no dashboard to set up and no runtime telemetry.

A working example

There is a complete, committed example in the repo — examples/petstore-ci: a single-file API, its OpenAPI spec, the generated suite, and the CI workflow. Change the spec (drop an endpoint: npx speccaster init --force, then npx speccaster drift) and watch the build fail — that is the first PR you want to catch.

The point isn't "tests were written." The point is that the moment spec, code, and tests disagree, something visible fails before production does. That is what "catching breaking changes automatically" actually takes.

What it does not do (honest scope)

Generated happy-path coverage is not a substitute for deep property-based fuzzing (Schemathesis), schema linting (Spectral), or hand-written sequence tests. It is the cheap, always-on fresh-contract floor: play it next to those, not instead of them.

See the loop in seconds — zero setup:
npx speccaster demo

Ephemeral API, generated suite, green run, then a spec edit changing the suite live. Nothing written to your repo.

Get started with SpecCaster