RESTful API for managing user-generated content including games, videos, artwork, and music. Built with Flask, PostgreSQL, and JWT authentication.
Base URL: http://localhost:5000
API Version: v1
The API uses JWT (JSON Web Tokens) for authentication. Include the token in the Authorization header:
Authorization: Bearer <your_access_token>
Create a new user account.
Endpoint: POST /api/auth/register
Request Body:
{
"username": "john_doe",
"email": "john@example.com",
"password": "securepassword123"
}Response (201 Created):
{
"message": "User created successfully",
"user": {
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"username": "john_doe",
"email": "john@example.com",
"rating_count": 0,
"last_login": null,
"created_at": "2025-11-06T10:00:00Z"
},
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}Validation Rules:
username: 3-50 characters, uniqueemail: Valid email format, uniquepassword: Minimum 6 characters
Authenticate and receive an access token.
Endpoint: POST /api/auth/login
Request Body:
{
"username": "john_doe",
"password": "securepassword123"
}Response (200 OK):
{
"message": "Login successful",
"user": {
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"username": "john_doe",
"email": "john@example.com",
"rating_count": 5,
"last_login": "2025-11-06T10:00:00Z",
"created_at": "2025-11-05T08:00:00Z"
},
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}Get information about the currently logged-in user.
Endpoint: GET /api/auth/me
Headers: Authorization: Bearer <token>
Response (200 OK):
{
"user": {
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"username": "john_doe",
"email": "john@example.com",
"rating_count": 5,
"last_login": "2025-11-06T10:00:00Z",
"created_at": "2025-11-05T08:00:00Z"
}
}Upload new media content.
Endpoint: POST /api/content
Headers: Authorization: Bearer <token>
Request Body:
{
"title": "Epic Adventure Game",
"description": "An amazing open-world adventure game",
"category": "game",
"thumbnail_url": "https://example.com/thumb.jpg",
"content_url": "https://example.com/game.zip"
}Response (201 Created):
{
"message": "Content created successfully",
"content": {
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"title": "Epic Adventure Game",
"description": "An amazing open-world adventure game",
"category": "game",
"thumbnail_url": "https://example.com/thumb.jpg",
"content_url": "https://example.com/game.zip",
"created_at": "2025-11-06T10:30:00Z",
"updated_at": "2025-11-06T10:30:00Z",
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"creator": {
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"username": "john_doe"
},
"stats": {
"total_ratings": 0,
"average_rating": 0
}
}
}Valid Categories: game, video, artwork, music
Get all media content with optional filtering, pagination, and sorting.
Endpoint: GET /api/content
Query Parameters:
page(int): Page number (default: 1)per_page(int): Items per page (default: 10, max: 100)category(string): Filter by category (game|video|artwork|music)user_id(UUID): Filter by creatorsearch(string): Search in title and descriptionsort_by(string): Sort field (default: created_at)order(string): Sort order (asc|desc, default: desc)
Example Request:
GET /api/content?category=game&per_page=5&sort_by=created_at&order=desc
Response (200 OK):
{
"content": [
{
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"title": "Epic Adventure Game",
"description": "An amazing open-world adventure game",
"category": "game",
"thumbnail_url": "https://example.com/thumb.jpg",
"content_url": "https://example.com/game.zip",
"created_at": "2025-11-06T10:30:00Z",
"updated_at": "2025-11-06T10:30:00Z",
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"creator": {
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"username": "john_doe"
},
"stats": {
"total_ratings": 3,
"average_rating": 4.67
}
}
],
"pagination": {
"page": 1,
"per_page": 5,
"total_pages": 2,
"total_items": 7
}
}Get details of a specific media content item.
Endpoint: GET /api/content/<media_id>
Response (200 OK):
{
"content": {
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"title": "Epic Adventure Game",
"description": "An amazing open-world adventure game",
"category": "game",
"thumbnail_url": "https://example.com/thumb.jpg",
"content_url": "https://example.com/game.zip",
"created_at": "2025-11-06T10:30:00Z",
"updated_at": "2025-11-06T10:30:00Z",
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"creator": {
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"username": "john_doe"
},
"stats": {
"total_ratings": 3,
"average_rating": 4.67
}
}
}Update media content (only by creator).
Endpoint: PUT /api/content/<media_id>
Headers: Authorization: Bearer <token>
Request Body (all fields optional):
{
"title": "Epic Adventure Game - Updated",
"description": "Updated description",
"category": "game",
"thumbnail_url": "https://example.com/new-thumb.jpg",
"content_url": "https://example.com/updated-game.zip"
}Response (200 OK):
{
"message": "Content updated successfully",
"content": { /* updated content object */ }
}Delete media content (only by creator).
Endpoint: DELETE /api/content/<media_id>
Headers: Authorization: Bearer <token>
Response (200 OK):
{
"message": "Content deleted successfully"
}Get list of available media categories.
Endpoint: GET /api/content/categories
Response (200 OK):
{
"categories": ["game", "video", "artwork", "music"]
}Rate a media content item (1-5 stars).
Endpoint: POST /api/ratings
Headers: Authorization: Bearer <token>
Request Body:
{
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"score": 5,
"comment": "Amazing game! Highly recommended!"
}Response (201 Created):
{
"message": "Rating created successfully",
"rating": {
"rating_id": "456a7890-b12c-34d5-e678-901234567890",
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"score": 5,
"comment": "Amazing game! Highly recommended!",
"created_at": "2025-11-06T11:00:00Z",
"updated_at": "2025-11-06T11:00:00Z",
"user": {
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"username": "john_doe"
},
"media": {
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"title": "Epic Adventure Game",
"category": "game"
}
}
}Constraints:
- Score must be between 1 and 5
- One rating per user per content
- Cannot rate non-existent content
Get all ratings with optional filtering.
Endpoint: GET /api/ratings
Query Parameters:
media_id(UUID): Filter by media contentuser_id(UUID): Filter by userpage(int): Page number (default: 1)per_page(int): Items per page (default: 10, max: 100)
Example Request:
GET /api/ratings?media_id=987f6543-e21b-12d3-a456-426614174000
Response (200 OK):
{
"ratings": [
{
"rating_id": "456a7890-b12c-34d5-e678-901234567890",
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"score": 5,
"comment": "Amazing game!",
"created_at": "2025-11-06T11:00:00Z",
"updated_at": "2025-11-06T11:00:00Z",
"user": {
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"username": "john_doe"
},
"media": {
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"title": "Epic Adventure Game",
"category": "game"
}
}
],
"pagination": {
"page": 1,
"per_page": 10,
"total_pages": 1,
"total_items": 3
}
}Get details of a specific rating.
Endpoint: GET /api/ratings/<rating_id>
Response (200 OK):
{
"rating": {
"rating_id": "456a7890-b12c-34d5-e678-901234567890",
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"score": 5,
"comment": "Amazing game!",
"created_at": "2025-11-06T11:00:00Z",
"updated_at": "2025-11-06T11:00:00Z",
"user": {
"user_id": "123e4567-e89b-12d3-a456-426614174000",
"username": "john_doe"
},
"media": {
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"title": "Epic Adventure Game",
"category": "game"
}
}
}Update a rating (only by the user who created it).
Endpoint: PUT /api/ratings/<rating_id>
Headers: Authorization: Bearer <token>
Request Body (at least one field required):
{
"score": 4,
"comment": "Updated comment"
}Response (200 OK):
{
"message": "Rating updated successfully",
"rating": { /* updated rating object */ }
}Delete a rating (only by the user who created it).
Endpoint: DELETE /api/ratings/<rating_id>
Headers: Authorization: Bearer <token>
Response (200 OK):
{
"message": "Rating deleted successfully"
}Get statistics for a specific media content's ratings.
Endpoint: GET /api/ratings/media/<media_id>/stats
Response (200 OK):
{
"media_id": "987f6543-e21b-12d3-a456-426614174000",
"media_title": "Epic Adventure Game",
"stats": {
"total_ratings": 3,
"average_rating": 4.67,
"rating_distribution": {
"1": 0,
"2": 0,
"3": 0,
"4": 1,
"5": 2
}
}
}All errors follow a consistent format:
{
"error": "Error type",
"message": "Detailed error message"
}200 OK: Successful request201 Created: Resource created successfully400 Bad Request: Validation error or bad request401 Unauthorized: Missing or invalid authentication403 Forbidden: Authenticated but not authorized404 Not Found: Resource not found500 Internal Server Error: Server error
{
"error": "Validation failed",
"messages": {
"email": ["Not a valid email address."],
"password": ["Length must be at least 6."]
}
}{
"error": "Authorization required",
"message": "Please provide an access token"
}{
"error": "Forbidden: You can only update your own content"
}{
"error": "Content not found"
}curl -X POST http://localhost:5000/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"username": "game_developer",
"email": "dev@example.com",
"password": "securepass123"
}'curl -X POST http://localhost:5000/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"username": "game_developer",
"password": "securepass123"
}'Save the access_token from the response.
curl -X POST http://localhost:5000/api/content \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"title": "My Awesome Game",
"description": "A fun platformer game",
"category": "game",
"content_url": "https://example.com/game.zip"
}'curl -X GET "http://localhost:5000/api/content?category=game&per_page=10"curl -X POST http://localhost:5000/api/ratings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"media_id": "MEDIA_ID_FROM_STEP_3",
"score": 5,
"comment": "Excellent game!"
}'curl -X GET http://localhost:5000/api/ratings/media/MEDIA_ID/stats- Passwords: Hashed using Werkzeug's
generate_password_hash - JWT Tokens: Expire after 1 hour (configurable)
- HTTPS: Use HTTPS in production
- SQL Injection: Protected by SQLAlchemy ORM
- Input Validation: All inputs validated with Marshmallow schemas