Skip to main content

Challenge Plays API

GET /api/challenge-plays

List all challenge plays for the authenticated client/user, with support for pagination, filtering, and sorting.

Query Parameters

  • clientId: string (required) — The client identifier. If not found, a 500 error is returned.
  • page: number (optional, default: 1) — The page number (1-based).
  • pageSize: number (optional, default: 20, max: 100) — Number of results per page.
  • sortBy: string (optional, default: createdAt) — Field to sort by (e.g., createdAt).
  • sortOrder: string (optional, default: desc) — Sort order: asc or desc.
  • userId: string (optional) — Filter by user ID.
  • challengeId: string (optional) — Filter by challenge ID.
  • startAfter: any (optional) — Cursor value for pagination (use the value of the sortBy field from the last item of the previous page).

Headers:

  • Authorization: Bearer <JWT>

Response

  • 200 OK:

    Success Response
    {
    "data": [ChallengePlay, ...],
    "page": number,
    "pageSize": number,
    "hasMore": boolean,
    "nextPageToken": any
    }
  • 401 Unauthorized: { "error": string }

  • 500 Internal Server Error: { "error": "Client ID not found" | string }

  • 500 Firestore index required: { "error": "Firestore index required", "details": string }

note

Use nextPageToken as the startAfter value for the next page request.
Filtering and sorting combinations may require Firestore composite indexes. If an index is missing, the error response will include a link to create it.


POST /api/challenge-plays

Create a new challenge play record for a user or guest.

Query Parameters

  • clientId: string (required) — The client identifier. If not found, a 500 error is returned.

Headers:

  • Authorization: Bearer <JWT>

Request Body:

Request Body
{
"challengeId": "string", // Required. The challenge ID
"userId": "string", // Optional. User's ID
"email": "string", // Optional. User's email
"displayName": "string", // Optional. User's display name
"photoURL": "string", // Optional. User's profile photo URL
"targetRepCount": 50, // Optional. Target repetitions
"targetDuration": 60 // Optional. Target duration (seconds)
}

Response

  • 200 OK:

    Success Response
    {
    "challengePlayId": "string", // Unique ID for the challenge play
    "redirectUrl": "string", // URL to redirect the user to the challenge play
    "createdAt": "string" // ISO date of creation
    }
  • 400 Bad Request: { "error": "string" }

  • 500 Internal Server Error: { "error": "string" }


ChallengePlay Object (for reference)

  • id: string — Unique challenge play ID
  • clientId: string — Client ID
  • userId: string (optional) — User ID
  • challengeId: string — Challenge ID
  • createdAt: string — ISO date
  • completedAt: string (optional, nullable) — ISO date
  • activityTime: number (optional) — Seconds spent in activity
  • repCount: number (optional) — Number of reps completed
  • grade: string (optional) — Grade achieved
  • targetRepCount: number (optional) — Target reps (Time Attack)
  • targetDuration: number (optional) — Target duration in seconds (Endurance)
  • caloriesBurned: number (optional)
  • email: string (optional)
  • displayName: string (optional)
  • photoURL: string (optional)
  • status: string (optional) — pending, started, completed, cancelled
Sample ChallengePlay Object
{
"id": "play123",
"clientId": "gofa",
"userId": "user456",
"challengeId": "challenge123",
"createdAt": "2024-05-25T10:00:00.000Z",
"completedAt": null,
"activityTime": 60,
"repCount": 50,
"grade": "S",
"targetRepCount": 50,
"targetDuration": 60,
"caloriesBurned": 25,
"email": "user@example.com",
"displayName": "User Name",
"photoURL": "https://example.com/photo.jpg",
"status": "completed"
}

note

Requires a valid JWT for the client.
Validates challenge and user existence.
The actual schema may include additional fields. For the most up-to-date schema, refer to the challenge play model/interface in your codebase.
All fields may not be present on every challenge play. Optional and nullable fields are indicated above.