Skip to main content

fastapi-contract

Catch FastAPI breaking changes that OpenAPI diff can't see.

v0.1 Technical Preview: the CLI currently checks FAPI001 response projection compatibility only. The public API and snapshot format are not yet stable.

Why

A FastAPI route can keep the same OpenAPI response schema while returning fewer fields. fastapi-contract compares extracted runtime configuration to a saved baseline and reports changes in the supported contract surface. It complements OpenAPI diff tools; a SAFE result is not a guarantee of full API compatibility.

Installation

Requires Python 3.11+. Install into your application's dependency environment.

pip install fastapi-contract

To try it from source, run pip install . in this repository, or use uv sync --group dev and prefix the commands below with uv run.

Quickstart

From your application project directory, create app/__init__.py and app/main.py. Put this in app/main.py:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class User(BaseModel):
    id: int
    email: str


@app.get("/users", response_model=User)
def users():
    return {"id": 1, "email": "alice@example.com"}

Save the accepted contract:

fastapi-contract snapshot app.main:app \
  -o fastapi-contract-baseline.json

After editing the application, compare it with that file:

fastapi-contract check app.main:app \
  --against fastapi-contract-baseline.json

An unchanged app prints SAFE: No incompatibility detected in the supported contract surface. and exits 0. snapshot also accepts --output instead of -o. No server needs to run.

Example breaking change

Before:

@app.get("/users", response_model=User)

After (replace only the decorator in the example):

@app.get(
    "/users",
    response_model=User,
    response_model_exclude={"email"},
)

The OpenAPI response schema still describes User, but the runtime response loses email. Running check against the original snapshot prints:

BREAKING
FAPI001 GET /users: response fields removed by projection: email

The command exits 1.

Exit codes

Code Result Meaning
0 SAFE No incompatibility detected in the supported surface; snapshot saved successfully for snapshot.
1 BREAKING / REVIEW A breaking projection change or a relevant change requiring human review.
2 ERROR Invalid arguments, app loading/file/analysis failure, invalid snapshot, or incompatible environment.

Supported rules

FAPI001 — Effective Response Projection Changed is the only enabled rule. Slice 1 supports static top-level projection of supported flat response models. Unsupported relevant changes can produce REVIEW rather than a definite finding. See the FAPI001 specification for the precise boundary.

Current limitations

  • Technical Preview, FAPI001 only; no alias, omission, or request-side checks.
  • Analysis is limited to the supported top-level Slice 1 surface. It does not exercise endpoints or prove their returned values match their declarations.
  • Baselines are snapshot files using the existing schema v1. There is no Git baseline loading, environment reconstruction, or automatic baseline refresh.
  • Baseline and current must use the same runtime/dependency environment. The checker requires matching recorded Python, FastAPI, Starlette, and Pydantic versions; keep exact versions consistent, including Python patch versions.
  • App loading imports module:attribute in the current process. Module-level side effects execute; only load trusted application code. No subprocess isolation is provided. Run from the project directory or install its modules.
  • Startup, lifespan, and the server are not run. Routes registered only during startup or lifespan are therefore not included.

CI usage

Commit fastapi-contract-baseline.json alongside your application. For a project that has fastapi-contract in its locked uv dependencies, a minimal GitHub Actions job is:

name: Contract check
on: [push, pull_request]
jobs:
  contract:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version-file: .python-version
      - run: python -m pip install uv
      - run: uv sync --frozen
      - run: >-
          uv run fastapi-contract check app.main:app
          --against fastapi-contract-baseline.json

Commit an exact Python patch version in .python-version and use that version and the same lockfile when generating the baseline. Keep the committed baseline unchanged during ordinary CI checks. For an intentional contract change, review its consumer impact, rerun snapshot in the matching environment, and commit the updated baseline with the application change for review.

Roadmap

  • Response serialized alias compatibility
  • Response omission behavior
  • Request-side runtime contracts
  • Other hidden runtime contracts
  • Git baseline workflow

Development

uv sync --group dev
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run mypy src
uv build

License

Apache License 2.0. See LICENSE.

Metadata

Release files for fastapi-contract 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastapi-contract 0.1.0
File Size Uploaded
fastapi_contract-0.1.0.tar.gz 95.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fastapi-contract 0.1.0
File Interpreter ABI Platform
fastapi_contract-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 120.6 kB

Release files / fastapi_contract-0.1.0.tar.gz

Download URL fastapi_contract-0.1.0.tar.gz
Size 95.0 kB
Tags Source
SHA-256 checksum
How to use checksums
732a773ad49bfaa2b563d2a9e7e0142a1f30d7a8bd8fbb0e01814d86e8d34557
BLAKE2b-256 checksum
How to use checksums
6309e7f55f46d961f7c50bb96a8350604e1bef8da53dc6b7006376ef230c6762
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.

Transparency log

Release files / fastapi_contract-0.1.0-py3-none-any.whl

Download URL fastapi_contract-0.1.0-py3-none-any.whl
Size 25.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b09ff3bf183b603a749c95d2bebc8ac4e3f4d5d2db51ff337a3cdb879b3f0888
BLAKE2b-256 checksum
How to use checksums
f37f7b74eb88746fb5e557d7cd378baba3833af7ba626a670a3a3e569ae39bf2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page