The Tennis Service API provides comprehensive endpoints for managing tennis-related data including user profiles, skills, games, grounds, locations, evaluations, and contacts. This service implements Domain-Driven Design (DDD) principles for better organization and maintainability.
Base URL: /api/tennis
All tennis service endpoints require authentication using JWT tokens. Include the token in the request headers:
textAuthorization: Bearer <your-jwt-token>
Tennis user profiles contain scheduling information and basic player details.
POST /api/tennis/profiles
Creates a new tennis user profile with availability schedule.
Request Body:
json{ "name": "John Tennis Player", "openTimes": [ { "day": "monday", "start": "09:00", "end": "17:00" }, { "day": "wednesday", "start": "10:00", "end": "16:00" }, { "day": "saturday", "start": "08:00", "end": "18:00" } ], "userId": 1 }
Response (201):
json{ "success": true, "data": { "id": 1, "name": "John Tennis Player", "openTimes": [...], "userId": 1, "createdAt": "2025-08-20T12:00:00.000Z", "updatedAt": "2025-08-20T12:00:00.000Z" } }
GET /api/tennis/profiles
Retrieves all tennis user profiles.
Response (200):
json{ "success": true, "data": [ { "id": 1, "name": "John Tennis Player", "openTimes": [...], "userId": 1, "createdAt": "2025-08-20T12:00:00.000Z", "updatedAt": "2025-08-20T12:00:00.000Z" } ] }
GET /api/tennis/profiles/:id
Parameters:
id (number): Profile IDResponse (200):
json{ "success": true, "data": { "id": 1, "name": "John Tennis Player", "openTimes": [...], "userId": 1 } }
GET /api/tennis/profiles/user/:userId
Parameters:
userId (number): User IDGET /api/tennis/profiles/exists/:userId
Parameters:
userId (number): User IDResponse (200):
json{ "success": true, "data": { "exists": true } }
GET /api/tennis/profiles/count
Response (200):
json{ "success": true, "data": { "count": 25 } }
PUT /api/tennis/profiles/:id
Parameters:
id (number): Profile IDRequest Body:
json{ "name": "Updated Tennis Player", "openTimes": [...] }
DELETE /api/tennis/profiles/:id
Parameters:
id (number): Profile IDManage contact information for tennis players.
POST /api/tennis/contacts
Request Body:
json{ "type": "EMAIL", "url": "player@example.com", "qrCode": "base64_encoded_qr_code_data", "userId": "1" }
Contact Types:
EMAIL - Email addressPHONE - Phone numberWECHAT - WeChat IDTIKTOK - TikTok handleINSTAGRAM - Instagram handleTWITTER - Twitter handlePUT /api/tennis/contacts/:id
Parameters:
id (number): Contact IDDELETE /api/tennis/contacts/:id
Parameters:
id (number): Contact IDManage tennis court locations.
POST /api/tennis/locations
Request Body:
json{ "name": "Central Tennis Court", "address": "123 Tennis St, City, State 12345", "latitude": 40.7128, "longitude": -74.0060 }
GET /api/tennis/locations
Response (200):
json{ "success": true, "data": [ { "id": 1, "name": "Central Tennis Court", "address": "123 Tennis St, City, State 12345", "latitude": 40.7128, "longitude": -74.0060, "createdAt": "2025-08-20T12:00:00.000Z" } ] }
GET /api/tennis/locations/:id
Parameters:
id (number): Location IDPUT /api/tennis/locations/:id
DELETE /api/tennis/locations/:id
Advanced skills management with DDD implementation.
FOREHAND - Forehand strokeBACKHAND - Backhand strokeSERVE - Serve techniqueRETURN - Return of serveNET_PLAY - Net play skillsEach skill is evaluated on four metrics (scale 1-10):
action - Technique executionstable - Consistencyspeed - Power/pacecontrol - Precision/placementPOST /api/tennis/skills
Creates a new skill or updates existing one for the user.
Request Body:
json{ "type": "FOREHAND", "action": 8, "stable": 7, "speed": 9, "control": 6, "userId": "1" }
Response (201):
json{ "success": true, "data": { "id": 1, "type": "FOREHAND", "action": 8, "stable": 7, "speed": 9, "control": 6, "userId": 1, "createdAt": "2025-08-20T12:00:00.000Z" } }
GET /api/tennis/skills
Query Parameters:
skip (number, optional): Records to skip for paginationtake (number, optional): Records to take for paginationGET /api/tennis/skills/statistics
Response (200):
json{ "success": true, "data": { "totalSkills": 150, "averageRatings": { "FOREHAND": 7.2, "BACKHAND": 6.8, "SERVE": 7.5, "RETURN": 6.9, "NET_PLAY": 6.5 }, "skillDistribution": { "FOREHAND": 32, "BACKHAND": 28, "SERVE": 31, "RETURN": 29, "NET_PLAY": 30 } } }
GET /api/tennis/skills/top-performers/:type
Parameters:
type (string): Skill type (FOREHAND, BACKHAND, SERVE, RETURN, NET_PLAY)Response (200):
json{ "success": true, "data": [ { "userId": 1, "averageScore": 8.5, "skillData": { "action": 9, "stable": 8, "speed": 9, "control": 8 } } ] }
GET /api/tennis/users/:userId/skills
Parameters:
userId (number): User IDQuery Parameters:
skip (number, optional): Records to skip for paginationtake (number, optional): Records to take for paginationGET /api/tennis/users/:userId/skills/:type
Parameters:
userId (number): User IDtype (string): Skill typeGET /api/tennis/users/:userId/skill-recommendations
Parameters:
userId (number): User IDResponse (200):
json{ "success": true, "data": { "recommendations": [ { "skillType": "BACKHAND", "currentLevel": 6.5, "targetLevel": 7.5, "suggestions": [ "Focus on follow-through technique", "Practice cross-court consistency" ] } ] } }
GET /api/tennis/skills/compare/:userAId/:userBId/:skillType
Parameters:
userAId (number): First user IDuserBId (number): Second user IDskillType (string): Skill type to compareResponse (200):
json{ "success": true, "data": { "userA": { "userId": 1, "skill": { "type": "FOREHAND", "action": 8, "stable": 7, "speed": 9, "control": 6 } }, "userB": { "userId": 2, "skill": { "type": "FOREHAND", "action": 7, "stable": 8, "speed": 8, "control": 7 } }, "comparison": { "winner": "userA", "strengths": { "userA": ["speed"], "userB": ["stable", "control"] } } } }
PUT /api/tennis/skills/:id
Parameters:
id (number): Skill IDDELETE /api/tennis/skills/:id
Parameters:
id (number): Skill IDManage tennis court facilities.
POST /api/tennis/tennis-grounds
Request Body:
json{ "name": "Court #1", "locationId": "1", "description": "Professional hard court with lighting", "facilities": { "lighting": true, "courtType": "hard", "covered": false, "restroom": true, "parking": true } }
GET /api/tennis/tennis-grounds
GET /api/tennis/tennis-grounds/:id
Parameters:
id (number): Tennis ground IDPUT /api/tennis/tennis-grounds/:id
DELETE /api/tennis/tennis-grounds/:id
Manage tennis game sessions and memberships.
PLANNED - Game is scheduledACTIVE - Game is in progressCOMPLETED - Game finishedCANCELLED - Game cancelledPOST /api/tennis/games
Request Body:
json{ "name": "Weekend Singles Match", "dmId": "1", "tennisGroundId": "1", "scheduledAt": "2025-08-25T14:00:00Z", "maxPlayers": 4, "description": "Friendly doubles match for intermediate players" }
Response (201):
json{ "success": true, "data": { "id": 1, "name": "Weekend Singles Match", "dmId": 1, "tennisGroundId": 1, "scheduledAt": "2025-08-25T14:00:00.000Z", "maxPlayers": 4, "status": "PLANNED", "description": "Friendly doubles match for intermediate players", "createdAt": "2025-08-20T12:00:00.000Z" } }
GET /api/tennis/games
GET /api/tennis/games/:id
Parameters:
id (number): Game IDPUT /api/tennis/games/:id
Request Body:
json{ "name": "Updated Game Name", "scheduledAt": "2025-08-26T15:00:00Z", "maxPlayers": 6, "status": "ACTIVE", "description": "Updated description" }
DELETE /api/tennis/games/:id
POST /api/tennis/games/join
Request Body:
json{ "gameId": "1", "userId": "2" }
Response (201):
json{ "success": true, "data": { "id": 1, "gameId": 1, "userId": 2, "status": "PENDING", "joinedAt": "2025-08-20T12:00:00.000Z" } }
PUT /api/tennis/game-members/:id
Parameters:
id (number): Game member IDRequest Body:
json{ "status": "CONFIRMED" }
Member Status Types:
PENDING - Waiting for confirmationCONFIRMED - Confirmed participationDECLINED - Declined participationDELETE /api/tennis/games/:gameId/leave
Parameters:
gameId (number): Game IDAdvanced evaluation system for tennis skills with domain-driven design.
POST /api/tennis/evaluations
Request Body:
json{ "userId": "1", "evaluatorId": "2", "skills": [ { "type": "FOREHAND", "action": 8, "stable": 7, "speed": 9, "control": 6 }, { "type": "BACKHAND", "action": 7, "stable": 8, "speed": 7, "control": 8 }, { "type": "SERVE", "action": 9, "stable": 6, "speed": 10, "control": 7 } ] }
Response (201):
json{ "success": true, "data": { "id": 1, "userId": 1, "evaluatorId": 2, "evaluationDate": "2025-08-20T12:00:00.000Z", "skills": [...] }, "warnings": [ "Serve speed score is exceptionally high, please verify" ] }
GET /api/tennis/evaluations/:id
Parameters:
id (number): Evaluation IDGET /api/tennis/evaluations/user/:userId
Parameters:
userId (number): User IDGET /api/tennis/evaluations/evaluator/:evaluatorId
Parameters:
evaluatorId (number): Evaluator IDGET /api/tennis/evaluations/user/:userId/latest
Parameters:
userId (number): User IDGET /api/tennis/evaluations/user/:userId/statistics
Parameters:
userId (number): User IDResponse (200):
json{ "success": true, "data": { "totalEvaluations": 5, "averageScores": { "FOREHAND": 7.8, "BACKHAND": 7.2, "SERVE": 8.1, "RETURN": 6.9, "NET_PLAY": 7.0 }, "improvementTrends": { "FOREHAND": "+0.5", "BACKHAND": "+1.2", "SERVE": "+0.3", "RETURN": "+0.8", "NET_PLAY": "+1.0" }, "lastEvaluationDate": "2025-08-15T12:00:00.000Z" } }
GET /api/tennis/evaluations/user/:userId/summary
Parameters:
userId (number): User IDGET /api/tennis/evaluations/user/:userId/history
Parameters:
userId (number): User IDGET /api/tennis/evaluations/skill/:skillType
Parameters:
skillType (string): Skill typePOST /api/tennis/evaluations/user/:userId/compare
Parameters:
userId (number): User IDRequest Body:
json{ "evaluationId1": 1, "evaluationId2": 2 }
POST /api/tennis/evaluations/validate
Request Body:
json{ "userId": "1", "skills": [ { "type": "FOREHAND", "action": 12, "stable": 7, "speed": 9, "control": 6 } ] }
Response (200):
json{ "success": true, "data": { "isValid": false, "errors": [ "Action score for FOREHAND exceeds maximum value of 10" ], "warnings": [ "Consider reviewing action score as it's unusually high" ] } }
DELETE /api/tennis/evaluations/:id
Parameters:
id (number): Evaluation IDAll tennis service responses follow a consistent format:
json{ "success": true, "data": { // Response data } }
json{ "success": true, "data": { // Response data }, "warnings": [ "Warning message" ] }
json{ "success": false, "error": "Error message" }
json{ "success": false, "message": "Validation error message" }
400 Bad Request - Missing Required Fields:
json{ "success": false, "message": "Name, openTimes, and userId are required" }
400 Bad Request - Invalid Skill Data:
json{ "success": false, "error": "User ID and skills array are required" }
404 Not Found:
json{ "success": false, "message": "User profile not found" }
500 Internal Server Error:
json{ "success": false, "error": "Internal server error" }
Currently no rate limiting is implemented, but it's recommended for production environments.
The Tennis service follows DDD principles:
This architecture ensures separation of concerns, testability, and maintainability of the tennis service domain.