Skip to main content

fastapi-routes

Create or modify FastAPI routes in the Oscilla codebase. Use when: adding new API endpoints, creating Pydantic request/response models, registering routers, designing REST APIs, or following route conventions for this project.

Source facts

Repository
tedivm/oscilla
Last source activity
April 19, 2026 at 17:28
Detected SKILL.md language
English
Stars
1
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
fastapi-routes
description
Create or modify FastAPI routes in the Oscilla codebase. Use when: adding new API endpoints, creating Pydantic request/response models, registering routers, designing REST APIs, or following route conventions for this project.
# FastAPI Routes > **context7**: If the `mcp_context7` tool is available, resolve and load the full `fastapi` documentation before proceeding: > ``` > mcp_context7_resolve-library-id: "fastapi" > mcp_context7_get-library-docs: <resolved-id> > ``` Guidelines and patterns for writing FastAPI routes in the Oscilla 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) content: str | None = None ``` --- ## Router Pattern Use `APIRouter` for all routes. Register the router in `oscilla/www.py` under the `/api` prefix. ```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 All application routes must be registered under the `/api` prefix in `oscilla/www.py`. **Exceptions** (no `/api` prefix by convention): - `/health` — liveness probe - `/ready` — readiness probe - `/static` — static file serving ```python # oscilla/www.py app.include_router(posts_router, prefix="/api") ``` --- ## OpenAPI Docs The OpenAPI documentation is served at these fixed paths — do not move them: | URL | Interface | | ----------------- | ------------ | | `/api/docs` | Swagger UI | | `/api/redoc` | ReDoc | | `/api/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 ``` --- ## 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 under `/api` in `oscilla/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 (`/api/docs`), ReDoc (`/api/redoc`), OpenAPI schema, middleware, authentication integration, and dependency injection patterns. - [docs/dev/authentication.md](../../docs/dev/authentication.md) — Authentication and authorization patterns used in this project. - [docs/dev/dependencies.md](../../docs/dev/dependencies.md) — FastAPI dependency injection conventions. - [FastAPI Docs](https://fastapi.tiangolo.com/)
View on GitHub