Skip to main content

Me

Overview

The Me module exposes the authenticated user's own profile, onboarding state, and personal game listings. All endpoints are scoped to the caller via JWT — no user ID is passed in the path.

Onboarding is handled by this module:

  • GET /api/v1/me — check hasCompletedOnboarding to decide whether to route the user to the onboarding screen.
  • POST /api/v1/me — complete the one-time onboarding by submitting the required profile fields.

The client checks onboarding status on every app launch via GET /api/v1/me and redirects incomplete users to the onboarding screen.

Profile Fields

FieldTypeValidationRemarks
namestringRequired, non-blank, max 200 characters
contactMethodsarray of ContactMethodAt least one valid contact method (whatsapp, telegram, or messenger), max 10 entries
skillLevelsarray of SkillLevelSelectionRequired, non-null, max 50 entries; at most one entry per activityEach entry pairs an activity with the user's skill level for that activity

ContactMethod

FieldTypeDescription
namestringOne of whatsapp, telegram, messenger
valuestringThe contact handle or number; must be non-blank

SkillLevelSelection

FieldTypeDescription
activityIdUUIDThe activity this selection applies to (see Activity)
skillLevelIdlongA skill level from GET /api/v1/skill-levels?activityId=... that belongs to activityId

Only one skill level per activity is allowed. Listing the same activityId twice returns 409 Conflict with error code DUPLICATE_SKILL_LEVEL_ACTIVITY.

API Contract

All endpoints are under /api/v1/me and require a valid JWT. Responses are wrapped in a standard ApiResponse envelope:

{
"success": true,
"data": { ... },
"message": "...",
"timestamp": "2026-04-04T12:00:00Z",
"path": "/api/v1/me"
}

GET /api/v1/me

Returns the current user profile and onboarding state. Called on every app launch.

cURL

curl -X GET http://localhost:8080/api/v1/me \
-H "Authorization: Bearer <TOKEN>"

Response 200 OK

{
"success": true,
"data": {
"userId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"authProvider": "auth0",
"providerUuid": "auth0|abc123",
"name": null,
"contactMethods": [],
"skillLevels": [],
"hasCompletedOnboarding": false,
"totalGamesJoined": 0,
"totalGamesHosted": 0,
"penaltyPoints": 0
},
"message": "User profile retrieved successfully.",
"timestamp": "2026-04-04T12:00:00Z",
"path": "/api/v1/me"
}
  • hasCompletedOnboarding: false — redirect to the onboarding screen.
  • hasCompletedOnboarding: true — proceed to the main app.

POST /api/v1/me

Completes the user profile. This is a one-time operation — calling it again after onboarding is complete returns 409 Conflict.

cURL

curl -X POST http://localhost:8080/api/v1/me \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Doe",
"contactMethods": [
{ "name": "whatsapp", "value": "+6591234567" },
{ "name": "telegram", "value": "@janedoe" }
],
"skillLevels": [
{ "activityId": "550e8400-e29b-41d4-a716-446655440000", "skillLevelId": 3 }
]
}'

Request body

{
"name": "Jane Doe",
"contactMethods": [
{ "name": "whatsapp", "value": "+6591234567" },
{ "name": "telegram", "value": "@janedoe" }
],
"skillLevels": [
{ "activityId": "550e8400-e29b-41d4-a716-446655440000", "skillLevelId": 3 }
]
}

Response 201 Created

{
"success": true,
"data": {
"userId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"authProvider": "auth0",
"providerUuid": "auth0|abc123",
"name": "Jane Doe",
"contactMethods": [
{ "name": "whatsapp", "value": "+6591234567" },
{ "name": "telegram", "value": "@janedoe" }
],
"skillLevels": [
{ "id": 3, "name": "High Beginner", "sortOrder": 3 }
],
"hasCompletedOnboarding": true,
"totalGamesJoined": 0,
"totalGamesHosted": 0,
"penaltyPoints": 0
},
"message": "User profile completed successfully.",
"timestamp": "2026-04-04T12:00:00Z",
"path": "/api/v1/me"
}

PUT /api/v1/me

Updates the authenticated user's profile. This endpoint uses patch semantics — only provided (non-null) fields are updated; omitted fields are left unchanged.

cURL

curl -X PUT http://localhost:8080/api/v1/me \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"name": "John Updated",
"contactMethods": [
{ "name": "whatsapp", "value": "+6587654321" }
],
"skillLevels": [
{ "activityId": "550e8400-e29b-41d4-a716-446655440000", "skillLevelId": 5 }
]
}'

Request body

{
"name": "John Updated",
"contactMethods": [
{ "name": "whatsapp", "value": "+6587654321" }
],
"skillLevels": [
{ "activityId": "550e8400-e29b-41d4-a716-446655440000", "skillLevelId": 5 }
]
}

All fields are optional — only include the fields you want to update.

FieldTypeDescription
namestringUpdated display name (max 200 chars)
contactMethodsarray of ContactMethodReplaces all contact methods (max 10 entries)
skillLevelsarray of SkillLevelSelectionReplaces all skill levels (max 50 entries; one per activity)

Response 200 OK

{
"success": true,
"data": {
"userId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"authProvider": "auth0",
"providerUuid": "auth0|abc123",
"name": "John Updated",
"contactMethods": [
{ "name": "whatsapp", "value": "+6587654321" }
],
"skillLevels": [
{ "id": 5, "name": "Middle Intermediate", "sortOrder": 5 }
],
"hasCompletedOnboarding": true,
"totalGamesJoined": 4,
"totalGamesHosted": 1,
"penaltyPoints": 0
},
"message": "User profile updated successfully.",
"timestamp": "2026-04-06T12:00:00Z",
"path": "/api/v1/me"
}

DELETE /api/v1/me

Permanently deletes the authenticated user's account and all associated data. This action is irreversible.

cURL

curl -X DELETE http://localhost:8080/api/v1/me \
-H "Authorization: Bearer <TOKEN>"

Response 204 No Content

No response body.

Me Games

Cursor-based listings scoped to the authenticated user. Both endpoints return CursorPagedResponse<GameResponse>, sorted by startTime ascending. See Game for the response shape.

GET /api/v1/me/games/joined

Games where the caller is an ACTIVE participant (excludes games they organise).

curl -X GET "http://localhost:8080/api/v1/me/games/joined?size=20" \
-H "Authorization: Bearer <TOKEN>"

GET /api/v1/me/games/hosted

Games where the caller is the organiser.

curl -X GET "http://localhost:8080/api/v1/me/games/hosted?size=20" \
-H "Authorization: Bearer <TOKEN>"

Query parameters (both endpoints)

ParameterTypeValidation
cursorstringOpaque cursor from a previous response
sizeinteger1..1000, default 20

Sequence Diagram

Happy Path

Already Completed

Duplicate Completion Attempt

Error Handling

ScenarioHTTP StatusError CodeClient Behavior
Missing or invalid required fields400Validation errorHighlight invalid fields, stay on screen
Profile already completed409PROFILE_ALREADY_COMPLETEDRedirect to main app
Multiple skill levels for same activity409DUPLICATE_SKILL_LEVEL_ACTIVITYCollapse selections; only one per activity
Skill level does not belong to its activity400Validation errorRe-fetch the activity's skill levels
Auth token expired / missing401Redirect to login
User not found (any endpoint)404Redirect to login
Server error500Show retry prompt

Implementation Notes

  • The client must call GET /api/v1/me on every cold start — never cache onboarding state locally, as it may be reset server-side.
  • Profile completion is a single atomic operation, not a multi-step flow. All required fields (name, contactMethods, skillLevels) must be submitted together.
  • Skill level selections are scoped per activity: each entry in skillLevels must pair an activityId with a skillLevelId that belongs to that activity, and each activity may appear at most once.
  • At least one contact method with a valid name (whatsapp, telegram, or messenger) and a non-blank value is required.
  • After completion, profile updates are done via PUT /api/v1/me (see API contract above). Only non-null fields are updated.
  • DELETE /api/v1/me permanently removes the user account — this action is irreversible.