Skip to content
Back to skills

Backend API Generation Skill

ASecurity

Comprehensive skill for generating production-grade backend APIs using Python (FastAPI) and Java (Spring Boot). Wraps python_advanced_skill and java_advanced_skill to provide unified API development standards.

  • 3 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 5, 2026
testingpythonrustgojavasqlfastapispringtestinggitapi

Works with

  • api

Security analysis

A100/100

Pro scans all 21 files and shows the line behind each finding

Scanned October 1, 2026

npx -y skills add sharmapuneet1510/awesome-prompts --skill skills --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Backend API Generation Skill?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Backend API Generation Skill
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/sharmapuneet1510-backend-api-generation-skill-awesome-prompts/badge)](https://www.skillsdirectory.com/skills/sharmapuneet1510-backend-api-generation-skill-awesome-prompts)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "Backend API Generation Skill"
version: 1.1
description: "Comprehensive skill for generating production-grade backend APIs using Python (FastAPI) and Java (Spring Boot). Wraps python_advanced_skill and java_advanced_skill to provide unified API development standards."
tags: ["backend", "api", "fastapi", "spring-boot", "rest", "validation", "jwt", "authentication"]
author: "Developer Team"
created: "2025-05-20"
applies_to: [python, java, fastapi, spring-boot, rest-api]
---

# Backend API Generation Skill — v1.1

## Quick Card

> Read this card first. Load a section below only when the task needs it.

| | |
|---|---|
| **Use when** | Generating REST endpoints in FastAPI or Spring Boot (`implementer:build`, `architect:api`) |
| **Skip when** | Language idioms alone — load `python_advanced_skill` / `java_advanced_skill` |
| **Inputs** | Endpoint list, auth type, data models, error scenarios, performance targets |
| **Produces** | Routers/controllers, request/response models, service + repository layers, DDL, tests |
| **Steps** | 1. Analyse requirements → 2. Define request/response models → 3. Implement service logic → 4. Wire routes with status codes → 5. Add auth + validation → 6. Test |
| **Done when** | §Validation Checklist passes; every endpoint documents its error responses |
| **Senior defaults** | Sync DB session → plain `def` handler (or go fully async with `AsyncSession`) · PyJWT + pwdlib (Argon2id), not python-jose/passlib · verify a dummy hash for unknown users so timing cannot enumerate accounts · Pydantic v2 `model_config`, never `class Config` · validate at the boundary, trust inside |
| **Load on demand** | §Input · §Output · §Process · §Code Example · §Validation Checklist |
| **Run report** | `html_report_skill` — adds: Endpoint table (method · path · auth · status codes) |
| **Pairs with** | `python_advanced_skill`, `java_advanced_skill`, `database_skill`, `test_skill`, `security_audit_skill` |

---

## Purpose

This skill provides a comprehensive framework for generating production-grade backend APIs across Python (FastAPI) and Java (Spring Boot) ecosystems. It combines the advanced coding standards from `python_advanced_skill` and `java_advanced_skill` with API-specific patterns for route design, input validation, authentication, error handling, and testing.

The skill ensures consistent API contracts, security best practices, and maintainability across different backend platforms.

## Input

### Task Specification
- **API endpoint requirements**: List of endpoints with HTTP methods (GET, POST, PUT, DELETE, PATCH)
- **Authentication type**: JWT, OAuth2, API key, or none
- **Data models**: Entity definitions with relationships and validation rules
- **Business logic**: Core algorithms and business rules to implement
- **Error scenarios**: Expected failure cases and error codes
- **Performance requirements**: Throughput, latency, and concurrency targets

### Context
- **Platform choice**: Python (FastAPI) or Java (Spring Boot)
- **Database**: PostgreSQL, MySQL, MongoDB, or in-memory
- **Existing services**: References to other microservices or external APIs
- **Compliance requirements**: GDPR, PCI-DSS, SOC2, or industry-specific
- **Team expertise**: Current team skill levels and tech preferences

### Tech Stack
- **Python Stack**: FastAPI 0.104+, Pydantic 2.x, SQLAlchemy 2.x, PyJWT for tokens, pwdlib (Argon2) for password hashing — not `python-jose` or `passlib`, both unmaintained
- **Java Stack**: Spring Boot 3.x, Spring Security, Spring Data JPA, jsonwebtoken
- **Shared**: RESTful design patterns, OpenAPI/Swagger documentation, comprehensive testing

## Output

### API Routes
- Fully implemented endpoint handlers with proper HTTP methods and status codes
- Route grouping using routers/controllers for maintainability
- Input/output serialization with Pydantic models (Python) or DTOs (Java)
- Query parameter validation and path parameter extraction

### Data Models
- Domain entities with all relationships defined
- Validation constraints (required fields, length limits, regex patterns)
- Serialization models for API responses
- Change audit fields (created_at, updated_at, created_by, updated_by)

### Service Layer
- Business logic isolated in service classes
- Transaction management and ACID compliance
- Caching strategies for frequently accessed data
- Error handling with custom exceptions

### Database Schemas
- SQL DDL statements for table creation
- Indexes for performance optimization
- Foreign key constraints and relationships
- Migration scripts for schema evolution

### Comprehensive Tests
- Unit tests for business logic with 80%+ code coverage
- Integration tests for API endpoints
- Authentication/authorization tests
- Error scenario validation
- Performance/load tests for critical paths

## Process

### Step 1: Analyze Requirements
- Understand the problem domain and business rules
- Identify all API endpoints and their operations
- Map data models and relationships
- Determine authentication and authorization needs
- List error scenarios and their handling strategies

### Step 2: Design API Contract
- Define endpoint paths following REST conventions (`/api/v1/resource`)
- Specify HTTP methods (GET for reads, POST for creates, PUT/PATCH for updates, DELETE for deletions)
- Design request/response body schemas
- Plan error response format
- Document with OpenAPI/Swagger specs

### Step 3: Implement Data Models
- Create Pydantic models (Python) or JPA entities (Java) with validation
- Include audit fields (created_at, updated_at, created_by)
- Define relationships (one-to-many, many-to-many)
- Add constraints and indexes for performance

### Step 4: Implement Authentication/Authorization
- Set up JWT token generation and validation
- Implement password hashing (Argon2id via pwdlib, or bcrypt)
- Create middleware/filters for route protection
- Design role-based access control (RBAC) if needed

### Step 5: Implement Routes with Input Validation
- Create route handlers/controller methods
- Add Pydantic field validation (Python) or Bean Validation (Java)
- Implement proper error handling with meaningful messages
- Return correct HTTP status codes (200, 201, 204, 400, 401, 403, 404, 409, 500)

### Step 6: Implement Service Layer
- Extract business logic into service classes
- Ensure separation of concerns between routes and business logic
- Handle transactions properly
- Implement proper exception handling

### Step 7: Write Comprehensive Tests
- Unit tests for service layer
- Integration tests for full API flow
- Mock external dependencies
- Test all error scenarios
- Aim for 80%+ code coverage

### Step 8: Document API
- Generate OpenAPI/Swagger documentation
- Document authentication method
- Provide example requests and responses
- Include error code reference

## Code Example: FastAPI Authentication Endpoints

```python
# routes/auth.py
from datetime import datetime, timedelta, timezone
from typing import Optional

from fastapi import APIRouter, HTTPException, status, Depends
import jwt  # PyJWT
from pwdlib import PasswordHash
from pydantic import BaseModel, ConfigDict, EmailStr, Field
from sqlalchemy.orm import Session

from db.database import get_db
from models.user import User
from config import settings

router = APIRouter(prefix="/api/v1/auth", tags=["authentication"])

# Argon2id with pwdlib's recommended parameters
password_hasher = PasswordHash.recommended()

# Verified against when the email is unknown, so a missing user costs the same
# time as a wrong password and response timing cannot enumerate accounts.
DUMMY_HASH = password_hasher.hash("dummy-password-for-timing")

# ============================================================================
# Request/Response Models with Input Validation
# ============================================================================

class RegisterRequest(BaseModel):
    """User registration request with comprehensive validation."""
    
    email: EmailStr = Field(..., description="User email address")
    password: str = Field(
        ...,
        min_length=8,
        max_length=128,
        description="Password (8-128 characters, must contain uppercase, lowercase, digit, special char)"
    )
    first_name: str = Field(..., min_length=1, max_length=100)
    last_name: str = Field(..., min_length=1, max_length=100)
    
    model_config = ConfigDict(json_schema_extra={
        "example": {
            "email": "user@example.com",
            "password": "SecurePass123!",
            "first_name": "John",
            "last_name": "Doe"
        }
    })


class LoginRequest(BaseModel):
    """User login request."""
    
    email: EmailStr = Field(..., description="User email address")
    password: str = Field(..., description="User password")
    
    model_config = ConfigDict(json_schema_extra={
        "example": {
            "email": "user@example.com",
            "password": "SecurePass123!"
        }
    })


class TokenResponse(BaseModel):
    """JWT token response."""
    
    access_token: str = Field(..., description="JWT access token")
    token_type: str = Field(default="bearer", description="Token type")
    expires_in: int = Field(..., description="Token expiration time in seconds")
    
    model_config = ConfigDict(json_schema_extra={
        "example": {
            "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
            "token_type": "bearer",
            "expires_in": 3600
        }
    })


class UserResponse(BaseModel):
    """User response model (safe - no password)."""
    
    id: int
    email: str
    first_name: str
    last_name: str
    created_at: datetime
    
    model_config = ConfigDict(from_attributes=True, json_schema_extra={
        "example": {
            "id": 1,
            "email": "user@example.com",
            "first_name": "John",
            "last_name": "Doe",
            "created_at": "2025-05-20T10:30:00Z"
        }
    })


# ============================================================================
# Helper Functions
# ============================================================================

def hash_password(password: str) -> str:
    """Hash password with Argon2id."""
    return password_hasher.hash(password)


def verify_password(plain_password: str, hashed_password: str) -> bool:
    """Verify password against hash."""
    return password_hasher.verify(plain_password, hashed_password)


def create_access_token(
    data: dict,
    expires_delta: Optional[timedelta] = None
) -> tuple[str, int]:
    """
    Create JWT access token.
    
    Args:
        data: Claims to include in token
        expires_delta: Token expiration time (default: 1 hour)
    
    Returns:
        Tuple of (token, expires_in_seconds)
    
    Raises:
        ValueError: If secret key is not configured
    """
    if not settings.SECRET_KEY:
        raise ValueError("SECRET_KEY not configured")
    
    to_encode = data.copy()
    
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(hours=1)
    
    to_encode.update({"exp": expire})
    
    encoded_jwt = jwt.encode(
        to_encode,
        settings.SECRET_KEY,
        algorithm=settings.ALGORITHM
    )
    
    expires_in = int(expires_delta.total_seconds()) if expires_delta else 3600
    
    return encoded_jwt, expires_in


def get_user_by_email(db: Session, email: str) -> Optional[User]:
    """Get user from database by email."""
    return db.query(User).filter(User.email == email).first()


# ============================================================================
# Endpoints
# ============================================================================

@router.post(
    "/register",
    response_model=UserResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Register a new user",
    responses={
        201: {"description": "User registered successfully"},
        400: {"description": "Invalid input data"},
        409: {"description": "Email already registered"},
        500: {"description": "Internal server error"}
    }
)
def register(
    request: RegisterRequest,
    db: Session = Depends(get_db)
) -> UserResponse:
    """
    Register a new user account.
    
    - **email**: Must be a valid email address and unique
    - **password**: Must be 8+ characters with uppercase, lowercase, digit, and special character
    - **first_name**: Required, 1-100 characters
    - **last_name**: Required, 1-100 characters
    
    Returns: Created user object (without password)
    
    Raises:
        HTTPException 409: Email already registered
        HTTPException 400: Invalid input validation failed
        HTTPException 500: Database error
    """
    # Check if user already exists
    existing_user = get_user_by_email(db, request.email)
    if existing_user:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=f"Email '{request.email}' is already registered",
            headers={"X-Error-Code": "EMAIL_EXISTS"}
        )
    
    # Validate password strength
    if not _is_strong_password(request.password):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Password must contain uppercase, lowercase, digit, and special character",
            headers={"X-Error-Code": "WEAK_PASSWORD"}
        )
    
    # Create new user
    hashed_password = hash_password(request.password)
    new_user = User(
        email=request.email,
        password_hash=hashed_password,
        first_name=request.first_name,
        last_name=request.last_name,
        created_at=datetime.now(timezone.utc)
    )
    
    try:
        db.add(new_user)
        db.commit()
        db.refresh(new_user)
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to create user account",
            headers={"X-Error-Code": "DB_ERROR"}
        ) from e
    
    return UserResponse.model_validate(new_user)


@router.post(
    "/login",
    response_model=TokenResponse,
    status_code=status.HTTP_200_OK,
    summary="User login",
    responses={
        200: {"description": "Login successful, token returned"},
        401: {"description": "Invalid credentials"},
        400: {"description": "Invalid input"},
        500: {"description": "Internal server error"}
    }
)
def login(
    request: LoginRequest,
    db: Session = Depends(get_db)
) -> TokenResponse:
    """
    Authenticate user and return JWT access token.
    
    - **email**: User email address
    - **password**: User password
    
    Returns: JWT access token valid for 1 hour
    
    Raises:
        HTTPException 401: Invalid email or password
        HTTPException 400: Invalid input data
        HTTPException 500: Database or token generation error
    """
    # Always run one hash verification, found or not, so timing does not
    # reveal whether the email is registered.
    user = get_user_by_email(db, request.email)
    password_ok = verify_password(
        request.password, user.password_hash if user else DUMMY_HASH
    )
    if user is None or not password_ok:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid email or password",
            headers={"X-Error-Code": "INVALID_CREDENTIALS", "WWW-Authenticate": "Bearer"}
        )
    
    # Create JWT token
    try:
        token_data = {
            "sub": str(user.id),
            "email": user.email,
            "iat": datetime.now(timezone.utc)
        }
        access_token, expires_in = create_access_token(token_data)
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to generate authentication token",
            headers={"X-Error-Code": "TOKEN_ERROR"}
        ) from e
    
    return TokenResponse(
        access_token=access_token,
        token_type="bearer",
        expires_in=expires_in
    )


# ============================================================================
# Helper Functions (continued)
# ============================================================================

def _is_strong_password(password: str) -> bool:
    """
    Validate password strength.
    
    Requirements:
    - Minimum 8 characters
    - At least one uppercase letter
    - At least one lowercase letter
    - At least one digit
    - At least one special character
    
    Args:
        password: Password to validate
    
    Returns:
        True if password meets all requirements
    """
    import re
    
    if len(password) < 8:
        return False
    if not re.search(r"[A-Z]", password):
        return False
    if not re.search(r"[a-z]", password):
        return False
    if not re.search(r"\d", password):
        return False
    if not re.search(r"[!@#$%^&*()_+\-=\[\]{};:,.<>?]", password):
        return False
    
    return True
```

## Validation Checklist

### Endpoint Implementation
- [ ] All endpoints implemented with correct HTTP methods (GET, POST, PUT, DELETE, PATCH)
- [ ] Routes follow RESTful conventions: `/api/v1/{resource}` format
- [ ] Query parameters extracted and validated
- [ ] Path parameters validated and type-checked
- [ ] Response serialization models defined (Pydantic/DTO)

### Input Validation
- [ ] Request models use Pydantic BaseModel (Python) or Bean Validation (Java)
- [ ] Field constraints defined: min/max length, regex patterns, required fields
- [ ] Email validation using EmailStr or custom validator
- [ ] Password validation enforces strength requirements (8+ chars, uppercase, lowercase, digit, special)
- [ ] Numeric ranges validated (positive, non-zero where applicable)
- [ ] Enum constraints for categorical fields
- [ ] Custom validators implemented for complex business rules

### HTTP Status Codes
- [ ] `200 OK` for successful GET, PUT, PATCH requests
- [ ] `201 Created` for successful POST requests (create)
- [ ] `204 No Content` for successful DELETE requests
- [ ] `400 Bad Request` for invalid input (validation errors)
- [ ] `401 Unauthorized` for missing/invalid authentication
- [ ] `403 Forbidden` for insufficient permissions
- [ ] `404 Not Found` for missing resources
- [ ] `409 Conflict` for duplicate resources (email already registered)
- [ ] `500 Internal Server Error` for unexpected server errors

### JWT Token Handling
- [ ] Token generation with proper claims (sub, email, iat, exp)
- [ ] Token expiration set (1 hour standard)
- [ ] Token signature verification on protected routes
- [ ] Refresh token mechanism (optional but recommended)
- [ ] Token rotation on sensitive operations
- [ ] Secure Secret key storage (environment variable, never hardcoded)

### Password Security
- [ ] Password hashing with Argon2id or bcrypt (pwdlib in Python, Spring Security `PasswordEncoder` in Java)
- [ ] Password never stored in plain text
- [ ] Password never logged or returned in API responses
- [ ] Hashing uses appropriate work factors (pwdlib `recommended()` for Argon2id; bcrypt cost 12+)
- [ ] Password verification uses constant-time comparison

### Configuration & Secrets
- [ ] SECRET_KEY stored in environment variables, not in code
- [ ] Database credentials in environment variables
- [ ] JWT algorithm configured (HS256, RS256, etc.)
- [ ] CORS settings configured for frontend access
- [ ] Rate limiting configured for authentication endpoints

### Code Conventions (from python_advanced_skill/java_advanced_skill)
- [ ] Type hints on all function parameters and return types (Python)
- [ ] Docstrings on all public functions (Python) or JavaDoc (Java)
- [ ] Meaningful variable names (no single letters except loop counters)
- [ ] Functions ≤ 20 lines (single responsibility)
- [ ] Classes ≤ 300 lines (separation of concerns)
- [ ] DRY principle: no code duplication
- [ ] Proper exception handling with custom exceptions

### Error Handling
- [ ] All endpoints have try-catch (Python) or try-except (Java) blocks
- [ ] HTTPException used with meaningful messages and error codes
- [ ] Validation errors return 400 with field-level details
- [ ] Authentication errors return 401 with WWW-Authenticate header
- [ ] Duplicate resource errors return 409 with conflict explanation
- [ ] No sensitive data in error messages (e.g., "User not found" instead of database query)
- [ ] Database errors caught and translated to 500 with generic message

## Success Criteria

### Test Coverage
- [ ] **Unit tests**: 80%+ code coverage for service layer
- [ ] **Integration tests**: All API endpoints tested end-to-end
- [ ] **Authentication tests**: JWT validation, token expiration, invalid credentials
- [ ] **Validation tests**: All field validators tested with valid/invalid inputs
- [ ] **Error tests**: All error scenarios return correct status codes
- [ ] **Test naming**: Follow `test_givenXxx_whenYyy_thenZzz()` pattern
- [ ] **Test structure**: Arrange-Act-Assert (AAA) pattern used

### JWT Token Validation
- [ ] Tokens issued with correct claims and expiration
- [ ] Protected endpoints verify token presence and validity
- [ ] Expired tokens rejected with 401
- [ ] Invalid signatures rejected with 401
- [ ] Token claims (sub, email) validated for authorization decisions

### Error Handling Validation
- [ ] All error scenarios tested: validation failure, duplicate, not found, unauthorized
- [ ] Error responses include consistent format: `{"detail": "message", "code": "ERROR_CODE"}`
- [ ] Proper HTTP status codes returned (400, 401, 403, 404, 409, 500)
- [ ] No stack traces or database details exposed in error messages
- [ ] Sensitive operations (login failures) return generic "Invalid credentials"

### Security Validation
- [ ] Passwords hashed with Argon2id or bcrypt (never plaintext)
- [ ] Password strength enforced (8+ chars, mixed case, digit, special char)
- [ ] No sensitive data in logs (no passwords, tokens, API keys)
- [ ] HTTPS required for all endpoints (configured in deployment)
- [ ] CORS properly configured to prevent cross-origin abuse

### Code Quality Validation
- [ ] All functions ≤ 20 lines, all classes ≤ 300 lines
- [ ] Type hints on all function signatures
- [ ] Docstrings on all public functions
- [ ] No code duplication (DRY principle)
- [ ] Meaningful variable names throughout
- [ ] Proper separation of concerns (routes, services, models)

## Internal Calls

This skill directly leverages:

### From `python_advanced_skill`
- **Type hints**: Use on all function parameters and returns (Python FastAPI implementation)
- **Docstring standards**: Comprehensive docstrings on all public functions
- **Exception handling**: Custom exceptions and proper error propagation
- **Code organization**: Service layer pattern with separation of concerns
- **Testing patterns**: Unit tests with AAA (Arrange-Act-Assert), meaningful test names
- **PEP 8 compliance**: Naming conventions, import organization, line lengths

### From `java_advanced_skill`
- **Spring Boot patterns**: Controller-Service-Repository architecture (Java implementation)
- **Bean validation**: @Valid, @NotNull, @Email, custom validators
- **Exception handling**: Custom exceptions extending RuntimeException, @ControllerAdvice
- **Transaction management**: @Transactional for database operations
- **Testing patterns**: Unit/integration tests with Mockito, meaningful test names
- **JavaDoc standards**: Comprehensive JavaDoc on all public classes/methods

## Related Skills

- `code_health_skill.md` - Code quality, error handling, performance patterns
- `error_handling_skill.md` - Comprehensive error handling strategies
- `python_advanced_skill.md` - Python coding standards and patterns
- `java_advanced_skill.md` - Java coding standards and patterns
- `documentation_skill.md` - API documentation and examples
- `logger_skill.md` - Logging standards and practices

## Version History

### v1.0 (2025-05-20)
- Initial release
- FastAPI authentication endpoints (register, login)
- JWT token generation and validation
- Input validation with Pydantic
- Password hashing with Argon2id (pwdlib) or bcrypt
- Comprehensive error handling
- Full validation checklist and success criteria

Files in this skill

  • README.md10.2 KB
  • adr_skill.md8.4 KB
  • agent_skill_design_skill.md3.1 KB
  • apache_camel_skill.md15.5 KB
  • apache_pulsar_skill.md17.1 KB
  • ba_create_skill.md18.9 KB
  • backend_skill.md22.1 KB
  • code_documentation_skill.md13.4 KB
  • code_formatting_skill.md11.7 KB
  • code_health_skill.md9.8 KB
  • code_review_skill.md36.7 KB
  • context_builder_skill.md11.7 KB
  • current_tech_spec_skill.md6.3 KB
  • database_skill.md18.4 KB
  • debugging_skill.md3.4 KB
  • error_handling_skill.md18.4 KB
  • frontend_skill.md23.6 KB
  • java_advanced_skill.md15 KB
  • jira_html_report_skill.md15.5 KB
  • jira_incremental_spec_generator_skill.md19.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…