# Tedivm Robs Awesome Python Template Fastapi Routes

> FastAPI Routes

- Skill: `tomevault-io/tedivm-robs-awesome-python-template-fastapi-routes` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/tedivm-robs-awesome-python-template-fastapi-routes`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/tedivm-robs-awesome-python-template-fastapi-routes/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/tedivm-robs-awesome-python-template-fastapi-routes

---


# FastAPI Routes

> **context7**: If the `context7_query-docs` tool is available, resolve and load the full `fastapi` documentation before proceeding:
> ```
> context7_resolve-library-id: "fastapi"
> context7_query-docs: /fastapi/fastapi "<your query>"
> ```

Guidelines and patterns for writing FastAPI routes in this codebase.

---

## REST Principles

APIs must adhere as closely as possible to REST principles, including appropriate use of HTTP verbs:

| Verb     | Usage                            |
| -------- | -------------------------------- |
| `GET`    | Read one or many resources       |
| `POST`   | Create a new resource            |
| `PUT`    | Replace / fully update a resource |
| `PATCH`  | Partial update (use sparingly)   |
| `DELETE` | Remove a resource                |

---

## Pydantic Models

- **Always** use Pydantic models for both input and output — never use plain `dict` or `Any`.
- **Never** reuse the same model for input and output. Use separate models:
  - `PostCreate` — user input for creating a resource
  - `PostUpdate` — user input for updating (optional fields)
  - `PostRead` — response shape returned to the client
- Parameters in **input** models must use `Field()` with validation constraints and a `description`.
- Output models do not require `Field()` unless you need aliases or serialization control.

```python
from uuid import UUID
from pydantic import BaseModel, Field


class PostCreate(BaseModel):
    title: str = Field(min_length=1, max_length=200, description="Post title")
    content: str = Field(min_length=1, description="Post content")


class PostRead(BaseModel):
    id: UUID
    title: str
    content: str
    created_at: str


class PostUpdate(BaseModel):
    title: str | None = Field(default=None, max_length=200, description="Post title")
    content: str | None = Field(default=None, description="Post content")
```

---

## Router Pattern

Use `APIRouter` for all routes. Register the router in `{{cookiecutter.__package_slug}}/www.py`.

```python
from uuid import UUID

from fastapi import APIRouter, status

router = APIRouter()


@router.post("/posts", response_model=PostRead, status_code=status.HTTP_201_CREATED)
async def create_post(post: PostCreate) -> PostRead:
    ...


@router.get("/posts/{post_id}", response_model=PostRead)
async def get_post(post_id: UUID) -> PostRead:
    ...


@router.put("/posts/{post_id}", response_model=PostRead)
async def update_post(post_id: UUID, post: PostUpdate) -> PostRead:
    ...


@router.delete("/posts/{post_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_post(post_id: UUID) -> None:
    ...
```

---

## Route Registration

Register routers in `{{cookiecutter.__package_slug}}/www.py` using `app.include_router()`.

**Exceptions** (no prefix by convention):
- `/health` — liveness probe
- `/` — root redirect to docs
- `/static` — static file serving

---

## OpenAPI Docs

The OpenAPI documentation is served at these fixed paths — do not move them:

| URL               | Interface    |
| ----------------- | ------------ |
| `/docs`           | Swagger UI   |
| `/redoc`          | ReDoc        |
| `/openapi.json`   | Raw schema   |

---

## Error Handling

Use `HTTPException` with appropriate status codes:

```python
from fastapi import HTTPException, status

@router.get("/posts/{post_id}", response_model=PostRead)
async def get_post(post_id: UUID) -> PostRead:
    post = await get_post_from_db(post_id)
    if post is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Post not found")
    return post
```

---

## Dependency Injection

Use `Depends()` to inject shared logic (database sessions, authentication, etc.) into routes.

```python
from fastapi import Depends

from {{cookiecutter.__package_slug}} import get_db


@router.get("/posts/{post_id}", response_model=PostRead)
async def get_post(post_id: UUID, db = Depends(get_db)) -> PostRead:
    ...
```

---

## Lifespan

Use the `lifespan` parameter on the `FastAPI` app instance for startup and shutdown logic. Do not use the deprecated `@app.on_event("startup")` / `@app.on_event("shutdown")` decorators.

```python
from contextlib import asynccontextmanager

from fastapi import FastAPI


@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup logic
    await initialize_database()
    yield
    # Shutdown logic
    await close_database()


app = FastAPI(lifespan=lifespan)
```

---

## Style Checklist

Before submitting a new route, verify:

- [ ] HTTP verb matches the operation semantics
- [ ] Separate `Create`, `Update`, and `Read` models defined
- [ ] All input model fields use `Field()` with description
- [ ] Route is `async`
- [ ] Router is registered in `{{cookiecutter.__package_slug}}/www.py`
- [ ] 201 status used for `POST` create endpoints
- [ ] 204 status used for `DELETE` endpoints (no response body)
- [ ] Path parameters use typed UUIDs where appropriate

---

## Further Reading

- [docs/dev/api.md](../../docs/dev/api.md) — Full FastAPI developer guide covering the application structure, startup events, Swagger UI, ReDoc, OpenAPI schema, middleware, and dependency injection patterns.
- [FastAPI Docs](https://fastapi.tiangolo.com/)

---
> Source: [tedivm/robs_awesome_python_template](https://github.com/tedivm/robs_awesome_python_template) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-05-22 -->

