# 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 ``` --- ## 1. Session Management ### Get Active Sessions ```http GET /sessions/me ``` **Response:** ```json [ { "cleaned_count": 2, "message": "Found 2 active sessions" } ] ``` ### Cleanup Expired Sessions ```http DELETE /sessions/cleanup ``` **Response:** ```json { "message": "Cleaned 5 expired sessions" } ``` ### Logout Current Session ```http POST /sessions/logout ``` **Response:** ```json { "message": "Logged out successfully" } ``` --- ## 2. Deck Versions ### Create Deck Version ```http POST /decks/{deck_id}/versions Content-Type: application/json { "content": "4x Thoughtseize, 4x Lightning Bolt, ...", "status": "DRAFT", "comment": "Updated for meta change" } ``` **Response:** ```json { "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 ```http GET /decks/{deck_id}/versions?page=1&page_size=50 ``` **Response:** ```json { "versions": [...], "total": 10, "page": 1, "page_size": 50, "total_pages": 1 } ``` ### Update Deck Version ```http PATCH /decks/{deck_id}/versions/{version_id} Content-Type: application/json { "status": "FINAL", "comment": "Ready for tournament" } ``` ### Delete Deck Version ```http DELETE /decks/{deck_id}/versions/{version_id} ``` --- ## 3. Game Replays ### Create Game Replay ```http 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:** ```json { "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 ```http GET /replays?page=1&page_size=50&user_id=42&status_filter=COMPLETED ``` **Response:** ```json { "replays": [...], "total": 100, "page": 1, "page_size": 50, "total_pages": 2 } ``` ### Get Replay Players ```http GET /replays/{replay_id}/players ``` **Response:** ```json [ { "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 ```http 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:** ```json { "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 ```http GET /outcomes?page=1&page_size=50&user_id=42 ``` --- ## 5. User Statistics ### Get User Statistics ```http GET /statistics/{user_id} ``` **Response:** ```json { "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 ```http POST /statistics/update Content-Type: application/json { "user_id": 42, "outcome": "WIN" } ``` **Response:** ```json { "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 ```http 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:** ```json { "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 ```http GET /collection?page=1&page_size=50&is_foil=true&is_alt_art=false ``` **Response:** ```json { "cards": [...], "total": 500, "page": 1, "page_size": 50, "total_pages": 10 } ``` ### Update Card in Collection ```http PATCH /collection/{card_id} Content-Type: application/json { "quantity": 3, "condition": "EX", "notes": "Slightly worn" } ``` ### Remove Card from Collection ```http DELETE /collection/{card_id} ``` --- ## 7. Wishlist ### Add to Wishlist ```http POST /wishlist Content-Type: application/json { "card_id": 12345, "max_price": 50.00, "notes": "Looking for foil version" } ``` **Response:** ```json { "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 ```http GET /wishlist?page=1&page_size=50 ``` ### Update Wishlist Item ```http PATCH /wishlist/{item_id} Content-Type: application/json { "max_price": 75.00, "notes": "Willing to pay more" } ``` ### Remove from Wishlist ```http DELETE /wishlist/{item_id} ``` --- ## 8. Groups ### Create Group ```http POST /groups Content-Type: application/json { "name": "Standard Players", "description": "Casual Standard players", "is_public": true, "max_members": 50 } ``` **Response:** ```json { "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 ```http GET /groups?page=1&page_size=50&is_public=true ``` **Response:** ```json { "groups": [...], "total": 5, "page": 1, "page_size": 50, "total_pages": 1 } ``` ### Update Group ```http PATCH /groups/{group_id} Content-Type: application/json { "description": "Updated description", "max_members": 100 } ``` ### Delete Group ```http DELETE /groups/{group_id} ``` --- ## 9. Group Members ### Add Group Member ```http POST /groups/{group_id}/members Content-Type: application/json { "user_id": 99, "role": "MEMBER" } ``` **Response:** ```json { "message": "Member added", "member_id": 5 } ``` ### Update Group Member Role ```http PATCH /groups/{group_id}/members/{member_id} Content-Type: application/json { "role": "ADMIN" } ``` **Response:** ```json { "message": "Member role updated" } ``` ### Remove Group Member ```http DELETE /groups/{group_id}/members/{member_id} ``` --- ## 10. Group Chat Messages ### Send Group Message ```http POST /groups/{group_id}/messages Content-Type: application/json { "message": "Hey everyone! Ready for a game?" } ``` **Response:** ```json { "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 ```http GET /groups/{group_id}/messages?page=1&page_size=50 ``` **Response:** ```json { "messages": [...], "total": 25, "page": 1, "page_size": 50, "total_pages": 1 } ``` --- ## 11. Networks ### Create Network ```http POST /networks Content-Type: application/json { "name": "MTG Enthusiasts", "description": "Friends who play Magic", "is_public": true } ``` **Response:** ```json { "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 ```http GET /networks?page=1&page_size=50 ``` ### Update Network ```http PATCH /networks/{network_id} Content-Type: application/json { "description": "Updated network description" } ``` ### Delete Network ```http DELETE /networks/{network_id} ``` --- ## 12. Network Members ### Add Network Member ```http POST /networks/{network_id}/members Content-Type: application/json { "user_id": 99, "role": "MEMBER" } ``` **Response:** ```json { "message": "Member added", "member_id": 3 } ``` --- ## 13. User Preferences ### Get User Preferences ```http GET /preferences ``` **Response:** ```json { "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 ```http PATCH /preferences Content-Type: application/json { "theme": "dark", "notifications_enabled": false, "default_format": "modern" } ``` **Response:** ```json { "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 ```http GET /activity?page=1&page_size=50&activity_type=LOGIN ``` **Response:** ```json { "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: ```json { "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 ```bash 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 ```bash curl "http://localhost:8000/api/v1/user-data/collection?page=1&page_size=10" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ### Example: Add to Wishlist ```bash 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 1. **Test endpoints** with curl or Postman 2. **Create integration tests** for each endpoint 3. **Add rate limiting** for production 4. **Implement pagination optimization** for large datasets 5. **Add search functionality** for cards and decks 6. **Create webhook endpoints** for real-time notifications