TODO REST API - Complete API Reference (Python FastAPI)
Overview
This document defines the complete API contract for the TODO REST API, including all endpoint specifications, authentication, request/response schemas, validation rules, and security guidelines.
Base URL: http://localhost:8000/api/v1 (or your deployed server URL)
Content-Type: application/json
Table of Contents
- Data Models
- Health Check
- Authentication
- List Endpoints
- Task Endpoints
- Error Responses
- Security Guidelines
Data Models
User
{
"id": "string (UUID v4)",
"username": "string (3-50 chars, unique)",
"email": "string (valid email, unique)",
"createdAt": "string (ISO 8601 datetime)",
"updatedAt": "string (ISO 8601 datetime, optional)"
}
Note: Passwords are never returned in responses.
List
{
"id": "string (UUID v4)",
"title": "string (required, max 255 chars)",
"description": "string (optional, max 1000 chars)",
"createdAt": "string (ISO 8601 datetime)",
"updatedAt": "string (ISO 8601 datetime, optional)"
}
Task
{
"id": "string (UUID v4)",
"listId": "string (UUID v4)",
"title": "string (required, max 255 chars)",
"description": "string (optional, max 2000 chars)",
"completed": "boolean (default: false)",
"priority": "string (enum: 'low', 'medium', 'high')",
"categories": "array of strings (max 10 items, each max 50 chars)",
"dueDate": "string (ISO 8601 datetime, optional)",
"createdAt": "string (ISO 8601 datetime)",
"updatedAt": "string (ISO 8601 datetime, optional)"
}
Health Check
GET /api/v1/health
Check the health and status of the API and its dependencies.
Authentication: Not required
Success Response (200):
{
"status": "healthy",
"timestamp": "2025-12-01T15:03:33.232819Z",
"service": "TODO REST API",
"version": "1.0.0",
"checks": {
"database": {
"status": "healthy",
"message": "Database connection successful"
},
"python": {
"status": "healthy",
"version": "3.11"
},
"disk": {
"status": "healthy",
"free_space_mb": 146645.1,
"used_percent": 6.8
},
"memory": {
"status": "healthy",
"memory_usage_mb": 13352,
"memory_available_mb": 3032
}
}
}
Status Values:
- healthy: All systems operational
- warning: System is operational but has warnings
- unhealthy: Critical issue detected (returns 503 status code)
Authentication
The API uses JWT (JSON Web Token) for authentication:
- Passwords are hashed with Argon2 (no length limits)
- Tokens expire after 1 hour (configurable)
- Tokens are sent as Authorization: Bearer <token> header
- Tokens are blacklisted on logout to prevent reuse
POST /api/v1/auth/signup
Create a new user account.
Request Body:
{
"username": "alice",
"email": "alice@example.com",
"password": "password123"
}
Validation Rules:
- username: 3-50 characters, unique, alphanumeric (underscores/hyphens allowed)
- email: Valid email format, unique
- password: Minimum 8 characters
Success Response (201):
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"user": {
"id": "a1b2c3d4-...",
"username": "alice",
"email": "alice@example.com",
"createdAt": "2025-12-01T10:00:00Z"
}
}
Error Responses:
- 400 Bad Request - Validation error
- 409 Conflict - Username or email already exists
- 422 Unprocessable Entity - Invalid input format
- 500 Internal Server Error - Server error
POST /api/v1/auth/login
Authenticate and receive a JWT token.
Request Body:
{
"username": "alice",
"password": "password123"
}
Success Response (200):
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"user": {
"id": "a1b2c3d4-...",
"username": "alice",
"email": "alice@example.com",
"createdAt": "2025-12-01T10:00:00Z"
}
}
Error Responses:
- 401 Unauthorized - Invalid username or password
- 422 Unprocessable Entity - Invalid input format
- 500 Internal Server Error - Server error
GET /api/v1/users/profile
Get current user profile (requires authentication).
Headers Required:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
Success Response (200):
{
"id": "a1b2c3d4-...",
"username": "alice",
"email": "alice@example.com",
"createdAt": "2025-12-01T10:00:00Z",
"updatedAt": null
}
Error Responses:
- 401 Unauthorized - Missing, invalid, expired, or blacklisted token
- 404 Not Found - User not found
- 500 Internal Server Error - Server error
POST /api/v1/auth/logout
Logout and blacklist the current token (requires authentication).
Headers Required:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
Success Response (204): - No content - Token is added to blacklist and can no longer be used
List Endpoints
GET /api/v1/lists
Retrieve all lists.
Response (200 OK):
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Groceries",
"description": "Weekly shopping list",
"createdAt": "2025-12-01T10:00:00Z",
"updatedAt": null
}
]
GET /api/v1/lists/{id}
Retrieve a single list by ID.
URL Parameters: id (UUID v4)
Response (200 OK):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Groceries",
"description": "Weekly shopping list",
"createdAt": "2025-12-01T10:00:00Z",
"updatedAt": null
}
Error Responses:
- 400 Bad Request - Invalid UUID format
- 404 Not Found - List not found
POST /api/v1/lists
Create a new list.
Request Body:
{
"title": "Groceries",
"description": "Weekly shopping list"
}
Validation Rules:
- title: Required, string, 1-255 characters, cannot be only whitespace
- description: Optional, string, max 1000 characters
Response (201 Created):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Groceries",
"description": "Weekly shopping list",
"createdAt": "2025-12-01T10:00:00Z",
"updatedAt": null
}
PATCH /api/v1/lists/{id}
Update an existing list.
URL Parameters: id (UUID v4)
Request Body (all fields optional):
{
"title": "Updated Groceries",
"description": "Updated description"
}
Response (200 OK):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Updated Groceries",
"description": "Updated description",
"createdAt": "2025-12-01T10:00:00Z",
"updatedAt": "2025-12-01T11:00:00Z"
}
DELETE /api/v1/lists/{id}
Delete a list and all associated tasks.
URL Parameters: id (UUID v4)
Response (204 No Content): - Empty body
Task Endpoints
GET /api/v1/lists/{listId}/tasks
Retrieve all tasks in a specific list.
URL Parameters: listId (UUID v4)
Response (200 OK):
[
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"listId": "550e8400-e29b-41d4-a716-446655440000",
"title": "Buy milk",
"description": "Get organic milk from the store",
"completed": false,
"priority": "high",
"categories": ["groceries", "dairy"],
"dueDate": "2025-12-01T18:00:00Z",
"createdAt": "2025-12-01T10:00:00Z",
"updatedAt": null
}
]
GET /api/v1/tasks/{id}
Retrieve a single task by ID.
URL Parameters: id (UUID v4)
Response (200 OK):
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"listId": "550e8400-e29b-41d4-a716-446655440000",
"title": "Buy milk",
"description": "Get organic milk from the store",
"completed": false,
"priority": "high",
"categories": ["groceries", "dairy"],
"dueDate": "2025-12-01T18:00:00Z",
"createdAt": "2025-12-01T10:00:00Z",
"updatedAt": null
}
POST /api/v1/lists/{listId}/tasks
Create a new task in a specific list.
URL Parameters: listId (UUID v4)
Request Body:
{
"title": "Buy milk",
"description": "Get organic milk from the store",
"priority": "high",
"dueDate": "2025-12-01T18:00:00Z",
"categories": ["groceries", "dairy"]
}
Validation Rules:
- title: Required, string, 1-255 characters, cannot be only whitespace
- description: Optional, string, max 2000 characters
- completed: Optional, boolean (default: false)
- dueDate: Optional, valid ISO 8601 datetime string
- priority: Optional, enum ('low', 'medium', 'high')
- categories: Optional, array of strings, max 10 items, each max 50 characters
Response (201 Created):
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"listId": "550e8400-e29b-41d4-a716-446655440000",
"title": "Buy milk",
"description": "Get organic milk from the store",
"completed": false,
"priority": "high",
"categories": ["groceries", "dairy"],
"dueDate": "2025-12-01T18:00:00Z",
"createdAt": "2025-12-01T10:00:00Z",
"updatedAt": null
}
PATCH /api/v1/tasks/{id}
Update an existing task.
URL Parameters: id (UUID v4)
Request Body (all fields optional):
{
"title": "Buy organic milk",
"completed": true,
"priority": "medium"
}
Response (200 OK):
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"listId": "550e8400-e29b-41d4-a716-446655440000",
"title": "Buy organic milk",
"description": "Get organic milk from the store",
"completed": true,
"priority": "medium",
"categories": ["groceries", "dairy"],
"dueDate": "2025-12-01T18:00:00Z",
"createdAt": "2025-12-01T10:00:00Z",
"updatedAt": "2025-12-01T11:00:00Z"
}
DELETE /api/v1/tasks/{id}
Delete a task.
URL Parameters: id (UUID v4)
Response (204 No Content): - Empty body
Error Responses
All error responses follow this format:
{
"error": "Error type",
"code": "ERROR_CODE",
"details": "Detailed error message or validation errors"
}
Common HTTP Status Codes
200 OK- Success201 Created- Resource created204 No Content- Success with no response body400 Bad Request- Invalid request data401 Unauthorized- Authentication required404 Not Found- Resource not found409 Conflict- Resource conflict (duplicate)422 Unprocessable Entity- Validation error500 Internal Server Error- Server error
Validation Error Format
{
"error": "Validation error",
"code": "VALIDATION_ERROR",
"details": {
"username": ["Username must be at least 3 characters"],
"email": ["Invalid email format"]
}
}
Security Guidelines
Authentication
- Use HTTPS in production
- Store JWT tokens securely (not in localStorage)
- Implement token refresh for long sessions
- Validate tokens on every protected request
- Logout properly to blacklist tokens
Password Security
- Minimum 8 characters required
- Argon2 hashing with secure parameters
- Never store plain text passwords
- Never log passwords in any form
Input Validation
- Validate all inputs with Pydantic schemas
- Sanitize user data before processing
- Use parameterized queries (automatic with SQLAlchemy)
- Validate UUIDs for all ID parameters
- Enforce length limits to prevent buffer overflows
Rate Limiting
- 10 requests per second per IP (configurable)
- Implemented at Nginx level
- Protects against abuse and DoS attacks
Data Protection
- No sensitive data in logs
- Generic error messages in production
- Input sanitization for all user data
- SQL injection prevention via ORM
- XSS protection via proper encoding
This API contract ensures consistent, secure, and reliable communication between clients and the TODO REST API server.