Skip to main content

API Endpoints

All endpoints are prefixed with /api. The base URL in development is http://localhost:5000/api.


Auth — /api/auth​

These endpoints handle user registration, login, session management, and password recovery.

MethodPathAuth RequiredDescription
POST/auth/registerNoRegister a new user account
POST/auth/loginNoLogin and set JWT httpOnly cookie
POST/auth/logoutNoClear JWT cookie
GET/auth/profileYesGet the currently authenticated user's profile
GET/auth/verify-emailNoVerify email address via token in query string
POST/auth/resend-verificationNoResend the email verification link
POST/auth/forgot-passwordNoRequest a password reset email
POST/auth/reset-passwordNoSubmit a new password using a reset token
GET/auth/users/:usernameNoGet a public user profile by username

POST /auth/register​

Request body:

{
"username": "Player123",
"email": "player@example.com",
"password": "SecurePassword1!"
}

Responses:

  • 201 — User created, verification email sent
  • 400 — Validation error (missing fields, duplicate email/username)

POST /auth/login​

Request body:

{
"email": "player@example.com",
"password": "SecurePassword1!"
}

Responses:

  • 200 — Login successful; sets token (httpOnly) and auth_info cookies
  • 400 — Invalid credentials or email not verified

GET /auth/verify-email​

Query parameters:

  • token — The verification token sent by email

Responses:

  • 200 — Email verified successfully
  • 400 — Invalid or expired token

POST /auth/forgot-password​

Request body:

{ "email": "player@example.com" }

Responses:

  • 200 — If the email exists, a reset link is sent (always returns 200 to avoid email enumeration)

POST /auth/reset-password​

Request body:

{
"token": "<reset-token-from-email>",
"newPassword": "NewSecurePassword1!"
}

Responses:

  • 200 — Password updated
  • 400 — Invalid or expired token

Lobbies — /api/lobbies​

MethodPathAuth RequiredDescription
GET/lobbiesNoList all lobbies (filterable, paginated)
POST/lobbiesYesCreate a new lobby
GET/lobbies/:idNoGet a single lobby by ID
GET/lobbies/my-createdYesGet lobbies created by the current user
PATCH/lobbies/:id/statusYesUpdate lobby status (open/closed/completed)
POST/lobbies/sync-countsYesSync participant count cache

GET /lobbies — Query Parameters​

ParameterTypeDescription
pagenumberPage number (default: 1)
limitnumberResults per page (default: 10)
statusstringFilter by status: open, closed, completed
gamestringFilter by game name

Response:

{
"lobbies": [...],
"total": 42,
"page": 1,
"pages": 5
}

POST /lobbies — Create Lobby​

Request body:

{
"name": "Ranked Match #1",
"game": "League of Legends",
"maxParticipants": 10,
"description": "Competitive ranked lobby"
}

Lobby Participants — /api/lobby-participants​

MethodPathAuth RequiredDescription
POST/lobby-participants/registerYesJoin a lobby
POST/lobby-participants/leaveYesLeave a lobby
GET/lobby-participants/my-lobbiesYesGet all lobbies the current user has joined

POST /lobby-participants/register​

Request body:

{ "lobbyId": "64abc123..." }

POST /lobby-participants/leave​

Request body:

{ "lobbyId": "64abc123..." }

Match Results — /api/match-results​

MethodPathAuth RequiredDescription
POST/match-results/submit-replayYesSubmit match result with a replay URL
GET/match-results/lobby/:lobbyIdNoGet all match results for a lobby

POST /match-results/submit-replay​

Request body:

{
"lobbyId": "64abc123...",
"replayUrl": "https://replay.pokemonshowdown.com/gen9randombattle-...",
"winnerId": "64def456..."
}

Validation: The replay URL must match a supported game's pattern (e.g., replay.pokemonshowdown.com).


Leaderboard — /api/leaderboard​

MethodPathAuth RequiredDescription
GET/leaderboardNoGet ranked players sorted by MMR

GET /leaderboard — Query Parameters​

ParameterTypeDescription
pagenumberPage number (default: 1)
limitnumberResults per page (default: 20)

Response:

{
"players": [
{
"rank": 1,
"username": "TopPlayer",
"mmr": 3200,
"tier": "Elite",
"wins": 50,
"losses": 10
}
],
"total": 200,
"page": 1,
"pages": 10
}

Riot Games — /api/riot​

MethodPathAuth RequiredDescription
POST/riot/linkYesLink a Riot account to the user profile
DELETE/riot/unlinkYesUnlink Riot account
GET/riot/profileYesGet the current user's linked Riot profile
GET/riot/profile/:riotIdNoGet a Riot profile by Riot ID
POST/riot/submit-lol-matchYesSubmit a League of Legends match
GET/riot/oauth/urlYesGet the Riot OAuth authorization URL
GET/riot/oauth/callbackNoOAuth callback (handled server-side)

GET /riot/oauth/url​

Returns the Riot RSO OAuth URL to redirect the user to for account authorization.

Response:

{
"url": "https://auth.riotgames.com/authorize?client_id=..."
}

Admin — /api/admin​

All admin endpoints require an authenticated user with the ADMIN role.

MethodPathDescription
GET/admin/statsPlatform-wide statistics
GET/admin/usersList all users (paginated)
POST/admin/usersCreate a new user
PATCH/admin/users/:idUpdate a user's data or role
DELETE/admin/users/:idDelete a user
GET/admin/lobbiesList all lobbies
PATCH/admin/lobbies/:idUpdate any lobby
DELETE/admin/lobbies/:idDelete any lobby

GET /admin/stats​

Response:

{
"totalUsers": 1500,
"totalLobbies": 320,
"openLobbies": 45,
"totalMatches": 980
}

GET /admin/users — Query Parameters​

ParameterTypeDescription
pagenumberPage number
limitnumberResults per page
searchstringSearch by username or email

Error Response Format​

All endpoints return errors in a consistent format:

{
"message": "Human-readable error description",
"error": "OPTIONAL_ERROR_CODE"
}
HTTP StatusMeaning
200OK
201Created
400Bad Request (validation error, business rule violation)
401Unauthorized (missing or invalid JWT)
403Forbidden (insufficient role)
404Not Found
500Internal Server Error