A production-grade RESTful backend API built with Flask, designed specifically for teaching and practicing API testing and automation. This API includes realistic features, comprehensive validations, and various failure scenarios to provide a complete testing experience.
This backend simulates a real enterprise API service with:
- Complete CRUD operations
- JWT authentication & authorization
- Comprehensive input validation
- Standardized response formats
- Multiple error scenarios
- Role-based access control
Perfect for QA engineers and automation testers to practice:
- API testing strategies
- Test automation frameworks
- Positive and negative test scenarios
- Authentication/Authorization testing
- Error handling validation
- Python 3.8 or higher
- pip (Python package manager)
-
Clone or download this repository
-
Navigate to the project directory
cd "API Backend"
-
Create a virtual environment (recommended)
python -m venv venv # On Windows venv\Scripts\activate # On macOS/Linux source venv/bin/activate
-
Install dependencies
pip install -r requirements.txt
-
Run the server
python app.py
The API will be available at: http://127.0.0.1:5000
| Method | Endpoint | Auth Required | Description |
|---|---|---|---|
| GET | /health |
No | Check API health status |
| Method | Endpoint | Auth Required | Description |
|---|---|---|---|
| POST | /login |
No | Login and get JWT token |
| Method | Endpoint | Auth Required | Admin Only | Description |
|---|---|---|---|---|
| POST | /users |
Yes | No | Create a new user |
| GET | /users |
No | No | Get all users |
| GET | /users/{id} |
No | No | Get user by ID |
| PUT | /users/{id} |
Yes | No | Update user |
| DELETE | /users/{id} |
Yes | Yes | Delete user |
| Method | Endpoint | Auth Required | Description |
|---|---|---|---|
| GET | /error |
No | Simulate 500 error for testing |
| POST | /reset |
No | Reset data to initial state |
-
Login to get JWT token
POST /login Content-Type: application/json { "email": "admin@example.com" }
Response:
{ "status": "success", "data": { "token": "eyJ0eXAiOiJKV1QiLCJhbGc...", "user": { "id": 1, "name": "Admin User", "email": "admin@example.com", "role": "admin" } }, "message": "Login successful" } -
Use the token in subsequent requests
GET /users Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
The API comes with two pre-seeded users for testing:
-
Admin User
- Email:
admin@example.com - Role:
admin - Can perform all operations including DELETE
- Email:
-
Regular User
- Email:
john@example.com - Role:
user - Cannot delete users
- Email:
Endpoint: GET /health
Description: Check if the API is running
Response:
{
"status": "success",
"data": {
"status": "healthy",
"timestamp": "2026-02-18T10:30:00.000000",
"version": "1.0.0"
},
"message": "API is running successfully"
}Endpoint: POST /login
Description: Authenticate user and receive JWT token
Request Body:
{
"email": "admin@example.com"
}Success Response (200):
{
"status": "success",
"data": {
"token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"user": {
"id": 1,
"name": "Admin User",
"email": "admin@example.com",
"role": "admin"
}
},
"message": "Login successful"
}Error Responses:
Missing Email (400):
{
"status": "error",
"error_code": "MISSING_FIELD",
"message": "Missing required field: email"
}Invalid Email Format (400):
{
"status": "error",
"error_code": "INVALID_EMAIL",
"message": "Invalid email format"
}User Not Found (404):
{
"status": "error",
"error_code": "USER_NOT_FOUND",
"message": "User not found with provided email"
}Endpoint: POST /users
Authentication: Required (JWT token)
Request Body:
{
"name": "Jane Smith",
"email": "jane@example.com",
"age": 28,
"role": "user"
}Success Response (201):
{
"status": "success",
"data": {
"id": 3,
"name": "Jane Smith",
"email": "jane@example.com",
"age": 28,
"role": "user",
"created_at": "2026-02-18T10:30:00.000000",
"updated_at": "2026-02-18T10:30:00.000000"
},
"message": "User created successfully"
}Error Responses:
Missing Required Field (400):
{
"status": "error",
"error_code": "MISSING_FIELD",
"message": "Missing required field: name"
}Name Too Short (400):
{
"status": "error",
"error_code": "INVALID_NAME",
"message": "Name must be at least 3 characters long"
}Invalid Email (400):
{
"status": "error",
"error_code": "INVALID_EMAIL",
"message": "Invalid email format"
}Age Less Than 18 (400):
{
"status": "error",
"error_code": "INVALID_AGE",
"message": "Age must be 18 or older"
}Duplicate Email (409):
{
"status": "error",
"error_code": "DUPLICATE_EMAIL",
"message": "Email already exists. Please use a different email."
}Unauthorized - No Token (401):
{
"status": "error",
"error_code": "MISSING_TOKEN",
"message": "Authorization token is missing. Please include a valid token in the request."
}Endpoint: GET /users
Query Parameters:
role(optional): Filter by role (adminoruser)
Example: GET /users?role=admin
Success Response (200):
{
"status": "success",
"data": {
"users": [
{
"id": 1,
"name": "Admin User",
"email": "admin@example.com",
"age": 30,
"role": "admin",
"created_at": "2026-02-18T10:00:00.000000",
"updated_at": "2026-02-18T10:00:00.000000"
},
{
"id": 2,
"name": "John Doe",
"email": "john@example.com",
"age": 25,
"role": "user",
"created_at": "2026-02-18T10:00:00.000000",
"updated_at": "2026-02-18T10:00:00.000000"
}
],
"count": 2
},
"message": "Retrieved 2 user(s) successfully"
}Endpoint: GET /users/{id}
Example: GET /users/1
Success Response (200):
{
"status": "success",
"data": {
"id": 1,
"name": "Admin User",
"email": "admin@example.com",
"age": 30,
"role": "admin",
"created_at": "2026-02-18T10:00:00.000000",
"updated_at": "2026-02-18T10:00:00.000000"
},
"message": "User retrieved successfully"
}Error Responses:
Invalid User ID (400):
{
"status": "error",
"error_code": "INVALID_USER_ID",
"message": "User ID must be a valid integer"
}User Not Found (404):
{
"status": "error",
"error_code": "USER_NOT_FOUND",
"message": "User with ID 999 not found"
}Endpoint: PUT /users/{id}
Authentication: Required (JWT token)
Request Body (all fields optional):
{
"name": "Jane Updated",
"email": "jane.updated@example.com",
"age": 30
}Success Response (200):
{
"status": "success",
"data": {
"id": 3,
"name": "Jane Updated",
"email": "jane.updated@example.com",
"age": 30,
"role": "user",
"created_at": "2026-02-18T10:30:00.000000",
"updated_at": "2026-02-18T11:00:00.000000"
},
"message": "User updated successfully"
}Error Responses: Similar to Create User, plus User Not Found (404)
Endpoint: DELETE /users/{id}
Authentication: Required (JWT token)
Authorization: Admin role required
Success Response (200):
{
"status": "success",
"data": {
"id": 3,
"name": "Jane Smith",
"email": "jane@example.com",
"age": 28,
"role": "user",
"created_at": "2026-02-18T10:30:00.000000",
"updated_at": "2026-02-18T10:30:00.000000"
},
"message": "User deleted successfully"
}Error Responses:
Forbidden - Not Admin (403):
{
"status": "error",
"error_code": "FORBIDDEN",
"message": "Admin access required. You do not have permission to perform this action."
}User Not Found (404):
{
"status": "error",
"error_code": "USER_NOT_FOUND",
"message": "User with ID 999 not found"
}- β Successfully create a user with valid data
- β Retrieve all users
- β Retrieve a specific user by ID
- β Update user with valid data
- β Delete user as admin
- β Login with valid email
- β Access protected endpoint with valid token
- β Create user with missing required fields
- β Create user with invalid email format
- β Create user with duplicate email
- β Create user with age < 18
- β Create user with name < 3 characters
- β Get non-existent user (404)
- β Update non-existent user (404)
- β Delete user without token (401)
- β Delete user as non-admin (403)
- β Access protected endpoint with expired token
- β Access protected endpoint with invalid token
- β Invalid HTTP method (405)
- π Name with exactly 3 characters
- π Age exactly 18
- π Age = 150 (maximum)
- π Age > 150 (should fail)
- π Name with 100 characters
{
"status": "success",
"data": {...},
"message": "Descriptive success message"
}{
"status": "error",
"error_code": "ERROR_CODE",
"message": "Human-readable error message"
}| Code | Description | Usage |
|---|---|---|
| 200 | OK | Successful GET, PUT, DELETE |
| 201 | Created | Successful POST |
| 400 | Bad Request | Validation errors |
| 401 | Unauthorized | Missing or invalid token |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 405 | Method Not Allowed | Invalid HTTP method |
| 409 | Conflict | Duplicate resource (email) |
| 500 | Internal Server Error | Server error |
API Backend/
β
βββ app.py # Main Flask application
βββ config.py # Configuration settings
βββ models.py # Data models and storage
βββ validators.py # Input validation logic
βββ responses.py # Response helper functions
βββ auth.py # Authentication & authorization
βββ requirements.txt # Python dependencies
βββ README.md # This file
- JWT token-based authentication
- Token expiration (1 hour)
- Role-based authorization
- Input validation and sanitization
- Email format validation
- SQL injection prevention (no SQL used)
- CORS enabled for cross-origin requests
- REST Clients: Postman, Insomnia, Thunder Client
- Automation Frameworks:
- Python: pytest + requests
- JavaScript: Jest + axios, Mocha + chai
- Java: RestAssured + TestNG/JUnit
- Performance Testing: JMeter, Locust
- API Documentation: Swagger/OpenAPI (can be added)
- Start with Health Check - Verify the API is running
- Test Authentication First - Get valid tokens for protected endpoints
- Test CRUD in Order - Create β Read β Update β Delete
- Reset Between Tests - Use
/resetendpoint to restore initial data - Test Error Scenarios - Don't just test happy paths
- Validate Response Schema - Check all responses match expected format
- Check Status Codes - Verify correct HTTP status for each scenario
- Test Authorization - Verify admin vs user permissions
If port 5000 is already in use, edit app.py and change:
app.run(debug=True, host='0.0.0.0', port=5001) # Use different portJWT tokens expire after 1 hour. Simply login again to get a new token.
CORS is enabled by default. If you encounter issues, verify Flask-CORS is installed.
Import this URL format to test APIs:
POST http://127.0.0.1:5000/login
GET http://127.0.0.1:5000/users
POST http://127.0.0.1:5000/users
import requests
# Base URL
BASE_URL = "http://127.0.0.1:5000"
# 1. Login
response = requests.post(f"{BASE_URL}/login", json={"email": "admin@example.com"})
token = response.json()["data"]["token"]
# 2. Create User
headers = {"Authorization": f"Bearer {token}"}
user_data = {
"name": "Test User",
"email": "test@example.com",
"age": 25
}
response = requests.post(f"{BASE_URL}/users", json=user_data, headers=headers)
print(response.json())This is an educational project for practicing API testing. Feel free to modify and extend it for your learning purposes.
This project is open source and available for educational purposes.
Current Version: 1.0.0
Last Updated: February 18, 2026
Happy Testing! π