Fastapi Endpoint Complete
Comprehensive skill designed for plan, build, production, ready. Includes structured workflows, validation checks, and reusable patterns for web development.
FastAPI Endpoint Complete
A comprehensive API development skill for building production-ready FastAPI endpoints with validation, authentication, database integration, and OpenAPI documentation.
When to Use
Choose FastAPI Endpoint Complete when:
- Building REST API endpoints with automatic request/response validation
- Creating APIs that need auto-generated OpenAPI/Swagger documentation
- Developing async Python backends with high performance requirements
- Implementing CRUD operations with SQLAlchemy or other ORMs
Consider alternatives when:
- Building a Django application — use Django REST Framework
- Creating a simple script API — use Flask for minimal setup
- Working with GraphQL — use Strawberry or Ariadne
Quick Start
# Install FastAPI with all dependencies pip install "fastapi[standard]" sqlalchemy alembic python-jose passlib[bcrypt] # Run the development server uvicorn main:app --reload --port 8000
from fastapi import FastAPI, HTTPException, Depends, Query, Path, status from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel, Field, EmailStr from typing import Optional from datetime import datetime app = FastAPI( title="My API", version="1.0.0", description="Production-ready API with FastAPI" ) app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Pydantic models for validation class UserCreate(BaseModel): email: EmailStr name: str = Field(min_length=2, max_length=100) password: str = Field(min_length=8) class UserResponse(BaseModel): id: int email: str name: str created_at: datetime class Config: from_attributes = True class UserUpdate(BaseModel): name: Optional[str] = Field(None, min_length=2, max_length=100) email: Optional[EmailStr] = None # CRUD endpoints @app.post("/users", response_model=UserResponse, status_code=status.HTTP_201_CREATED) async def create_user(user: UserCreate, db=Depends(get_db)): existing = await db.execute( select(User).where(User.email == user.email) ) if existing.scalar_one_or_none(): raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Email already registered" ) db_user = User(**user.model_dump()) db.add(db_user) await db.commit() await db.refresh(db_user) return db_user @app.get("/users", response_model=list[UserResponse]) async def list_users( skip: int = Query(0, ge=0), limit: int = Query(20, ge=1, le=100), search: Optional[str] = Query(None, min_length=1), db=Depends(get_db) ): query = select(User) if search: query = query.where(User.name.ilike(f"%{search}%")) query = query.offset(skip).limit(limit) result = await db.execute(query) return result.scalars().all() @app.get("/users/{user_id}", response_model=UserResponse) async def get_user( user_id: int = Path(gt=0), db=Depends(get_db) ): user = await db.get(User, user_id) if not user: raise HTTPException(status_code=404, detail="User not found") return user @app.patch("/users/{user_id}", response_model=UserResponse) async def update_user( user_id: int, updates: UserUpdate, db=Depends(get_db) ): user = await db.get(User, user_id) if not user: raise HTTPException(status_code=404, detail="User not found") update_data = updates.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(user, field, value) await db.commit() await db.refresh(user) return user @app.delete("/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_user(user_id: int, db=Depends(get_db)): user = await db.get(User, user_id) if not user: raise HTTPException(status_code=404, detail="User not found") await db.delete(user) await db.commit()
Core Concepts
FastAPI Architecture Patterns
| Pattern | Use Case | Components |
|---|---|---|
| Router-based | Feature separation | APIRouter per resource |
| Dependency Injection | Shared logic (auth, db) | Depends() |
| Middleware | Cross-cutting concerns | CORS, logging, timing |
| Background Tasks | Async work after response | BackgroundTasks |
| Events | Startup/shutdown logic | lifespan context manager |
| Exception Handlers | Custom error responses | @app.exception_handler |
Authentication with JWT
from fastapi import Depends, HTTPException, status from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from jose import JWTError, jwt from datetime import datetime, timedelta security = HTTPBearer() SECRET_KEY = "your-secret-key" ALGORITHM = "HS256" def create_access_token(data: dict, expires_delta: timedelta = timedelta(hours=1)): to_encode = data.copy() expire = datetime.utcnow() + expires_delta to_encode.update({"exp": expire}) return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) async def get_current_user( credentials: HTTPAuthorizationCredentials = Depends(security), db=Depends(get_db) ): try: payload = jwt.decode(credentials.credentials, SECRET_KEY, algorithms=[ALGORITHM]) user_id = payload.get("sub") if not user_id: raise HTTPException(status_code=401, detail="Invalid token") except JWTError: raise HTTPException(status_code=401, detail="Invalid token") user = await db.get(User, int(user_id)) if not user: raise HTTPException(status_code=401, detail="User not found") return user # Protected endpoint @app.get("/me", response_model=UserResponse) async def get_current_user_profile(user=Depends(get_current_user)): return user
Configuration
| Option | Description | Default |
|---|---|---|
host | Server bind address | "0.0.0.0" |
port | Server port | 8000 |
reload | Auto-reload on code changes | true (dev) |
workers | Number of Uvicorn workers | 1 |
cors_origins | Allowed CORS origins | ["*"] (dev) |
docs_url | Swagger UI path | "/docs" |
redoc_url | ReDoc documentation path | "/redoc" |
log_level | Logging level | "info" |
Best Practices
- Use Pydantic models for all request and response schemas to get automatic validation, serialization, and OpenAPI documentation — never manually parse request bodies or validate fields in endpoint logic
- Organize endpoints into routers by resource (
users_router,orders_router) and include them in the main app with prefixes to keep the codebase maintainable as the API grows - Use dependency injection for cross-cutting concerns like database sessions, authentication, and rate limiting so endpoint functions stay focused on business logic
- Return appropriate HTTP status codes — 201 for creation, 204 for deletion, 409 for conflicts, 422 for validation errors — clients depend on status codes for error handling
- Add pagination to all list endpoints from the start with
skipandlimitparameters and sensible defaults; retrofitting pagination into endpoints that return unbounded results causes breaking changes
Common Issues
Circular import errors with routers: Splitting FastAPI apps into multiple files often creates circular imports when models and dependencies reference each other. Use a separate deps.py file for shared dependencies, and import types using TYPE_CHECKING guards to break circular references.
Async database sessions leaking: Forgetting to close database sessions in error paths causes connection pool exhaustion. Use FastAPI's dependency injection with yield to ensure sessions are always closed: async def get_db(): async with session() as s: yield s.
OpenAPI schema conflicts with optional fields: Using Optional[str] in Pydantic models generates different OpenAPI schemas than str | None, and inconsistent usage confuses API clients. Standardize on one approach across all models and verify the generated OpenAPI spec matches your documentation expectations.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.