- Overview
- Authentication
- Base URL
- Response Format
- Error Handling
- Endpoints
- Models
- Permissions
- Rate Limiting
The TeamHub API is a RESTful API built with Django REST Framework. It provides programmatic access to all TeamHub features including teams, projects, tasks, and user management.
API Version: v1
Protocol: HTTP/HTTPS
Data Format: JSON
All protected endpoints require a JWT (JSON Web Token) in the Authorization header:
Authorization: Bearer <your-access-token>Method 1: Username/Password
POST /api/token/
Content-Type: application/json
{
"username": "john_doe",
"password": "secure_password"
}Response:
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}Method 2: Google OAuth
GET /api/auth/google/login/?redirect=http://localhost:3000This redirects to Google OAuth flow and returns a JWT token upon successful authentication.
POST /api/token/refresh
Content-Type: application/json
{
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}Response:
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}- Access Token: 60 minutes
- Refresh Token: 24 hours (sliding)
Development: http://localhost:8000/api
Production: https://api.teamhub.com/api
{
"id": 1,
"name": "Project Name",
"created_at": "2026-01-15T10:30:00Z"
}[
{
"id": 1,
"name": "Item 1"
},
{
"id": 2,
"name": "Item 2"
}
]{
"error": "Error message describing what went wrong"
}| Code | Description |
|---|---|
200 OK |
Request successful |
201 Created |
Resource created successfully |
400 Bad Request |
Invalid request parameters |
401 Unauthorized |
Missing or invalid authentication |
403 Forbidden |
Insufficient permissions |
404 Not Found |
Resource not found |
500 Internal Server Error |
Server error |
401 Unauthorized:
{
"detail": "Authentication credentials were not provided."
}403 Forbidden:
{
"error": "Only higher staff can create teams"
}404 Not Found:
{
"error": "Task not found"
}POST /api/token/Request Body:
{
"username": "john_doe",
"password": "secure_password123"
}Response: 200 OK
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}POST /api/token/refreshRequest Body:
{
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}Response: 200 OK
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}GET /api/auth/google/login/Query Parameters:
redirect(optional): URL to redirect after authentication
Response: Redirects to Google OAuth consent screen, then back to your redirect URL with token.
GET /api/auth/google/callback/custom/Query Parameters:
code: Authorization code from Google
Response: Redirects to frontend with JWT token in URL parameters.
GET /api/users/Headers:
Authorization: Bearer <token>
Response: 200 OK
[
{
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"first_name": "John",
"last_name": "Doe",
"is_staff": true
},
{
"id": 2,
"username": "jane_smith",
"email": "jane@example.com",
"first_name": "Jane",
"last_name": "Smith",
"is_staff": false
}
]GET /api/teams/Headers:
Authorization: Bearer <token>
Description: Returns all teams where the user is either a member or owner.
Response: 200 OK
[
{
"id": 1,
"name": "Development Team",
"owner": 1,
"owner_username": "john_doe",
"member_count": 5,
"created_at": "2026-01-10T08:00:00Z"
},
{
"id": 2,
"name": "Design Team",
"owner": 3,
"owner_username": "alice_wonder",
"member_count": 3,
"created_at": "2026-01-12T10:30:00Z"
}
]POST /api/teams/create/Headers:
Authorization: Bearer <token>
Permissions: User must have is_staff = true
Request Body:
{
"name": "Backend Team",
"member_ids": [2, 3, 4]
}Request Fields:
name(string, required): Team namemember_ids(array, optional): Array of user IDs to add as members
Response: 201 Created
{
"id": 3,
"name": "Backend Team",
"owner": 1,
"owner_username": "john_doe",
"member_count": 3,
"created_at": "2026-02-10T14:25:00Z"
}Error Response: 403 Forbidden
{
"error": "Only higher staff can create teams"
}GET /api/projects/Headers:
Authorization: Bearer <token>
Description: Returns all projects where the user is a member.
Response: 200 OK
[
{
"id": 1,
"name": "Website Redesign",
"team": 1,
"team_name": "Development Team",
"join_code": "a3f7b9c2",
"member_count": 5,
"members_list": [
{
"id": 1,
"username": "john_doe",
"email": "john@example.com"
},
{
"id": 2,
"username": "jane_smith",
"email": "jane@example.com"
}
],
"created_at": "2026-01-15T09:00:00Z"
}
]POST /api/projects/create/Headers:
Authorization: Bearer <token>
Permissions: User must be a member or owner of the team.
Request Body:
{
"name": "Mobile App Development",
"team_id": 1
}Request Fields:
name(string, required): Project nameteam_id(integer, required): ID of the team this project belongs to
Response: 201 Created
{
"id": 2,
"name": "Mobile App Development",
"team": 1,
"team_name": "Development Team",
"join_code": "e8d4c1f9",
"member_count": 5,
"members_list": [
{
"id": 1,
"username": "john_doe",
"email": "john@example.com"
}
],
"created_at": "2026-02-10T15:00:00Z"
}Note: All team members (including owner) are automatically added to the project.
Error Responses:
400 Bad Request
{
"error": "team_id and name are required"
}403 Forbidden
{
"error": "You are not a member of this team"
}404 Not Found
{
"error": "Team not found"
}POST /api/projects/join/Headers:
Authorization: Bearer <token>
Request Body:
{
"join_code": "a3f7b9c2"
}Request Fields:
join_code(string, required): Unique 8-character project code
Response: 200 OK
{
"message": "Joined project successfully",
"project": {
"id": 1,
"name": "Website Redesign"
}
}Error Responses:
400 Bad Request
{
"error": "join_code is required"
}404 Not Found
{
"error": "Invalid project code"
}GET /api/tasks/Headers:
Authorization: Bearer <token>
Description: Returns all tasks from projects where the user is a member.
Response: 200 OK
[
{
"id": 1,
"title": "Design homepage mockup",
"description": "Create initial design concepts for the new homepage",
"status": "doing",
"assigned_to": 2,
"assigned_to_username": "jane_smith",
"project": 1,
"project_name": "Website Redesign",
"created_at": "2026-02-08T10:00:00Z"
},
{
"id": 2,
"title": "Set up database schema",
"description": "Create models for user, team, and project",
"status": "done",
"assigned_to": 1,
"assigned_to_username": "john_doe",
"project": 1,
"project_name": "Website Redesign",
"created_at": "2026-02-07T14:30:00Z"
}
]POST /api/tasks/Headers:
Authorization: Bearer <token>
Permissions: User must be a member of the project.
Request Body:
{
"title": "Implement user authentication",
"description": "Add JWT-based authentication with Google OAuth",
"project": 1,
"assigned_to": 2,
"status": "todo"
}Request Fields:
title(string, required): Task titledescription(string, optional): Detailed task descriptionproject(integer, required): Project IDassigned_to(integer, optional): User ID to assign task tostatus(string, optional): Task status -todo(default),doing, ordone
Response: 201 Created
{
"id": 3,
"title": "Implement user authentication",
"description": "Add JWT-based authentication with Google OAuth",
"status": "todo",
"assigned_to": 2,
"assigned_to_username": "jane_smith",
"project": 1,
"project_name": "Website Redesign",
"created_at": "2026-02-10T16:00:00Z"
}Error Response: 403 Forbidden
{
"error": "You are not a member of this project"
}PATCH /api/tasks/<task_id>/Headers:
Authorization: Bearer <token>
Permissions: Only the assigned user can update task status.
Request Body:
{
"status": "doing"
}Request Fields:
status(string, required): New status -todo,doing, ordone
Example:
PATCH /api/tasks/1/
Content-Type: application/json
Authorization: Bearer <token>
{
"status": "done"
}Response: 200 OK
{
"id": 1,
"title": "Design homepage mockup",
"description": "Create initial design concepts for the new homepage",
"status": "done",
"assigned_to": 2,
"assigned_to_username": "jane_smith",
"project": 1,
"project_name": "Website Redesign",
"created_at": "2026-02-08T10:00:00Z"
}Error Responses:
400 Bad Request
{
"error": "Invalid status. Must be 'todo', 'doing', or 'done'"
}403 Forbidden
{
"error": "You are not assigned to this task"
}404 Not Found
{
"error": "Task not found"
}{
"id": Integer,
"username": String,
"email": String,
"first_name": String,
"last_name": String,
"is_staff": Boolean
}{
"id": Integer,
"name": String,
"owner": Integer (User ID),
"owner_username": String (read-only),
"member_count": Integer (computed),
"created_at": DateTime
}Relationships:
owner: One-to-Many with Usermembers: Many-to-Many with User
{
"id": Integer,
"name": String,
"team": Integer (Team ID),
"team_name": String (read-only),
"join_code": String (8 chars, auto-generated),
"member_count": Integer (computed),
"members_list": Array[User] (read-only),
"created_at": DateTime
}Relationships:
team: Many-to-One with Teammembers: Many-to-Many with User (auto-populated from team)
{
"id": Integer,
"title": String,
"description": String,
"status": String ("todo" | "doing" | "done"),
"assigned_to": Integer (User ID, nullable),
"assigned_to_username": String (read-only),
"project": Integer (Project ID),
"project_name": String (read-only),
"created_at": DateTime
}Relationships:
project: Many-to-One with Projectassigned_to: Many-to-One with User (optional)
| Endpoint | Anonymous | Authenticated | Staff Only |
|---|---|---|---|
POST /api/token/ |
β | β | β |
GET /api/users/ |
β | β | β |
GET /api/teams/ |
β | β | β |
POST /api/teams/create/ |
β | β | β |
GET /api/projects/ |
β | β | β |
POST /api/projects/create/ |
β | β * | β |
POST /api/projects/join/ |
β | β | β |
GET /api/tasks/ |
β | β | β |
POST /api/tasks/ |
β | β * | β |
PATCH /api/tasks/<id>/ |
β | β ** | β |
Legend:
- β Allowed
- β Forbidden
- β * Allowed if user is team member
- β ** Allowed if user is assigned to task
- Team Creation: Only users with
is_staff=true - Project Creation: User must be member or owner of the team
- Task Creation: User must be member of the project
- Task Status Update: User must be assigned to the task
- Project Join: Any authenticated user with valid join code
Currently, no rate limiting is implemented. Consider implementing rate limiting in production:
Recommended Limits:
- Authentication endpoints: 5 requests/minute
- Read endpoints: 100 requests/minute
- Write endpoints: 30 requests/minute
When team members are added or removed, they are automatically synchronized to all projects in that team:
Example:
- User
jane_smithis added to "Development Team" - Automatically added to all existing projects in "Development Team"
- Can immediately create tasks in those projects
When a project is created, all team members are automatically added:
Example:
- Create project "Mobile App" for "Development Team" (5 members)
- All 5 team members automatically become project members
- No manual member addition required
# 1. Login and get token
curl -X POST http://localhost:8000/api/token/ \
-H "Content-Type: application/json" \
-d '{"username": "john_doe", "password": "password123"}'
# Response: {"access": "eyJ0...", "refresh": "eyJ0..."}
# 2. Create a team (staff only)
curl -X POST http://localhost:8000/api/teams/create/ \
-H "Authorization: Bearer eyJ0..." \
-H "Content-Type: application/json" \
-d '{"name": "Dev Team", "member_ids": [2, 3]}'
# 3. Create a project
curl -X POST http://localhost:8000/api/projects/create/ \
-H "Authorization: Bearer eyJ0..." \
-H "Content-Type: application/json" \
-d '{"name": "Website Redesign", "team_id": 1}'
# 4. Create a task
curl -X POST http://localhost:8000/api/tasks/ \
-H "Authorization: Bearer eyJ0..." \
-H "Content-Type: application/json" \
-d '{
"title": "Design homepage",
"description": "Create mockups",
"project": 1,
"assigned_to": 2,
"status": "todo"
}'
# 5. Update task status
curl -X PATCH http://localhost:8000/api/tasks/1/ \
-H "Authorization: Bearer eyJ0..." \
-H "Content-Type: application/json" \
-d '{"status": "done"}'
# 6. List all tasks
curl -X GET http://localhost:8000/api/tasks/ \
-H "Authorization: Bearer eyJ0..."Add to backend/teamhub/settings.py:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}401 Unauthorized:
- Token expired (refresh it)
- Missing
Authorizationheader - Invalid token format
403 Forbidden:
- Insufficient permissions
- Not a member of team/project
- Not assigned to task
CORS Errors:
- Check
CORS_ALLOWED_ORIGINSin settings - Ensure frontend URL is whitelisted
Last Updated: February 10, 2026
API Version: 1.0