Back to skills
SKILL.md
Backend
ASecurityGenerating REST endpoints in FastAPI or Spring Boot (`implementer:build`, `architect:api`)
- 3 stars
- 0 votes
- 0 copies
- 0 views
- Added October 1, 2026
Works with
Security analysis
100/100npx -y skills add sharmapuneet1510/awesome-prompts --skill backend --agent claude-codeAre you the author of Backend?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/sharmapuneet1510-backend)---
name: backend
description: Generating REST endpoints in FastAPI or Spring Boot (`implementer:build`, `architect: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
Attribution
Comments
Loading comments…