TaskFlow / API_DOCUMENTATION.md
BilalCode's picture
taskflow todo app
310260a

KIro Todo API Documentation

Version: 1.0.0 Base URL: http://localhost:8001 Authentication: JWT Bearer Token


Table of Contents

  1. Overview
  2. Authentication
  3. Task Management
  4. Data Models
  5. Error Handling
  6. Security
  7. Examples

Overview

The KIro Todo API is a RESTful API built with FastAPI that provides secure, multi-user task management with complete data isolation. Each user can only access their own tasks, enforced through JWT authentication and database-level filtering.

Key Features:

  • JWT-based authentication
  • User-scoped data isolation
  • Complete CRUD operations for tasks
  • Task completion tracking
  • Comprehensive error handling
  • Automatic timestamp management

Authentication

All task endpoints require a valid JWT token in the Authorization header.

User Signup

Create a new user account.

Endpoint: POST /api/auth/signup

Request Body:

{
  "email": "user@example.com",
  "password": "SecurePass123"
}

Response: 201 Created

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "user": {
    "id": 1,
    "email": "user@example.com"
  }
}

Validation Rules:

  • Email must be valid format
  • Password minimum 8 characters
  • Password must contain: uppercase, lowercase, number
  • Email must be unique

Error Responses:

  • 400 Bad Request - Invalid email format or weak password
  • 409 Conflict - Email already exists

User Signin

Authenticate an existing user.

Endpoint: POST /api/auth/signin

Request Body:

{
  "email": "user@example.com",
  "password": "SecurePass123"
}

Response: 200 OK

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "user": {
    "id": 1,
    "email": "user@example.com"
  }
}

Error Responses:

  • 401 Unauthorized - Invalid credentials

Task Management

All task endpoints require authentication via JWT token.

Authentication Header:

Authorization: Bearer <your_jwt_token>

List All Tasks

Retrieve all tasks for the authenticated user.

Endpoint: GET /api/tasks

Headers:

Authorization: Bearer <token>

Response: 200 OK

[
  {
    "id": 1,
    "title": "Complete project documentation",
    "description": "Write comprehensive API docs",
    "completed": false,
    "user_id": 1,
    "created_at": "2026-02-03T10:30:00Z",
    "updated_at": "2026-02-03T10:30:00Z"
  },
  {
    "id": 2,
    "title": "Review pull requests",
    "description": null,
    "completed": true,
    "user_id": 1,
    "created_at": "2026-02-03T09:15:00Z",
    "updated_at": "2026-02-03T11:45:00Z"
  }
]

Query Parameters: None

Notes:

  • Returns only tasks owned by authenticated user
  • Ordered by creation date (newest first)
  • Empty array if user has no tasks

Create Task

Create a new task for the authenticated user.

Endpoint: POST /api/tasks

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
  "title": "Buy groceries",
  "description": "Milk, eggs, bread, and coffee"
}

Response: 201 Created

{
  "id": 3,
  "title": "Buy groceries",
  "description": "Milk, eggs, bread, and coffee",
  "completed": false,
  "user_id": 1,
  "created_at": "2026-02-03T12:00:00Z",
  "updated_at": "2026-02-03T12:00:00Z"
}

Field Requirements:

  • title (required): 1-200 characters, cannot be empty or whitespace
  • description (optional): 0-2000 characters, can be null

Error Responses:

  • 400 Bad Request - Missing or empty title
  • 401 Unauthorized - Invalid or missing token

Notes:

  • user_id is automatically set from JWT token
  • completed defaults to false
  • Timestamps are automatically generated

Get Single Task

Retrieve a specific task by ID.

Endpoint: GET /api/tasks/{task_id}

Headers:

Authorization: Bearer <token>

Path Parameters:

  • task_id (integer): The task ID

Response: 200 OK

{
  "id": 1,
  "title": "Complete project documentation",
  "description": "Write comprehensive API docs",
  "completed": false,
  "user_id": 1,
  "created_at": "2026-02-03T10:30:00Z",
  "updated_at": "2026-02-03T10:30:00Z"
}

Error Responses:

  • 401 Unauthorized - Invalid or missing token
  • 403 Forbidden - Task belongs to another user
  • 404 Not Found - Task does not exist

Security:

  • Ownership is verified before returning task
  • Users cannot access other users' tasks

Update Task

Update an existing task's title and/or description.

Endpoint: PUT /api/tasks/{task_id}

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Path Parameters:

  • task_id (integer): The task ID

Request Body:

{
  "title": "Complete project documentation (Updated)",
  "description": "Write comprehensive API docs with examples"
}

Partial Update Supported:

{
  "title": "New title only"
}

Response: 200 OK

{
  "id": 1,
  "title": "Complete project documentation (Updated)",
  "description": "Write comprehensive API docs with examples",
  "completed": false,
  "user_id": 1,
  "created_at": "2026-02-03T10:30:00Z",
  "updated_at": "2026-02-03T12:30:00Z"
}

Field Requirements:

  • title (optional): If provided, 1-200 characters, cannot be empty
  • description (optional): If provided, 0-2000 characters

Error Responses:

  • 400 Bad Request - Empty title provided
  • 401 Unauthorized - Invalid or missing token
  • 403 Forbidden - Task belongs to another user
  • 404 Not Found - Task does not exist

Notes:

  • Only provided fields are updated
  • updated_at timestamp is automatically updated
  • Ownership is verified before update

Delete Task

Permanently delete a task.

Endpoint: DELETE /api/tasks/{task_id}

Headers:

Authorization: Bearer <token>

Path Parameters:

  • task_id (integer): The task ID

Response: 200 OK

{
  "message": "Task deleted successfully"
}

Error Responses:

  • 401 Unauthorized - Invalid or missing token
  • 403 Forbidden - Task belongs to another user
  • 404 Not Found - Task does not exist

Notes:

  • Deletion is permanent (no soft delete)
  • Ownership is verified before deletion

Toggle Task Completion

Toggle a task's completion status (complete ↔ incomplete).

Endpoint: PATCH /api/tasks/{task_id}/complete

Headers:

Authorization: Bearer <token>

Path Parameters:

  • task_id (integer): The task ID

Request Body: None

Response: 200 OK

{
  "id": 1,
  "title": "Complete project documentation",
  "description": "Write comprehensive API docs",
  "completed": true,
  "user_id": 1,
  "created_at": "2026-02-03T10:30:00Z",
  "updated_at": "2026-02-03T13:00:00Z"
}

Behavior:

  • completed: false β†’ completed: true
  • completed: true β†’ completed: false

Error Responses:

  • 401 Unauthorized - Invalid or missing token
  • 403 Forbidden - Task belongs to another user
  • 404 Not Found - Task does not exist

Notes:

  • updated_at timestamp is automatically updated
  • Ownership is verified before toggle

Data Models

User

{
  id: number;              // Auto-generated primary key
  email: string;           // Unique, valid email format
  password_hash: string;   // Bcrypt hashed password (never exposed in API)
  created_at: datetime;    // Auto-generated timestamp
}

Task

{
  id: number;              // Auto-generated primary key
  title: string;           // Required, 1-200 characters
  description: string | null;  // Optional, 0-2000 characters
  completed: boolean;      // Default: false
  user_id: number;         // Foreign key to User (from JWT)
  created_at: datetime;    // Auto-generated timestamp
  updated_at: datetime;    // Auto-updated on changes
}

JWT Token Payload

{
  user_id: number;         // User's database ID
  email: string;           // User's email
  exp: number;             // Token expiration timestamp
  iat: number;             // Token issued at timestamp
}

Error Handling

All errors follow a consistent format:

{
  "error": "Detailed error message",
  "message": "User-friendly message",
  "details": null
}

HTTP Status Codes

Code Meaning When Used
200 OK Successful GET, PUT, PATCH, DELETE
201 Created Successful POST (resource created)
400 Bad Request Invalid input, validation failure
401 Unauthorized Missing or invalid JWT token
403 Forbidden Valid token but insufficient permissions
404 Not Found Resource does not exist
409 Conflict Resource already exists (e.g., duplicate email)
500 Internal Server Error Unexpected server error

Common Error Scenarios

Missing Authentication:

{
  "error": "Not authenticated",
  "message": "Authentication is required to access this resource",
  "details": null
}

Invalid Token:

{
  "error": "Invalid token",
  "message": "Authentication is required to access this resource",
  "details": null
}

Accessing Another User's Task:

{
  "error": "You do not have permission to access this task",
  "message": "You do not have permission to access this resource",
  "details": null
}

Task Not Found:

{
  "error": "Task not found",
  "message": "The requested resource was not found",
  "details": null
}

Validation Error:

{
  "error": "Title is required and cannot be empty",
  "message": "The request contains invalid data",
  "details": null
}

Security

Authentication Flow

  1. User Registration/Login:

    • User provides email and password
    • Backend validates credentials
    • Backend generates JWT token with user_id
    • Token returned to client
  2. Authenticated Requests:

    • Client includes token in Authorization: Bearer <token> header
    • Backend verifies token signature
    • Backend extracts user_id from token payload
    • Backend uses user_id for all database queries

Security Guarantees

βœ… User Identity from JWT Only:

  • User ID is NEVER accepted from client input
  • All user identification comes from verified JWT token
  • Prevents user impersonation attacks

βœ… Complete Data Isolation:

  • All database queries filtered by authenticated user_id
  • Users cannot view, edit, or delete other users' tasks
  • Ownership verified on every operation

βœ… Password Security:

  • Passwords hashed with bcrypt before storage
  • Plain-text passwords never stored
  • Password hashes never exposed in API responses

βœ… SQL Injection Prevention:

  • All queries use SQLModel ORM with parameterization
  • No raw SQL with string concatenation

βœ… CORS Protection:

  • CORS middleware configured with allowed origins
  • Prevents unauthorized cross-origin requests

Token Management

Token Expiration: 7 days (168 hours)

Token Format:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJleHAiOjE3MDcwNTI4MDB9.signature

Token Verification:

  • Signature verified using JWT_SECRET
  • Expiration checked on every request
  • Invalid tokens rejected with 401 Unauthorized

Examples

Complete Workflow Example

1. Create Account

curl -X POST http://localhost:8001/api/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
    "email": "john@example.com",
    "password": "SecurePass123"
  }'

Response:

{
  "access_token": "eyJhbGc...",
  "token_type": "bearer",
  "user": {
    "id": 1,
    "email": "john@example.com"
  }
}

2. Create Task

curl -X POST http://localhost:8001/api/tasks \
  -H "Authorization: Bearer eyJhbGc..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Learn FastAPI",
    "description": "Build a REST API with authentication"
  }'

Response:

{
  "id": 1,
  "title": "Learn FastAPI",
  "description": "Build a REST API with authentication",
  "completed": false,
  "user_id": 1,
  "created_at": "2026-02-03T14:00:00Z",
  "updated_at": "2026-02-03T14:00:00Z"
}

3. List Tasks

curl -X GET http://localhost:8001/api/tasks \
  -H "Authorization: Bearer eyJhbGc..."

Response:

[
  {
    "id": 1,
    "title": "Learn FastAPI",
    "description": "Build a REST API with authentication",
    "completed": false,
    "user_id": 1,
    "created_at": "2026-02-03T14:00:00Z",
    "updated_at": "2026-02-03T14:00:00Z"
  }
]

4. Mark Task Complete

curl -X PATCH http://localhost:8001/api/tasks/1/complete \
  -H "Authorization: Bearer eyJhbGc..."

Response:

{
  "id": 1,
  "title": "Learn FastAPI",
  "description": "Build a REST API with authentication",
  "completed": true,
  "user_id": 1,
  "created_at": "2026-02-03T14:00:00Z",
  "updated_at": "2026-02-03T14:30:00Z"
}

5. Update Task

curl -X PUT http://localhost:8001/api/tasks/1 \
  -H "Authorization: Bearer eyJhbGc..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Master FastAPI",
    "description": "Build production-ready APIs"
  }'

6. Delete Task

curl -X DELETE http://localhost:8001/api/tasks/1 \
  -H "Authorization: Bearer eyJhbGc..."

Response:

{
  "message": "Task deleted successfully"
}

JavaScript/TypeScript Example

// API Client Configuration
const API_BASE_URL = 'http://localhost:8001';
let authToken: string | null = null;

// Signup
async function signup(email: string, password: string) {
  const response = await fetch(`${API_BASE_URL}/api/auth/signup`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password })
  });

  const data = await response.json();
  authToken = data.access_token;
  return data;
}

// Create Task
async function createTask(title: string, description?: string) {
  const response = await fetch(`${API_BASE_URL}/api/tasks`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${authToken}`
    },
    body: JSON.stringify({ title, description })
  });

  return response.json();
}

// List Tasks
async function listTasks() {
  const response = await fetch(`${API_BASE_URL}/api/tasks`, {
    headers: {
      'Authorization': `Bearer ${authToken}`
    }
  });

  return response.json();
}

// Toggle Task Completion
async function toggleTaskComplete(taskId: number) {
  const response = await fetch(`${API_BASE_URL}/api/tasks/${taskId}/complete`, {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${authToken}`
    }
  });

  return response.json();
}

// Delete Task
async function deleteTask(taskId: number) {
  const response = await fetch(`${API_BASE_URL}/api/tasks/${taskId}`, {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${authToken}`
    }
  });

  return response.json();
}

Testing the API

Using Swagger UI

FastAPI provides interactive API documentation:

  1. Start the backend server
  2. Open browser to: http://localhost:8001/docs
  3. Click "Authorize" button
  4. Enter JWT token from signup/signin response
  5. Test endpoints interactively

Using Postman

  1. Import the API endpoints
  2. Set Authorization header: Bearer <token>
  3. Set Content-Type header: application/json
  4. Test each endpoint

Using curl

See examples above for complete curl commands.


Rate Limiting & Performance

Current Implementation:

  • No rate limiting (suitable for development/hackathon)
  • Database connection pooling via Neon PostgreSQL
  • Async/await for non-blocking I/O

Production Recommendations:

  • Add rate limiting middleware
  • Implement request caching
  • Add database query optimization
  • Monitor API performance metrics

Support & Troubleshooting

Common Issues:

  1. 401 Unauthorized on all requests

    • Check token is included in Authorization header
    • Verify token format: Bearer <token>
    • Ensure JWT_SECRET matches between backend and frontend
  2. 403 Forbidden when accessing task

    • Task belongs to another user
    • Verify you're using correct user's token
  3. CORS errors from frontend

    • Check CORS_ORIGINS in backend .env
    • Ensure frontend URL is in allowed origins list
  4. Database connection errors

    • Verify DATABASE_URL in .env
    • Check Neon PostgreSQL is accessible
    • Test connection with database client

API Versioning

Current Version: v1.0.0

Endpoint Prefix: /api/

Future Versioning Strategy:

  • Breaking changes will use new prefix: /api/v2/
  • Current endpoints will remain stable
  • Deprecation notices will be provided in advance

Changelog

v1.0.0 (2026-02-03)

  • Initial release
  • User authentication (signup, signin)
  • Task CRUD operations
  • Task completion tracking
  • JWT-based security
  • Complete data isolation

Last Updated: 2026-02-03 Maintained By: KIro Todo Development Team