GitHub Copilot ChatGPT Claude Codex CLI Cursor opencode Skill Text

fastapi-router-py

Create FastAPI routers with CRUD operations, authentication dependencies, and proper response models. Use when building REST API endpoints, creating new routes, implementing CRUD operations, or adding authenticated endpoints in FastAPI applications.

Ciza · 0 points · 23 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download microsoft-skills-.github_plugins_azure-sdk-python_skills_fastapi-router-py-e58528d.zip · 2 KB
Part of microsoft/skills — 195 skills

Install

skills CLI npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-python/skills/fastapi-router-py
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git git clone https://github.com/microsoft/skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

FastAPI Router

Create FastAPI routers following established patterns with proper authentication, response models, and HTTP status codes.

Quick Start

Copy the template from assets/template.py and replace placeholders:

  • {{ResourceName}} → PascalCase name (e.g., Project)
  • {{resource_name}} → snake_case name (e.g., project)
  • {{resource_plural}} → plural form (e.g., projects)

Authentication Patterns

# Optional auth - returns None if not authenticated
current_user: Optional[User] = Depends(get_current_user)

# Required auth - raises 401 if not authenticated
current_user: User = Depends(get_current_user_required)

Response Models

@router.get("/items/{item_id}", response_model=Item)
async def get_item(item_id: str) -> Item:
    ...

@router.get("/items", response_model=list[Item])
async def list_items() -> list[Item]:
    ...

HTTP Status Codes

@router.post("/items", status_code=status.HTTP_201_CREATED)
async def create_item(item: ItemCreate) -> Item:
  ...

@router.delete("/items/{id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_item(id: str) -> None:
  ...

Integration Steps

  1. Create router in src/backend/app/routers/
  2. Mount in src/backend/app/main.py
  3. Create corresponding Pydantic models
  4. Create service layer if needed
  5. Add frontend API functions

Best Practices

  1. Pick def or async def per endpoint based on whether you call async I/O; do not call blocking I/O from an async def handler.
  2. Manage long-lived resources (DB pools, HTTP clients) in lifespan and inject via Depends; use with/async with for per-request resources.

Reference Files

File Contents
references/capabilities.md Additional non-hero capabilities, operation-group coverage, and production checklists.
Files (skills)
  • assets
    • template.py 4.6 KB
      """
      {{ResourceName}} Router
      
      Handles CRUD operations for {{resource_name}} resources.
      
      Template placeholders to replace:
      - {{ResourceName}} (PascalCase)
      - {{resource_name}} (snake_case)
      - {{resource_plural}} (plural snake_case)
      """
      
      from typing import Optional
      from fastapi import APIRouter, Depends, HTTPException, Query, status
      
      from app.auth.jwt import get_current_user, get_current_user_required
      from app.models.user import User
      from app.models.{{resource_name}} import (
          {{ResourceName}},
          {{ResourceName}}Create,
          {{ResourceName}}Update,
      )
      from app.services.{{resource_name}}_service import {{ResourceName}}Service
      
      router = APIRouter(prefix="/api", tags=["{{resource_plural}}"])
      
      
      # ============================================================================
      # Dependencies
      # ============================================================================
      
      
      def get_service() -> {{ResourceName}}Service:
          """Dependency to get service instance."""
          return {{ResourceName}}Service()
      
      
      # ============================================================================
      # Endpoints
      # ============================================================================
      
      
      @router.get("/{{resource_plural}}", response_model=list[{{ResourceName}}])
      async def list_{{resource_plural}}(
          limit: int = Query(default=50, ge=1, le=100),
          offset: int = Query(default=0, ge=0),
          current_user: Optional[User] = Depends(get_current_user),
          service: {{ResourceName}}Service = Depends(get_service),
      ) -> list[{{ResourceName}}]:
          """
          List all {{resource_plural}}.
      
          - **limit**: Maximum number of items to return (1-100)
          - **offset**: Number of items to skip
          """
          return await service.list_{{resource_plural}}(limit=limit, offset=offset)
      
      
      @router.get("/{{resource_plural}}/{{{resource_name}}_id}", response_model={{ResourceName}})
      async def get_{{resource_name}}(
          {{resource_name}}_id: str,
          current_user: Optional[User] = Depends(get_current_user),
          service: {{ResourceName}}Service = Depends(get_service),
      ) -> {{ResourceName}}:
          """
          Get a specific {{resource_name}} by ID.
      
          Raises 404 if not found.
          """
          result = await service.get_{{resource_name}}_by_id({{resource_name}}_id)
          if result is None:
              raise HTTPException(
                  status_code=status.HTTP_404_NOT_FOUND,
                  detail="{{ResourceName}} not found",
              )
          return result
      
      
      @router.post(
          "/{{resource_plural}}",
          response_model={{ResourceName}},
          status_code=status.HTTP_201_CREATED,
      )
      async def create_{{resource_name}}(
          data: {{ResourceName}}Create,
          current_user: User = Depends(get_current_user_required),
          service: {{ResourceName}}Service = Depends(get_service),
      ) -> {{ResourceName}}:
          """
          Create a new {{resource_name}}.
      
          Requires authentication.
          """
          return await service.create_{{resource_name}}(data, current_user.id)
      
      
      @router.patch("/{{resource_plural}}/{{{resource_name}}_id}", response_model={{ResourceName}})
      async def update_{{resource_name}}(
          {{resource_name}}_id: str,
          data: {{ResourceName}}Update,
          current_user: User = Depends(get_current_user_required),
          service: {{ResourceName}}Service = Depends(get_service),
      ) -> {{ResourceName}}:
          """
          Update an existing {{resource_name}}.
      
          Requires authentication and ownership.
          """
          # Verify ownership
          existing = await service.get_{{resource_name}}_by_id({{resource_name}}_id)
          if existing is None:
              raise HTTPException(
                  status_code=status.HTTP_404_NOT_FOUND,
                  detail="{{ResourceName}} not found",
              )
      
          # Optional: Check ownership
          # if existing.author_id != current_user.id:
          #     raise HTTPException(
          #         status_code=status.HTTP_403_FORBIDDEN,
          #         detail="Not authorized to update this {{resource_name}}",
          #     )
      
          return await service.update_{{resource_name}}({{resource_name}}_id, data)
      
      
      @router.delete(
          "/{{resource_plural}}/{{{resource_name}}_id}",
          status_code=status.HTTP_204_NO_CONTENT,
      )
      async def delete_{{resource_name}}(
          {{resource_name}}_id: str,
          current_user: User = Depends(get_current_user_required),
          service: {{ResourceName}}Service = Depends(get_service),
      ) -> None:
          """
          Delete a {{resource_name}}.
      
          Requires authentication and ownership.
          """
          existing = await service.get_{{resource_name}}_by_id({{resource_name}}_id)
          if existing is None:
              raise HTTPException(
                  status_code=status.HTTP_404_NOT_FOUND,
                  detail="{{ResourceName}} not found",
              )
      
          await service.delete_{{resource_name}}({{resource_name}}_id)
      
  • references
    • capabilities.md 934 B
      # fastapi-router-py capability coverage
      
      **SDK/package**: `fastapi`
      
      This reference captures additional non-hero capabilities and API breadth so the main `SKILL.md` can stay focused on copy/paste hero flows.
      
      ## Hero scenarios covered in SKILL.md
      
      - `Quick Start`
      - `Authentication Patterns`
      - `Response Models`
      - `HTTP Status Codes`
      
      ## Important non-hero scenarios to include when needed
      
      - `Integration Steps`
      - `Best Practices`
      
      ## API breadth checklist
      
      - Verify dependency lifetimes (`Depends` with `yield`) for resources like DB connections and HTTP clients.
      - Confirm request/response validation uses Pydantic models with appropriate field constraints.
      - Include proper error responses with `HTTPException` and correct status codes.
      - Avoid blocking I/O in `async def` endpoints; use `run_in_executor` or a thread-pool for sync calls.
      - Validate middleware, background tasks, and lifespan event patterns for production paths.
      
  • SKILL.md 2.2 KB
    ---
    name: fastapi-router-py
    description: Create FastAPI routers with CRUD operations, authentication dependencies, and proper response models. Use when building REST API endpoints, creating new routes, implementing CRUD operations, or adding authenticated endpoints in FastAPI applications.
    license: MIT
    metadata:
      author: Microsoft
      version: "1.0.0"
    ---
    
    # FastAPI Router
    
    Create FastAPI routers following established patterns with proper authentication, response models, and HTTP status codes.
    
    ## Quick Start
    
    Copy the template from [assets/template.py](assets/template.py) and replace placeholders:
    - `{{ResourceName}}` → PascalCase name (e.g., `Project`)
    - `{{resource_name}}` → snake_case name (e.g., `project`)
    - `{{resource_plural}}` → plural form (e.g., `projects`)
    
    ## Authentication Patterns
    
    ```python
    # Optional auth - returns None if not authenticated
    current_user: Optional[User] = Depends(get_current_user)
    
    # Required auth - raises 401 if not authenticated
    current_user: User = Depends(get_current_user_required)
    ```
    
    ## Response Models
    
    ```python
    @router.get("/items/{item_id}", response_model=Item)
    async def get_item(item_id: str) -> Item:
        ...
    
    @router.get("/items", response_model=list[Item])
    async def list_items() -> list[Item]:
        ...
    ```
    
    ## HTTP Status Codes
    
    ```python
    @router.post("/items", status_code=status.HTTP_201_CREATED)
    async def create_item(item: ItemCreate) -> Item:
      ...
    
    @router.delete("/items/{id}", status_code=status.HTTP_204_NO_CONTENT)
    async def delete_item(id: str) -> None:
      ...
    ```
    
    ## Integration Steps
    
    1. Create router in `src/backend/app/routers/`
    2. Mount in `src/backend/app/main.py`
    3. Create corresponding Pydantic models
    4. Create service layer if needed
    5. Add frontend API functions
    
    ## Best Practices
    
    1. **Pick `def` or `async def` per endpoint based on whether you call async I/O; do not call blocking I/O from an `async def` handler.**
    2. **Manage long-lived resources (DB pools, HTTP clients) in `lifespan` and inject via `Depends`;** use `with`/`async with` for per-request resources.
    
    ## Reference Files
    
    | File | Contents |
    |------|----------|
    | [references/capabilities.md](references/capabilities.md) | Additional non-hero capabilities, operation-group coverage, and production checklists. |
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related