This document provides comprehensive documentation for all API endpoints in the Club Management System.
All API endpoints are relative to the application base URL.
Most endpoints require authentication. The system uses Better Auth for authentication with session-based tokens.
Authorization: Bearer token (automatically handled by Better Auth)Cookie: Session cookies (automatically managed)
Create a new team and become its leader.
Endpoint: POST /api/teams/create
Authentication: Required
Request Body:
{
"name": "string (3-50 characters)"
}Success Response (201):
{
"team": {
"id": "string",
"name": "string",
"joinCode": "string",
"members": [],
"teamleadId": "string",
"teamleadName": "string",
"points": 0,
"isVerified": false,
"createdAt": "ISO date string",
"isTeamLead": true
}
}Error Responses:
400: Invalid team name401: Unauthorized409: User already in a team500: Internal server error
Join an existing team using a join code.
Endpoint: POST /api/teams/join
Authentication: Required
Request Body:
{
"joinCode": "string (8 characters)"
}Success Response (200):
{
"message": "Successfully joined team"
}Error Responses:
400: Invalid join code or team is full401: Unauthorized404: Team not found409: User already in a team500: Internal server error
Leave the current team (for regular members only).
Endpoint: POST /api/teams/leave
Authentication: Required
Request Body: None
Success Response (200):
{
"message": "Successfully left team"
}Error Responses:
400: Team lead cannot leave (must delete team)401: Unauthorized403: Cannot leave verified team404: User not in a team500: Internal server error
Delete an entire team (team leaders only).
Endpoint: POST /api/teams/delete
Authentication: Required (Team Leader only)
Request Body: None
Success Response (200):
{
"message": "Team deleted successfully"
}Error Responses:
401: Unauthorized403: Cannot delete verified team404: User is not a team leader500: Internal server error
Get information about the current user's team.
Endpoint: GET /api/teams/my-team
Authentication: Required
Success Response (200):
{
"team": {
"id": "string",
"name": "string",
"joinCode": "string (only for team leaders)",
"members": [
{
"id": "string",
"name": "string",
"email": "string"
}
],
"teamleadId": "string",
"teamleadName": "string",
"points": "number",
"isVerified": "boolean",
"createdAt": "ISO date string",
"isTeamLead": "boolean"
}
}Response when not in a team (200):
{
"team": null
}Error Responses:
401: Unauthorized500: Internal server error
Get the ranked list of all verified teams.
Endpoint: GET /api/leaderboard
Authentication: Not required
Success Response (200):
[
{
"rank": 1,
"id": "string",
"name": "string",
"points": 0
}
]Error Response (200 - graceful degradation):
[]Retrieve all available CTF challenges for the authenticated user's team.
Endpoint: GET /api/questions
Authentication: Required
Request Body: None
Requirements:
- User must be authenticated
- User must be a member of a verified team
- Only verified teams can access challenges
Success Response (200):
{
"questions": [
{
"id": "string",
"title": "string",
"description": "string",
"objective": "string (optional)",
"notes": "string (optional)",
"hints": ["string"],
"points": "number",
"category": "string",
"resources": ["string"],
"solved": "boolean"
}
]
}Response Fields:
id: Unique identifier for the questiontitle: Challenge titledescription: Detailed challenge descriptionobjective: Learning objective (optional)notes: Additional notes (optional)hints: Array of hint stringspoints: Points awarded for solvingcategory: Challenge category (e.g., "Cryptography", "Web Security")resources: Array of resource URLssolved: Whether the user's team has solved this challenge
Error Responses:
401: Unauthorized (user not logged in)404: Team not found or not verified500: Internal server error
Notes:
- Only verified teams can access challenges
- The
solvedfield indicates if the user's current team has completed the challenge - Hints are provided as an array of strings
- Resources are external links that may help with the challenge
Submit an answer (flag) for a specific challenge.
Endpoint: POST /api/questions/submit
Authentication: Required
Request Body:
{
"questionId": "string",
"answer": "string"
}Requirements:
- User must be authenticated
- User must be a member of a verified team
- Question ID must exist
- Answer must match the exact flag (case-sensitive)
Success Response (200):
{
"success": true,
"message": "Correct answer! Points awarded.",
"points": 100
}Error Responses:
400: Invalid request, question already solved, or incorrect answer401: Unauthorized404: Team not found/not verified or question not found500: Internal server error
Get a paginated list of all users (Admin only).
Endpoint: GET /api/admin/users
Authentication: Required (Admin)
Query Parameters:
page: number (default: 1)limit: number (default: 10)search: string (optional)field: "email" | "name" (default: "email")
Success Response (200):
{
"users": [
{
"id": "string",
"name": "string",
"email": "string",
"image": "string",
"emailVerified": "boolean",
"banned": "boolean",
"banReason": "string | null",
"banExpires": "ISO date string | null",
"createdAt": "ISO date string"
}
],
"total": 100,
"page": 1,
"limit": 10
}Error Responses:
401: Unauthorized403: Forbidden (not admin)500: Internal server error
Ban a user from the system (Admin only).
Endpoint: POST /api/admin/users
Authentication: Required (Admin)
Request Body:
{
"userId": "string",
"banReason": "string",
"banExpiresIn": "number (hours from now)"
}Success Response (200):
{
"message": "User banned successfully"
}Error Responses:
400: Invalid request data401: Unauthorized403: Forbidden (not admin)404: User not found500: Internal server error
Remove ban from a user (Admin only).
Endpoint: DELETE /api/admin/users
Authentication: Required (Admin)
Request Body:
{
"userId": "string"
}Success Response (200):
{
"message": "User unbanned successfully"
}Error Responses:
401: Unauthorized403: Forbidden (not admin)404: User not found500: Internal server error
Get a list of all teams (Admin only).
Endpoint: GET /api/admin/teams
Authentication: Required (Admin)
Success Response (200):
{
"teams": [
{
"id": "string",
"name": "string",
"joinCode": "string",
"members": ["ObjectId"],
"teamleadId": "ObjectId",
"points": "number",
"isVerified": "boolean",
"createdAt": "ISO date string"
}
]
}Error Responses:
401: Unauthorized403: Forbidden (not admin)500: Internal server error
Verify or unverify a team (Admin only).
Endpoint: POST /api/admin/teams/verify
Authentication: Required (Admin)
Request Body:
{
"teamId": "string",
"isVerified": "boolean"
}Success Response (200):
{
"message": "Team verification updated successfully"
}Error Responses:
400: Invalid request data401: Unauthorized403: Forbidden (not admin)404: Team not found500: Internal server error
The authentication API is handled by Better Auth and uses a catch-all route.
Endpoint: /api/auth/[...all]
This includes endpoints for:
- Sign in/Sign up
- Sign out
- Password reset
- Session management
- OAuth providers
Refer to Better Auth documentation for detailed authentication API usage.
All error responses follow this format:
{
"error": "Error message description"
}- API endpoints may have rate limiting in place
- Respect standard HTTP status codes for rate limiting (429)
{
id: string;
name: string;
email: string;
image?: string;
emailVerified: boolean;
banned: boolean;
banReason?: string | null;
banExpires?: Date | null;
createdAt: Date;
}{
id: string;
name: string;
joinCode?: string;
members: TeamMember[];
teamleadId: string;
teamleadName: string;
points: number;
isVerified: boolean;
createdAt: string;
isTeamLead: boolean;
}{
id: string;
title: string;
description: string;
objective?: string;
notes?: string;
hints: string[];
points: number;
category: string;
resources: string[];
solved: boolean;
}{
id: string;
name: string;
email: string;
}200: Success201: Created400: Bad Request401: Unauthorized403: Forbidden404: Not Found409: Conflict500: Internal Server Error
Last updated: January 9, 2026