17 KiB
API Routes Documentation
Complete reference for all backend API endpoints.
Base URL
http://localhost:3100/api
Authentication
Most endpoints require authentication via JWT Bearer token:
Authorization: Bearer <access_token>
Response Format
Success Response
{
"data": [...],
"total": 100,
"page": 1,
"limit": 50,
"totalPages": 2
}
Error Response
{
"error": {
"message": "Error description",
"statusCode": 400
}
}
HTTP Status Codes
200 OK- Request successful201 Created- Resource created successfully400 Bad Request- Invalid input401 Unauthorized- Authentication required or failed403 Forbidden- Insufficient permissions404 Not Found- Resource not found409 Conflict- Resource already exists429 Too Many Requests- Rate limit exceeded500 Internal Server Error- Server error
Authentication Routes
POST /auth/login
Login with username and password.
Request Body:
{
"username": "admin",
"password": "admin123"
}
Response (200):
{
"user": {
"id": 1,
"username": "admin",
"email": "admin@flashpoint.local",
"role": "admin",
"permissions": ["games.read", "games.play", ...]
},
"tokens": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "a1b2c3d4e5f6...",
"expiresIn": 3600
}
}
Validation:
username: 3-50 characterspassword: Minimum 6 characters
Errors:
401- Invalid credentials429- Too many failed attempts (lockout)
POST /auth/register
Register a new user account.
Request Body:
{
"username": "newuser",
"email": "user@example.com",
"password": "password123"
}
Response (201):
{
"user": {
"id": 2,
"username": "newuser",
"email": "user@example.com",
"role": "user",
"permissions": ["games.read", "games.play", ...]
},
"tokens": {
"accessToken": "...",
"refreshToken": "...",
"expiresIn": 3600
}
}
Validation:
username: 3-50 characters, uniqueemail: Valid email format, uniquepassword: Minimum 6 characters
Errors:
403- Registration disabled409- Username or email already exists
POST /auth/logout
Logout and revoke refresh token.
Request Body:
{
"refreshToken": "a1b2c3d4e5f6..."
}
Response (200):
{
"success": true,
"message": "Logged out successfully"
}
POST /auth/refresh
Refresh access token using refresh token.
Request Body:
{
"refreshToken": "a1b2c3d4e5f6..."
}
Response (200):
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "new-refresh-token...",
"expiresIn": 3600
}
Errors:
401- Invalid or expired refresh token
GET /auth/me
Get current authenticated user information.
Headers: Authorization: Bearer <token>
Response (200):
{
"id": 1,
"username": "admin",
"email": "admin@flashpoint.local",
"role": "admin",
"permissions": ["games.read", "games.play", ...]
}
User Management Routes
GET /users
List all users with pagination.
Auth: Required
Permission: users.read
Query Parameters:
page(number, default: 1)limit(number, default: 50, max: 100)
Response (200):
{
"data": [
{
"id": 1,
"username": "admin",
"email": "admin@flashpoint.local",
"roleId": 1,
"roleName": "admin",
"isActive": true,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z",
"lastLoginAt": "2024-01-15T10:30:00.000Z"
}
],
"total": 10,
"page": 1,
"limit": 50,
"totalPages": 1
}
GET /users/:id
Get single user by ID.
Auth: Required
Permission: users.read
Response (200):
{
"id": 1,
"username": "admin",
"email": "admin@flashpoint.local",
"roleId": 1,
"roleName": "admin",
"isActive": true,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z",
"lastLoginAt": "2024-01-15T10:30:00.000Z"
}
Errors:
404- User not found
POST /users
Create new user (admin only).
Auth: Required
Permission: users.create
Request Body:
{
"username": "newuser",
"email": "user@example.com",
"password": "password123",
"roleId": 2,
"isActive": true
}
Response (201):
{
"id": 2,
"username": "newuser",
"email": "user@example.com",
"roleId": 2,
"roleName": "user",
"isActive": true,
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-01-15T10:00:00.000Z"
}
Errors:
409- Username or email already exists
PATCH /users/:id
Update existing user.
Auth: Required
Permission: users.update
Request Body:
{
"email": "newemail@example.com",
"roleId": 3,
"isActive": false
}
Response (200):
{
"id": 2,
"username": "newuser",
"email": "newemail@example.com",
"roleId": 3,
"roleName": "moderator",
"isActive": false,
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-01-15T11:00:00.000Z"
}
DELETE /users/:id
Delete user (prevents deleting last admin).
Auth: Required
Permission: users.delete
Response (200):
{
"success": true,
"message": "User deleted successfully"
}
Errors:
403- Cannot delete last admin404- User not found
POST /users/:id/change-password
Change user password. Users can change their own password, admins can change any password.
Auth: Required
Request Body:
{
"currentPassword": "oldpassword",
"newPassword": "newpassword123"
}
Response (200):
{
"success": true,
"message": "Password changed successfully"
}
Errors:
401- Current password incorrect403- Insufficient permissions
GET /users/me/settings
Get all settings for current user.
Auth: Required
Response (200):
{
"theme_mode": "dark",
"primary_color": "blue",
"sidebar_collapsed": "false"
}
PATCH /users/me/settings
Update multiple settings for current user.
Auth: Required
Request Body:
{
"theme_mode": "light",
"primary_color": "green",
"sidebar_collapsed": "true"
}
Response (200):
{
"theme_mode": "light",
"primary_color": "green",
"sidebar_collapsed": "true"
}
Game Routes
GET /games
Search and filter games with pagination.
Auth: Optional (guest access if enabled)
Permission: games.read
Query Parameters:
search(string) - Search in title, developer, publisherplatforms[](string[]) - Filter by platform namesseries[](string[]) - Filter by series namesdevelopers[](string[]) - Filter by developerspublishers[](string[]) - Filter by publishersplayModes[](string[]) - Filter by play modeslanguages[](string[]) - Filter by languageslibrary(string) - Filter by library (arcade, theatre)tags[](string[]) - Filter by tagsyearFrom(number) - Filter by release year (min)yearTo(number) - Filter by release year (max)showBroken(boolean, default: false) - Include broken gamesshowExtreme(boolean, default: false) - Include adult contentsortBy(string, default: title) - Sort columnsortOrder(asc|desc, default: asc) - Sort directionpage(number, default: 1)limit(number, default: 50, max: 100)
Response (200):
{
"data": [
{
"id": "12345-abcd-6789",
"title": "Game Title",
"developer": "Developer Name",
"publisher": "Publisher Name",
"platformName": "Flash",
"library": "arcade",
"releaseDate": "2010-05-15",
"tagsStr": "Action;Adventure;Platformer",
"logoPath": "Logos/1/12345-abcd-6789.png",
"screenshotPath": "Screenshots/1/12345-abcd-6789.png",
"presentOnDisk": 1,
"lastPlayed": "2024-01-15T10:00:00.000Z",
"playtime": 3600,
"playCounter": 5
}
],
"total": 1000,
"page": 1,
"limit": 50,
"totalPages": 20
}
GET /games/:id
Get single game by ID with all details.
Auth: Optional
Permission: games.read
Response (200):
{
"id": "12345-abcd-6789",
"title": "Game Title",
"alternateTitles": "Alternate Title",
"series": "Game Series",
"developer": "Developer Name",
"publisher": "Publisher Name",
"platformName": "Flash",
"playMode": "Single Player",
"status": "Playable",
"broken": false,
"extreme": false,
"notes": "Game notes",
"tagsStr": "Action;Adventure",
"source": "https://example.com",
"launchCommand": "http://example.com/game.swf",
"releaseDate": "2010-05-15",
"version": "1.0",
"originalDescription": "Game description",
"language": "English",
"library": "arcade",
"logoPath": "Logos/1/12345-abcd-6789.png",
"screenshotPath": "Screenshots/1/12345-abcd-6789.png",
"presentOnDisk": 1,
"lastPlayed": "2024-01-15T10:00:00.000Z",
"playtime": 3600,
"playCounter": 5
}
Errors:
404- Game not found
GET /games/:id/related
Get related games (same developer or platform).
Auth: Optional
Permission: games.read
Query Parameters:
limit(number, default: 10, max: 50)
Response (200):
[
{
"id": "67890-efgh-1234",
"title": "Related Game",
"developer": "Developer Name",
"platformName": "Flash",
...
}
]
GET /games/random
Get a random game.
Auth: Optional
Permission: games.read
Query Parameters:
library(string, optional) - Filter by library
Response (200):
{
"id": "12345-abcd-6789",
"title": "Random Game",
...
}
GET /games/filter-options
Get all filter options for dropdowns (series, developers, platforms, etc.).
Auth: Optional
Permission: games.read
Response (200):
{
"series": [
{ "name": "Game Series", "count": 50 }
],
"developers": [
{ "name": "Developer Name", "count": 100 }
],
"publishers": [
{ "name": "Publisher Name", "count": 75 }
],
"playModes": [
{ "name": "Single Player", "count": 1000 },
{ "name": "Multiplayer", "count": 200 }
],
"languages": [
{ "name": "English", "count": 5000 }
],
"tags": [
{ "name": "Action", "count": 500 }
],
"platforms": [
{ "name": "Flash", "count": 10000 },
{ "name": "HTML5", "count": 2000 }
],
"yearRange": {
"min": 1990,
"max": 2024
}
}
Play Tracking Routes
All play tracking routes require authentication.
POST /play/start
Start a new play session.
Auth: Required
Permission: games.play
Request Body:
{
"gameId": "12345-abcd-6789",
"gameTitle": "Game Title"
}
Response (200):
{
"success": true,
"sessionId": "a1b2c3d4e5f6..."
}
POST /play/end
End a play session.
Auth: Required
Request Body:
{
"sessionId": "a1b2c3d4e5f6..."
}
Response (200):
{
"success": true,
"message": "Play session ended successfully"
}
GET /play/stats
Get current user's overall play statistics.
Auth: Required
Response (200):
{
"userId": 1,
"totalGamesPlayed": 50,
"totalPlaytimeSeconds": 36000,
"totalSessions": 150,
"firstPlayAt": "2024-01-01T00:00:00.000Z",
"lastPlayAt": "2024-01-15T10:00:00.000Z"
}
GET /play/game-stats
Get current user's per-game statistics.
Auth: Required
Query Parameters:
limit(number, default: 50, max: 100)offset(number, default: 0)
Response (200):
{
"data": [
{
"gameId": "12345-abcd-6789",
"gameTitle": "Game Title",
"totalPlays": 5,
"totalPlaytimeSeconds": 3600,
"firstPlayedAt": "2024-01-10T00:00:00.000Z",
"lastPlayedAt": "2024-01-15T10:00:00.000Z"
}
],
"limit": 50,
"offset": 0
}
GET /play/history
Get current user's play session history.
Auth: Required
Query Parameters:
limit(number, default: 50, max: 100)offset(number, default: 0)
Response (200):
{
"data": [
{
"id": 1,
"userId": 1,
"gameId": "12345-abcd-6789",
"gameTitle": "Game Title",
"startedAt": "2024-01-15T10:00:00.000Z",
"endedAt": "2024-01-15T11:00:00.000Z",
"durationSeconds": 3600,
"sessionId": "a1b2c3d4e5f6..."
}
],
"limit": 50,
"offset": 0
}
GET /play/top-games
Get current user's top played games by playtime.
Auth: Required
Query Parameters:
limit(number, default: 10, max: 50)
Response (200):
[
{
"gameId": "12345-abcd-6789",
"gameTitle": "Game Title",
"totalPlays": 10,
"totalPlaytimeSeconds": 7200,
"firstPlayedAt": "2024-01-01T00:00:00.000Z",
"lastPlayedAt": "2024-01-15T00:00:00.000Z"
}
]
GET /play/activity-over-time
Get play activity over time (daily aggregation).
Auth: Required
Query Parameters:
days(number, default: 30, max: 365)
Response (200):
[
{
"date": "2024-01-15",
"playtime": 3600,
"sessions": 5
}
]
GET /play/games-distribution
Get games distribution by playtime (for pie charts).
Auth: Required
Query Parameters:
limit(number, default: 10, max: 20)
Response (200):
[
{
"name": "Game Title",
"value": 7200
}
]
Role & Permission Routes
GET /roles
Get all roles with their permissions.
Auth: Required
Permission: roles.read
Response (200):
[
{
"id": 1,
"name": "admin",
"description": "Administrator with full access",
"priority": 100,
"permissions": [
{
"id": 1,
"name": "games.read",
"description": "View and browse games",
"resource": "games",
"action": "read"
}
],
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
]
GET /roles/:id
Get single role with permissions.
Auth: Required
Permission: roles.read
Response (200):
{
"id": 1,
"name": "admin",
"description": "Administrator with full access",
"priority": 100,
"permissions": [...],
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
GET /roles/permissions
Get all available permissions.
Auth: Required
Permission: roles.read
Response (200):
[
{
"id": 1,
"name": "games.read",
"description": "View and browse games",
"resource": "games",
"action": "read"
}
]
Activity Log Routes
GET /activities
Get activity logs with pagination and filtering.
Auth: Required
Permission: activities.read
Query Parameters:
page(number, default: 1)limit(number, default: 50, max: 100)userId(number, optional) - Filter by useraction(string, optional) - Filter by actionresource(string, optional) - Filter by resourcedateFrom(string, optional) - Filter by date (ISO format)dateTo(string, optional) - Filter by date (ISO format)
Response (200):
{
"data": [
{
"id": 1,
"userId": 1,
"username": "admin",
"action": "login",
"resource": "auth",
"resourceId": null,
"details": null,
"ipAddress": "192.168.1.1",
"userAgent": "Mozilla/5.0...",
"createdAt": "2024-01-15T10:00:00.000Z"
}
],
"total": 100,
"page": 1,
"limit": 50,
"totalPages": 2
}
Platform Routes
GET /platforms
Get all platforms.
Auth: Optional
Response (200):
[
{
"name": "Flash",
"count": 10000
},
{
"name": "HTML5",
"count": 2000
}
]
Tag Routes
GET /tags
Get all tags with game counts.
Auth: Optional
Response (200):
[
{
"name": "Action",
"count": 500
},
{
"name": "Adventure",
"count": 300
}
]
Utility Routes
GET /health
Server health check (no authentication required).
Response (200):
{
"status": "ok",
"timestamp": "2024-01-15T10:00:00.000Z",
"flashpointPath": "D:/Flashpoint",
"databaseConnected": true,
"gameServiceUrl": "http://localhost:22500"
}
Rate Limiting
Default rate limits:
- Window: 60 seconds
- Max requests: 100 per window
Exceeding rate limit returns:
{
"error": {
"message": "Too many requests, please try again later",
"statusCode": 429
}
}
CORS
CORS is configured to allow requests from the configured frontend origin (default: http://localhost:5173).
Allowed headers:
AuthorizationContent-Type
Allowed methods:
GET,POST,PATCH,DELETE,OPTIONS
Pagination
Paginated endpoints follow this pattern:
Request:
GET /api/users?page=2&limit=25
Response:
{
"data": [...],
"total": 100,
"page": 2,
"limit": 25,
"totalPages": 4
}
Error Handling
All errors follow this format:
{
"error": {
"message": "Descriptive error message",
"statusCode": 400
}
}
Common error scenarios:
- Validation errors: Include field and reason
- Authentication errors: Include "No token provided" or "Invalid token"
- Authorization errors: "Insufficient permissions"
- Not found errors: "{Resource} not found"