- Add Alembic migration setup with async configuration - Create 16 user data models (users, decks, cards, replays, etc.) - Implement comprehensive API endpoints with JWT auth - Add replay, card collection, group, network, preferences, and activity log routers - Include API documentation and migration test plan - Update Dockerfile to run migrations on startup
15 KiB
15 KiB
User Data API Endpoints - Complete Documentation
Overview
The User Data API provides comprehensive CRUD operations for:
- Session Management - User authentication sessions
- Deck Versions - Deck version history and rollback
- Game Replays - Game recording and playback
- Game Outcomes - Win/loss tracking with ratings
- User Statistics - Denormalized stats (games, wins, streaks)
- Card Collection - User-owned cards with condition/language
- Wishlist - Cards users want to acquire
- Groups - User groups with roles and chat
- Networks - Extended social connections
- Preferences - User settings and preferences
- Activity Log - Audit trail with JSONB metadata
Base URL
/api/v1/user-data
Authentication
All endpoints require a valid JWT token in the Authorization header:
Authorization: Bearer <your-jwt-token>
1. Session Management
Get Active Sessions
GET /sessions/me
Response:
[
{
"cleaned_count": 2,
"message": "Found 2 active sessions"
}
]
Cleanup Expired Sessions
DELETE /sessions/cleanup
Response:
{
"message": "Cleaned 5 expired sessions"
}
Logout Current Session
POST /sessions/logout
Response:
{
"message": "Logged out successfully"
}
2. Deck Versions
Create Deck Version
POST /decks/{deck_id}/versions
Content-Type: application/json
{
"content": "4x Thoughtseize, 4x Lightning Bolt, ...",
"status": "DRAFT",
"comment": "Updated for meta change"
}
Response:
{
"id": 1,
"deck_id": 42,
"version_number": 3,
"content": "4x Thoughtseize, ...",
"status": "DRAFT",
"comment": "Updated for meta change",
"created_at": "2026-01-01T12:00:00Z"
}
Get Deck Versions
GET /decks/{deck_id}/versions?page=1&page_size=50
Response:
{
"versions": [...],
"total": 10,
"page": 1,
"page_size": 50,
"total_pages": 1
}
Update Deck Version
PATCH /decks/{deck_id}/versions/{version_id}
Content-Type: application/json
{
"status": "FINAL",
"comment": "Ready for tournament"
}
Delete Deck Version
DELETE /decks/{deck_id}/versions/{version_id}
3. Game Replays
Create Game Replay
POST /replays
Content-Type: application/json
{
"game_uuid": "550e8400-e29b-41d4-a716-446655440000",
"room_id": 1,
"game_type": "Draft",
"format": "Standard",
"duration_seconds": 1800,
"start_time": "2026-01-01T12:00:00Z",
"end_time": "2026-01-01T12:30:00Z",
"status": "COMPLETED",
"replay_data": {
"turns": [...],
"deck": {...}
}
}
Response:
{
"id": 1,
"game_uuid": "550e8400-...",
"room_id": 1,
"game_type": "Draft",
"format": "Standard",
"duration_seconds": 1800,
"start_time": "2026-01-01T12:00:00Z",
"end_time": "2026-01-01T12:30:00Z",
"status": "COMPLETED",
"replay_data": {...},
"created_at": "2026-01-01T12:30:00Z",
"updated_at": "2026-01-01T12:30:00Z",
"players": [...]
}
Get Game Replays
GET /replays?page=1&page_size=50&user_id=42&status_filter=COMPLETED
Response:
{
"replays": [...],
"total": 100,
"page": 1,
"page_size": 50,
"total_pages": 2
}
Get Replay Players
GET /replays/{replay_id}/players
Response:
[
{
"id": 1,
"user_id": 42,
"deck_id": 10,
"position": 1,
"won": true,
"lost": false,
"concession": false,
"turn_one": false
}
]
4. Game Outcomes
Create Game Outcome
POST /outcomes
Content-Type: application/json
{
"game_uuid": "550e8400-e29b-41d4-a716-446655440000",
"outcome": "WIN",
"opponent_id": 99,
"format": "Standard",
"rating_before": 1500,
"rating_after": 1525,
"rating_change": 25
}
Response:
{
"id": 1,
"user_id": 42,
"game_uuid": "550e8400-...",
"outcome": "WIN",
"opponent_id": 99,
"format": "Standard",
"rating_before": 1500,
"rating_after": 1525,
"rating_change": 25,
"created_at": "2026-01-01T12:30:00Z"
}
Get Game Outcomes
GET /outcomes?page=1&page_size=50&user_id=42
5. User Statistics
Get User Statistics
GET /statistics/{user_id}
Response:
{
"user_id": 42,
"total_games": 150,
"total_wins": 90,
"total_losses": 55,
"total_concessions": 5,
"win_rate": 60.0,
"current_streak": 3,
"best_streak": 8,
"average_rating": 1450.5,
"last_game_date": "2026-01-01T12:00:00Z",
"updated_at": "2026-01-01T12:30:00Z"
}
Update User Statistics
POST /statistics/update
Content-Type: application/json
{
"user_id": 42,
"outcome": "WIN"
}
Response:
{
"user_id": 42,
"total_games": 151,
"total_wins": 91,
"total_losses": 55,
"win_rate": 60.26,
"current_streak": 4,
"updated_at": "2026-01-01T12:35:00Z"
}
6. Card Collection
Add Card to Collection
POST /collection
Content-Type: application/json
{
"card_id": 12345,
"quantity": 4,
"condition": "NEAR_MINT",
"language": "EN",
"is_foil": true,
"is_alt_art": false,
"acquired_date": "2026-01-01T00:00:00Z",
"acquisition_method": "Bought",
"notes": "From card shop"
}
Response:
{
"id": 1,
"user_id": 42,
"card_id": 12345,
"quantity": 4,
"condition": "NEAR_MINT",
"language": "EN",
"is_foil": true,
"is_alt_art": false,
"acquired_date": "2026-01-01T00:00:00Z",
"acquisition_method": "Bought",
"notes": "From card shop",
"created_at": "2026-01-01T12:00:00Z",
"updated_at": "2026-01-01T12:00:00Z"
}
Get Card Collection
GET /collection?page=1&page_size=50&is_foil=true&is_alt_art=false
Response:
{
"cards": [...],
"total": 500,
"page": 1,
"page_size": 50,
"total_pages": 10
}
Update Card in Collection
PATCH /collection/{card_id}
Content-Type: application/json
{
"quantity": 3,
"condition": "EX",
"notes": "Slightly worn"
}
Remove Card from Collection
DELETE /collection/{card_id}
7. Wishlist
Add to Wishlist
POST /wishlist
Content-Type: application/json
{
"card_id": 12345,
"max_price": 50.00,
"notes": "Looking for foil version"
}
Response:
{
"id": 1,
"user_id": 42,
"card_id": 12345,
"max_price": 50.00,
"notes": "Looking for foil version",
"created_at": "2026-01-01T12:00:00Z"
}
Get Wishlist
GET /wishlist?page=1&page_size=50
Update Wishlist Item
PATCH /wishlist/{item_id}
Content-Type: application/json
{
"max_price": 75.00,
"notes": "Willing to pay more"
}
Remove from Wishlist
DELETE /wishlist/{item_id}
8. Groups
Create Group
POST /groups
Content-Type: application/json
{
"name": "Standard Players",
"description": "Casual Standard players",
"is_public": true,
"max_members": 50
}
Response:
{
"id": 1,
"name": "Standard Players",
"description": "Casual Standard players",
"owner_id": 42,
"is_public": true,
"max_members": 50,
"created_at": "2026-01-01T12:00:00Z",
"updated_at": "2026-01-01T12:00:00Z",
"member_count": 1,
"is_member": true
}
Get User Groups
GET /groups?page=1&page_size=50&is_public=true
Response:
{
"groups": [...],
"total": 5,
"page": 1,
"page_size": 50,
"total_pages": 1
}
Update Group
PATCH /groups/{group_id}
Content-Type: application/json
{
"description": "Updated description",
"max_members": 100
}
Delete Group
DELETE /groups/{group_id}
9. Group Members
Add Group Member
POST /groups/{group_id}/members
Content-Type: application/json
{
"user_id": 99,
"role": "MEMBER"
}
Response:
{
"message": "Member added",
"member_id": 5
}
Update Group Member Role
PATCH /groups/{group_id}/members/{member_id}
Content-Type: application/json
{
"role": "ADMIN"
}
Response:
{
"message": "Member role updated"
}
Remove Group Member
DELETE /groups/{group_id}/members/{member_id}
10. Group Chat Messages
Send Group Message
POST /groups/{group_id}/messages
Content-Type: application/json
{
"message": "Hey everyone! Ready for a game?"
}
Response:
{
"id": 1,
"group_id": 1,
"sender_id": 42,
"sender_username": "player42",
"message": "Hey everyone! Ready for a game?",
"created_at": "2026-01-01T12:00:00Z"
}
Get Group Messages
GET /groups/{group_id}/messages?page=1&page_size=50
Response:
{
"messages": [...],
"total": 25,
"page": 1,
"page_size": 50,
"total_pages": 1
}
11. Networks
Create Network
POST /networks
Content-Type: application/json
{
"name": "MTG Enthusiasts",
"description": "Friends who play Magic",
"is_public": true
}
Response:
{
"id": 1,
"name": "MTG Enthusiasts",
"description": "Friends who play Magic",
"creator_id": 42,
"is_public": true,
"created_at": "2026-01-01T12:00:00Z",
"member_count": 1,
"is_member": true
}
Get User Networks
GET /networks?page=1&page_size=50
Update Network
PATCH /networks/{network_id}
Content-Type: application/json
{
"description": "Updated network description"
}
Delete Network
DELETE /networks/{network_id}
12. Network Members
Add Network Member
POST /networks/{network_id}/members
Content-Type: application/json
{
"user_id": 99,
"role": "MEMBER"
}
Response:
{
"message": "Member added",
"member_id": 3
}
13. User Preferences
Get User Preferences
GET /preferences
Response:
{
"user_id": 42,
"theme": "light",
"notifications_enabled": true,
"email_notifications": true,
"auto_save_decks": true,
"default_format": "standard",
"language": "EN",
"updated_at": "2026-01-01T12:00:00Z"
}
Update User Preferences
PATCH /preferences
Content-Type: application/json
{
"theme": "dark",
"notifications_enabled": false,
"default_format": "modern"
}
Response:
{
"user_id": 42,
"theme": "dark",
"notifications_enabled": false,
"email_notifications": true,
"auto_save_decks": true,
"default_format": "modern",
"language": "EN",
"updated_at": "2026-01-01T12:05:00Z"
}
14. Activity Log
Get Activity Log
GET /activity?page=1&page_size=50&activity_type=LOGIN
Response:
{
"entries": [
{
"id": 1,
"user_id": 42,
"activity_type": "LOGIN",
"activity_data": {"ip": "192.168.1.1"},
"ip_address": "192.168.1.1",
"created_at": "2026-01-01T12:00:00Z"
}
],
"total": 100,
"page": 1,
"page_size": 50,
"total_pages": 2
}
Error Responses
All endpoints return consistent error responses:
{
"detail": "Error message"
}
Common Error Codes
| Status Code | Description |
|---|---|
| 400 | Bad Request - Invalid input |
| 401 | Unauthorized - Missing or invalid token |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Resource doesn't exist |
| 409 | Conflict - Resource already exists |
| 500 | Internal Server Error |
Testing with cURL
Example: Create a Deck Version
curl -X POST "http://localhost:8000/api/v1/user-data/decks/42/versions" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": "4x Thoughtseize, 4x Lightning Bolt, ...",
"status": "DRAFT",
"comment": "Updated for meta"
}'
Example: Get Card Collection
curl "http://localhost:8000/api/v1/user-data/collection?page=1&page_size=10" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Example: Add to Wishlist
curl -X POST "http://localhost:8000/api/v1/user-data/wishlist" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"card_id": 12345,
"max_price": 50.00,
"notes": "Looking for foil"
}'
Available Endpoints Summary
| Method | Endpoint | Description |
|---|---|---|
| GET | /sessions/me |
Get active sessions |
| DELETE | /sessions/cleanup |
Cleanup expired sessions |
| POST | /sessions/logout |
Logout current session |
| POST | /decks/{id}/versions |
Create deck version |
| GET | /decks/{id}/versions |
Get deck versions |
| PATCH | /decks/{id}/versions/{vid} |
Update deck version |
| DELETE | /decks/{id}/versions/{vid} |
Delete deck version |
| POST | /replays |
Create game replay |
| GET | /replays |
Get game replays |
| GET | /replays/{id} |
Get specific replay |
| PATCH | /replays/{id} |
Update replay |
| DELETE | /replays/{id} |
Delete replay |
| POST | /replays/{id}/players |
Add player to replay |
| GET | /replays/{id}/players |
Get replay players |
| POST | /outcomes |
Create game outcome |
| GET | /outcomes |
Get game outcomes |
| GET | /statistics/{id} |
Get user statistics |
| POST | /statistics/update |
Update user statistics |
| POST | /collection |
Add card to collection |
| GET | /collection |
Get card collection |
| PATCH | /collection/{id} |
Update card |
| DELETE | /collection/{id} |
Remove card |
| POST | /wishlist |
Add to wishlist |
| GET | /wishlist |
Get wishlist |
| PATCH | /wishlist/{id} |
Update wishlist item |
| DELETE | /wishlist/{id} |
Remove from wishlist |
| POST | /groups |
Create group |
| GET | /groups |
Get user groups |
| GET | /groups/{id} |
Get specific group |
| PATCH | /groups/{id} |
Update group |
| DELETE | /groups/{id} |
Delete group |
| POST | /groups/{id}/members |
Add group member |
| PATCH | /groups/{id}/members/{mid} |
Update member role |
| DELETE | /groups/{id}/members/{mid} |
Remove member |
| POST | /groups/{id}/messages |
Send group message |
| GET | /groups/{id}/messages |
Get group messages |
| POST | /networks |
Create network |
| GET | /networks |
Get user networks |
| GET | /networks/{id} |
Get specific network |
| PATCH | /networks/{id} |
Update network |
| DELETE | /networks/{id} |
Delete network |
| POST | /networks/{id}/members |
Add network member |
| GET | /preferences |
Get user preferences |
| PATCH | /preferences |
Update preferences |
| GET | /activity |
Get activity log |
Next Steps
- Test endpoints with curl or Postman
- Create integration tests for each endpoint
- Add rate limiting for production
- Implement pagination optimization for large datasets
- Add search functionality for cards and decks
- Create webhook endpoints for real-time notifications