<ahref="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display"target="_blank"title="Pay as you go for market data"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
<ahref="https://www.svix.com/"target="_blank"title="Svix - Webhooks as a service"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
<ahref="https://www.permit.io/blog/implement-authorization-in-fastapi?utm_source=github&utm_medium=referral&utm_campaign=fastapi"target="_blank"title="Fine-Grained Authorization for FastAPI"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/permit.png"></a>
<ahref="https://dribia.com/en/"target="_blank"title="Dribia - Data Science within your reach"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/dribia.png"></a>
<ahref="https://www.rapidproxy.io/?ref=fastapi"target="_blank"title="Try RapidProxy for free - Residential Proxies with 90M+ Global IPs. Starting from $0.65/GB for web scraping, automation, and data collection."><imgsrc="https://fastapi.tiangolo.com/img/sponsors/rapidproxy.png"></a>
@ -20,20 +20,6 @@ FastAPI automatically generates **OpenAPI 3.1** specifications, so any tool you
///
## SDK Generators from FastAPI Sponsors { #sdk-generators-from-fastapi-sponsors }
This section highlights **venture-backed** and **company-supported** solutions from companies that sponsor FastAPI. These products provide **additional features** and **integrations** on top of high-quality generated SDKs.
By ✨ [**sponsoring FastAPI**](https://github.com/sponsors/tiangolo) ✨, these companies help ensure the framework and its **ecosystem** remain healthy and **sustainable**.
Their sponsorship also demonstrates a strong commitment to the FastAPI **community** (you), showing that they care not only about offering a **great service** but also about supporting a **robust and thriving framework**, FastAPI. 🙇
Some of these solutions may also be open source or offer free tiers, so you can try them without a financial commitment. Other commercial SDK generators are available and can be found online. 🤓
## Create a TypeScript SDK { #create-a-typescript-sdk }
* 👷 Remove not needed `allow-unsafe-pr-checkout: true`. PR [#15876](https://github.com/fastapi/fastapi/pull/15876) by [@YuriiMotov](https://github.com/YuriiMotov).
* ⬆ Bump the github-actions group with 5 updates. PR [#15872](https://github.com/fastapi/fastapi/pull/15872) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump the python-packages group across 1 directory with 10 updates. PR [#15870](https://github.com/fastapi/fastapi/pull/15870) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump CodSpeedHQ/action from 4.17.0 to 4.17.5 in the github-actions group. PR [#15826](https://github.com/fastapi/fastapi/pull/15826) by [@dependabot[bot]](https://github.com/apps/dependabot).
## 0.138.2 (2026-06-29)
### Refactors
* ♻️ Make `app.frontend()` return 404 for methods other than `GET` or `HEAD` with no static file matches. PR [#15863](https://github.com/fastapi/fastapi/pull/15863) by [@tiangolo](https://github.com/tiangolo).
### Internal
* 🔧 Update sponsors: remove Stainless. PR [#15862](https://github.com/fastapi/fastapi/pull/15862) by [@tiangolo](https://github.com/tiangolo).
* ♻️ Refactor how sponsors data is handled for banners. PR [#15852](https://github.com/fastapi/fastapi/pull/15852) by [@tiangolo](https://github.com/tiangolo).
## 0.138.1 (2026-06-25)
### Refactors
* ♻️ Refactor Library Skills, make info easier to find for agents. PR [#15841](https://github.com/fastapi/fastapi/pull/15841) by [@tiangolo](https://github.com/tiangolo).
**FastAPI** uses this fallback only for requests that look like browser navigation. Missing files like JavaScript, CSS, and images still return `404`.
**FastAPI** uses this fallback only for `GET` and `HEAD` requests that look like browser navigation. Missing files like JavaScript, CSS, and images still return `404`.
Requests with other methods, like `POST` or `PUT`, to paths that only match the frontend fallback also return `404`. Regular **FastAPI***path operations* still have higher priority than frontend routes.
<atitle="Auth, user management and more for your B2B product"style="display: block; position: relative;"href="https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=topbanner"target="_blank">
<atitle="Deploy & scale any full-stack web app on Render. Focus on building apps, not infra."style="display: block; position: relative;"href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi"target="_blank">
<atitle="Cut Code Review Time & Bugs in Half with CodeRabbit"style="display: block; position: relative;"href="https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=banner&utm_campaign=fastapi"target="_blank">
<atitle="Greptile: The AI Code Reviewer"style="display: block; position: relative;"href="https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page"target="_blank">
<atitle="Auth, user management and more for your B2B product"style="display: block; position: relative;"href="https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=topbanner"target="_blank">
<spanclass="sponsor-badge">sponsor</span>
<imgclass="sponsor-image"src="/img/sponsors/propelauth-banner.png"alt="Auth, user management and more for your B2B product"/>
</a>
</div>
<divclass="item">
<atitle="Deploy & scale any full-stack web app on Render. Focus on building apps, not infra."style="display: block; position: relative;"href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi"target="_blank">
<spanclass="sponsor-badge">sponsor</span>
<imgclass="sponsor-image"src="/img/sponsors/render-banner.svg"alt="Deploy & scale any full-stack web app on Render. Focus on building apps, not infra."/>
</a>
</div>
<divclass="item">
<atitle="Cut Code Review Time & Bugs in Half with CodeRabbit"style="display: block; position: relative;"href="https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=banner&utm_campaign=fastapi"target="_blank">
<spanclass="sponsor-badge">sponsor</span>
<imgclass="sponsor-image"src="/img/sponsors/coderabbit-banner.png"alt="Cut Code Review Time & Bugs in Half with CodeRabbit"/>
</a>
</div>
<divclass="item">
<atitle="Making Retail Purchases Actionable for Brands and Developers"style="display: block; position: relative;"href="https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source"target="_blank">
<spanclass="sponsor-badge">sponsor</span>
<imgclass="sponsor-image"src="/img/sponsors/subtotal-banner.svg"alt="Making Retail Purchases Actionable for Brands and Developers"/>
</a>
</div>
<divclass="item">
<atitle="Deploy enterprise applications at startup speed"style="display: block; position: relative;"href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi"target="_blank">
<spanclass="sponsor-badge">sponsor</span>
<imgclass="sponsor-image"src="/img/sponsors/railway-banner.png"alt="Deploy enterprise applications at startup speed"/>
</a>
</div>
<divclass="item">
<atitle="SerpApi: Web Search API"style="display: block; position: relative;"href="https://serpapi.com/?utm_source=fastapi_website"target="_blank">
<spanclass="sponsor-badge">sponsor</span>
<imgclass="sponsor-image"src="/img/sponsors/serpapi-banner.png"alt="SerpApi: Web Search API"/>
</a>
</div>
<divclass="item">
<atitle="Greptile: The AI Code Reviewer"style="display: block; position: relative;"href="https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page"target="_blank">
<spanclass="sponsor-badge">sponsor</span>
<imgclass="sponsor-image"src="/img/sponsors/greptile-banner.png"alt="Greptile: The AI Code Reviewer"/>
description: FastAPI best practices and conventions. Use when working with FastAPI APIs and Pydantic models for them. Keeps FastAPI code clean and up to date with the latest features and patterns, updated with new versions. Write new code or refactor and update old code.
description: FastAPI best practices and conventions. Use when working with FastAPI APIs, Pydantic models, dependencies, streaming responses including Server-Sent Events (SSE), and serving frontend apps. Keeps FastAPI code clean and up to date with the latest features and patterns.
---
# FastAPI
Official FastAPI skill to write code with best practices, keeping up to date with new versions and features.
## Quick Reference
* Serve frontend apps: use `app.frontend()` or `router.frontend()` for built frontend assets; see [Serve Frontend Apps](#serve-frontend-apps).
* Server-Sent Events (SSE): use `response_class=EventSourceResponse` and `yield`; see [Streaming](#streaming-json-lines-sse-bytes) and [the streaming reference](references/streaming.md).
* JSON Lines and byte streaming: see [the streaming reference](references/streaming.md).
* Dependencies: use `Annotated[..., Depends(...)]`; see [Dependency Injection](#dependency-injection) and [the dependency injection reference](references/dependencies.md) for `yield`, scopes, and class dependencies.
* Response models: prefer return types; use `response_model` when the public response schema differs from the internal return value; see [the response reference](references/responses.md).
* Pydantic models: do not use ellipsis or `RootModel`; see [the Pydantic reference](references/pydantic.md).
* Routing: declare router-level prefix, tags, and shared dependencies on the `APIRouter`; see [the path operation reference](references/path-operations.md).
* Tooling and related libraries: use uv, Ruff, ty, Asyncer, SQLModel, and HTTPX when applicable; see [the other tools reference](references/other-tools.md).
## Use the `fastapi` CLI
Run the development server on localhost with reload:
@ -15,39 +26,28 @@ Run the development server on localhost with reload:
fastapi dev
```
Run the production server:
```bash
fastapi run
```
### Add an entrypoint in `pyproject.toml`
FastAPI CLI will read the entrypoint in `pyproject.toml` to know where the FastAPI app is declared.
Prefer declaring the entrypoint in `pyproject.toml`:
```toml
[tool.fastapi]
entrypoint = "my_app.main:app"
```
### Use `fastapi` with a path
When adding the entrypoint to `pyproject.toml` is not possible, or the user explicitly asks not to, or it's running an independent small app, you can pass the app file path to the `fastapi` command:
When adding the entrypoint is not possible, or the user explicitly asks not to, pass the app file path:
```bash
fastapi dev my_app/main.py
```
Prefer to set the entrypoint in `pyproject.toml` when possible.
## Use `Annotated`
Always prefer the `Annotated` style for parameter and dependency declarations.
It keeps the function signatures working in other contexts, respects the types, allows reusability.
### In Parameter Declarations
Always prefer the `Annotated` style for parameter and dependency declarations. It keeps function signatures working in other contexts, respects the types, and allows reusability.
Use `Annotated` for parameter declarations, including `Path`, `Query`, `Header`, etc.:
@ -67,23 +67,7 @@ async def read_item(
return {"message": "Hello World"}
```
instead of:
```python
# DO NOT DO THIS
@app.get("/items/{item_id}")
async def read_item(
item_id: int = Path(ge=1, description="The item ID"),
See [the Pydantic reference](references/pydantic.md) for more details.
## Return Type or Response Model
@ -178,62 +136,9 @@ async def get_item() -> Item:
return Item(name="Plumbus", description="All-purpose home device")
```
**Important**: Return types or response models are what filter data ensuring no sensitive information is exposed. And they are used to serialize data with Pydantic (in Rust), this is the main idea that can increase response performance.
The return type doesn't have to be a Pydantic model, it could be a different type, like a list of integers, or a dict, etc.
### When to use `response_model` instead
If the return type is not the same as the type that you want to use to validate, filter, or serialize, use the `response_model` parameter on the decorator instead.
```python
from typing import Any
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
@app.get("/items/me", response_model=Item)
async def get_item() -> Any:
return {"name": "Foo", "description": "A very nice Item"}
```
This can be particularly useful when filtering data to expose only the public fields and avoid exposing sensitive information.
```python
from typing import Any
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class InternalItem(BaseModel):
name: str
description: str | None = None
secret_key: str
Return types or response models filter data to avoid exposing sensitive information, and they let Pydantic serialize the data on the Rust side for performance.
class Item(BaseModel):
name: str
description: str | None = None
@app.get("/items/me", response_model=Item)
async def get_item() -> Any:
item = InternalItem(
name="Foo", description="A very nice Item", secret_key="supersecret"
)
return item
```
Use `response_model` when the type you return is not the same as the public schema you want to validate, filter, document, and serialize. See [the response reference](references/responses.md).
## Performance
@ -243,36 +148,23 @@ Instead, declare a return type or response model. Pydantic will handle the data
## Including Routers
When declaring routers, prefer to add router level parameters like prefix, tags, etc. to the router itself, instead of in `include_router()`.
Do this:
When declaring routers, prefer to add router-level parameters like prefix, tags, and shared dependencies to the router itself instead of in `include_router()`.
There could be exceptions, but try to follow this convention.
Apply shared dependencies at the router level via `dependencies=[Depends(...)]`.
See [the path operation reference](references/path-operations.md) for more routing patterns.
## Serve Frontend Apps
@ -316,15 +205,15 @@ app.include_router(router)
## Dependency Injection
See [the dependency injection reference](references/dependencies.md) for detailed patterns including `yield` with `scope`, and class dependencies.
Use dependencies when the logic can't be declared in Pydantic validation, depends on external resources, needs cleanup (with `yield`), or is shared across endpoints.
Use dependencies when the logic can't be declared in Pydantic validation, depends on external resources, needs cleanup with `yield`, or is shared across endpoints.
Apply shared dependencies at the router level via `dependencies=[Depends(...)]`.
See [the dependency injection reference](references/dependencies.md) for detailed patterns including `yield` with `scope`, and class dependencies.
## Async vs Sync *path operations*
Use `async`*path operations* only when fully certain that the logic called inside is compatible with async and await (it's called with `await`) or that it doesn't block.
Use `async`*path operations* only when fully certain that the logic called inside is compatible with async and await, and that it doesn't block.
```python
from fastapi import FastAPI
@ -332,30 +221,44 @@ from fastapi import FastAPI
app = FastAPI()
# Use async def when calling async code
@app.get("/async-items/")
async def read_async_items():
data = await some_async_library.fetch_items()
return data
# Use plain def when calling blocking/sync code or when in doubt
@app.get("/items/")
def read_items():
data = some_blocking_library.fetch_items()
return data
```
In case of doubt, or by default, use regular `def` functions, those will be run in a threadpool so they don't block the event loop.
In case of doubt, or by default, use regular `def` functions. They will be run in a threadpool so they don't block the event loop. The same rules apply to dependencies.
The same rules apply to dependencies.
Make sure blocking code is not run inside of `async` functions. The logic will work, but will damage the performance heavily.
Make sure blocking code is not run inside of `async` functions. The logic will work, but will damage performance heavily.
When needing to mix blocking and async code, see Asyncer in [the other tools reference](references/other-tools.md).
## Streaming (JSON Lines, SSE, bytes)
To stream Server-Sent Events, use `response_class=EventSourceResponse` and `yield` items from the endpoint.
```python
from collections.abc import AsyncIterable
from fastapi import FastAPI
from fastapi.sse import EventSourceResponse, ServerSentEvent
Plain objects are automatically JSON-serialized as `data:` fields. Use `ServerSentEvent` for full control over SSE fields (`event`, `id`, `retry`, `comment`) and `raw_data` for pre-formatted strings.
See [the streaming reference](references/streaming.md) for JSON Lines, Server-Sent Events (`EventSourceResponse`, `ServerSentEvent`), and byte streaming (`StreamingResponse`) patterns.
## Tooling
@ -372,9 +275,7 @@ See [the other tools reference](references/other-tools.md) for details on other
## Do not use Pydantic RootModels
Do not use Pydantic `RootModel`, instead use regular type annotations with `Annotated` and Pydantic validation utilities.
For example, for a list with validations you could do:
Do not use Pydantic `RootModel`; instead use regular type annotations with `Annotated` and Pydantic validation utilities.
class ItemList(RootModel[Annotated[list[int], Field(min_length=1)]]):
pass
@app.post("/items/")
async def create_items(items: ItemList):
return items
```
FastAPI supports these type annotations and will create a Pydantic `TypeAdapter` for them, so that types can work as normally and there's no need for the custom logic and types in RootModels.
FastAPI supports these type annotations and will create a Pydantic `TypeAdapter` for them, so types work normally without custom wrapper models. See [the Pydantic reference](references/pydantic.md).
## Use one HTTP operation per function
Don't mix HTTP operations in a single function, having one function per HTTP operation helps separate concerns and organize the code.
Do this:
Don't mix HTTP operations in a single function. Having one function per HTTP operation helps separate concerns and organize the code.
When declaring routers, prefer to add router-level parameters like prefix, tags, and shared dependencies to the router itself instead of in `include_router()`.
When possible, include a return type. It will be used to validate, filter, document, and serialize the response.
```python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
@app.get("/items/me")
async def get_item() -> Item:
return Item(name="Plumbus", description="All-purpose home device")
```
Return types or response models filter data to avoid exposing sensitive information. They also let Pydantic serialize data on the Rust side for performance.
The return type doesn't have to be a Pydantic model. It can be a different type, like a list of integers, a dict, etc.
## When to use `response_model`
If the return type is not the same as the type that you want to use to validate, filter, or serialize, use the `response_model` parameter on the decorator.
```python
from typing import Any
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
@app.get("/items/me", response_model=Item)
async def get_item() -> Any:
return {"name": "Foo", "description": "A very nice Item"}
```
This is particularly useful when filtering data to expose only the public fields and avoid exposing sensitive information.
```python
from typing import Any
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class InternalItem(BaseModel):
name: str
description: str | None = None
secret_key: str
class Item(BaseModel):
name: str
description: str | None = None
@app.get("/items/me", response_model=Item)
async def get_item() -> Any:
item = InternalItem(
name="Foo", description="A very nice Item", secret_key="supersecret"