Integration Guide
FastAPI integration guide
FastAPI generates OpenAPI documentation automatically from your Pydantic models and route decorators. StateAnchor sits upstream of your merge and gates changes to those models and route signatures before they reach SDK consumers -- catching the drift that OpenAPI export alone cannot prevent.
This guide covers FastAPI teams that have typed API consumers: other internal services, external developers, or AI agents that call your endpoints. If your API is internal-only and consumers are always updated in lockstep, StateAnchor still helps but is less critical.
What you’ll need
- Python 3.9 or later
- FastAPI (any recent version)
- A GitHub repository
- A StateAnchor account -- connect a repo to start
Step 1 -- Map your API to stateanchor.yaml
Create a stateanchor.yaml file in your repository root. Map your Pydantic request and response models to the models section, using PascalCase names that match your Python class names. Each FastAPI route becomes one entry inendpoints.
Here is a complete example for an Items service:
service: items-api
version: "1.0.0"
info:
title: Items API
description: FastAPI items service for the Acme platform
server:
base_url: https://api.acme.com
auth:
type: bearer
models:
Item:
id: integer
name: string
description: string
price: number
in_stock: boolean
ItemCreate:
name: string
description: string
price: number
ItemResponse:
id: integer
name: string
price: number
created_at: string
endpoints:
- name: listItems
method: GET
path: /items
description: List all items
- name: getItem
method: GET
path: /items/{item_id}
description: Get a single item by ID
returns:
$ref: ItemResponse
- name: createItem
method: POST
path: /items
description: Create a new item
body:
$ref: ItemCreate
returns:
$ref: ItemResponse
- name: updateItem
method: PUT
path: /items/{item_id}
description: Update an existing item
body:
$ref: ItemCreate
returns:
$ref: ItemResponse
- name: deleteItem
method: DELETE
path: /items/{item_id}
description: Delete an item
outputs:
python: true
typescript: truestateanchor.yaml should match your Pydantic class names. Use PascalCase consistently: ItemCreate, ItemResponse, not item_create or itemCreate.A few things to note:
- Separate request and response models -- FastAPI encourages
ItemCreate(no id) for POST body andItemResponse(with id, timestamps) for responses. Model them separately in StateAnchor so the gate catches if you accidentally expose or remove fields. - Path parameters -- use the same format as FastAPI:
/items/{item_id}. The braces must be present. - outputs -- set
python: trueto generate a typed Python client that matches your Pydantic schemas.
Step 2 -- Add the GitHub Action
The StateAnchor GitHub Action validates your spec on every push and PR. FastAPI teams often run tests in a parallel job -- you can structure the gate as a required step before deployment, ensuring no breaking change ships even if tests pass.
Create .github/workflows/stateanchor.yml:
name: StateAnchor gate
on:
push:
branches: ["main", "master"]
pull_request:
permissions:
contents: read
statuses: write
pull-requests: write
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install -r requirements.txt
- run: pytest
gate:
runs-on: ubuntu-latest
# Gate runs in parallel with tests; both must pass before deploy
steps:
- uses: actions/checkout@v4
- name: StateAnchor sync
uses: stateanchor/sync-action@v1
with:
api-key: ${{ secrets.STATEANCHOR_API_KEY }}Add STATEANCHOR_API_KEY to your repository secrets. You can find it in the StateAnchor dashboard under project settings.
Step 3 -- Key ERR patterns with FastAPI
FastAPI APIs evolve in predictable ways that trigger specific gate errors. These are the most common:
Adding a required field to a response model
You add a new required field sku: string to ItemResponse. From StateAnchor’s perspective, this is a field_removed-equivalent event from the consumer’s perspective -- existing SDK code that deserializesItemResponse now has a field it does not know about, and strict deserializers will fail. The gate emits type_changed or field_added_requiredand blocks the merge.
Fix: make the new field optional in your Pydantic model (sku: Optional[str] = None) and mark it as optional in StateAnchor, or version the response model.
Changing a return type
You refactor getItem to return ItemWithDetails instead ofItemResponse. StateAnchor emits type_changed because thereturns field changed. Generated SDKs will have the wrong return type, causing type errors in statically typed consumers.
Renaming a route path
You rename /items to /catalog/items. StateAnchor emits an endpoint_removed ERR for the old path and an endpoint_addedINFO for the new path. Consumers calling the old path will receive 404 after deployment.
Common patterns for FastAPI
Pydantic v2 model names
With Pydantic v2, use PascalCase model names in stateanchor.yamlthat exactly match your Python class names. StateAnchor’s TypeScript and Python SDK generators use these names as type identifiers in generated code.
Dependency injection on routes
FastAPI’s Depends() pattern is commonly used for auth. Map this toserver.auth.type for the service default, and override withauth: none on routes that use a different dependency or no auth at all:
server:
base_url: https://api.acme.com
auth:
type: bearer
endpoints:
- name: healthCheck
method: GET
path: /health
auth: none # public route, no auth dependencyBackground tasks
FastAPI routes that kick off background tasks and return immediately (202 Accepted) do not return a rich response body. For these endpoints, omit the returnsfield or set it to a simple status model:
endpoints:
- name: triggerExport
method: POST
path: /exports
description: Start a background export job
body:
$ref: ExportRequest
# returns omitted -- async job, response is 202 AcceptedNext steps
- Drift exceptions -- approve intentional breaking changes with the two-signal model
- Gate engine -- how the four drift syndromes drive the gate decision
- stateanchor.yaml reference -- complete field-by-field spec documentation