> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fitsociety.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Get every programme's scheduled work for one date

> Everything the authenticated client's **multi-week calendar** programmes have scheduled on ONE date, plus the month dot grid that sits above the list.

`programmes[]` is a LIST because a client can be on several programmes at once — one entry per programme that actually has something on that date. A programme is OMITTED when it has nothing there (the date falls outside its span, or its calendar authors no day for that weekday), so `programmes.length` is the number of cards to render. A REST day is kept and flagged `day.isRestDay`, since an empty rest card is still meaningful.

Each `day.items[]` is produced by the same helper `GET /app/v1/workout/plans/client/template-with-progress/{templateId}` uses, so the item shape is identical between the two endpoints — including the nested `workout` summary with its `exercises`, and `activity` carrying what was logged.

`programmeMonthCalendar` is the same shape and helper the training page returns, for the month containing `date`, so the calendar needs no second request.

Switched-off (`Inactive`) programmes are INCLUDED, matching the month calendar this screen is opened from: a date that showed a dot there always resolves to a card here. Each entry carries `status` and `isActive` so the client can badge or blur a paused programme rather than the server hiding it. `Draft` plans are never returned.

Scoped to `mode: "multi_week"` + `layout: "calendar_week"`: a day's items need per-day dates and a schedule that authors them, and only that combination has both. `date` omitted → today in the company's timezone.

Requires the workout_calendar:read scope. This operation maps to /app/v1/workout/client/programme-day and retains its Workout V2 permission, feature-flag, and resource-scope checks.

The clientId path parameter identifies the client represented by the request context.



## OpenAPI

````yaml /openapi/public-v1.json get /public/v1/workout/clients/{clientId}/programme-day
openapi: 3.1.0
info:
  title: FITsociety Public API v1
  version: 1.0.0
  description: >-
    Developer Public API endpoints under `/public/v1`. This reference is
    filtered to OAuth/Bearer Public API resources and excludes provider callback
    receivers, storefront routes, public widgets, wishlist routes, and
    access-device validation endpoints.
  contact:
    name: FITsociety Engineering
servers:
  - url: https://api.fitsociety.io
    description: Production
security: []
tags:
  - name: Workout
    description: >-
      Workout V2 libraries, programmes, client plans, calendars, sessions,
      groups, settings and progress. AI operations are excluded.
  - name: OAuth
    description: Public API OAuth endpoints for server-to-server client credentials.
  - name: Health
    description: Public API token health checks.
  - name: Platform
    description: >-
      Inspect Public API client context, capabilities, scopes, and redacted
      audit logs.
  - name: Company Catalog
    description: Read and manage company profile metadata and locations.
  - name: Clients
    description: >-
      Create and manage clients through the Public API using Bearer access
      tokens.
  - name: Coaches
    description: Retrieve coaches for the authenticated company via integrations.
  - name: Calendar Events
    description: Read Public API calendar events.
  - name: Calendar Templates
    description: >-
      Read and manage event types and event templates used by calendar
      availability and bookings.
  - name: Calendar Extensions
    description: >-
      Read recurring bookings, booking requests, calendar tasks, and
      availability closure metadata.
  - name: Availability
    description: Read bookable availability slots and signed availability tokens.
  - name: Availability Management
    description: >-
      Manage coach and location availability templates used to derive bookable
      slots.
  - name: Bookings
    description: Read and manage Public API bookings.
  - name: Finance
    description: >-
      Read invoices, transactions, products, subscriptions, and memberships with
      guarded finance writes.
  - name: Credits
    description: >-
      Read company-wide and client-scoped credit allocations, mutations, and
      guarded credit adjustments.
  - name: Exports
    description: >-
      Create and monitor asynchronous company exports through Public API Bearer
      endpoints.
  - name: Webhooks
    description: >-
      Manage outbound webhook subscriptions and inspect delivery attempts
      through Public API Bearer endpoints.
  - name: Measurements
    description: Read and write client measurement entries.
  - name: Progress Photos
    description: Read client progress photo metadata and short-lived signed media URLs.
  - name: Forms
    description: Read, create, update, and archive company form templates.
  - name: Intakes
    description: Assign intake forms and read client intake assignments and submissions.
  - name: Check-ups
    description: >-
      Schedule and cancel client check-ups and read their status and
      submissions.
  - name: Documents
    description: >-
      Read client document and folder metadata, register external document
      links, update metadata, and archive documents from Public API listings.
      Binary upload, permanent deletion, and company-wide document management
      are not exposed.
  - name: Habits
    description: Read habits and habit entries.
  - name: Goals
    description: Read client goal summaries.
  - name: Conversations
    description: >-
      Read and manage direct and group chat conversations through the Public
      API.
  - name: Reports
    description: Read aggregate attendance, revenue, and retention summaries.
paths:
  /public/v1/workout/clients/{clientId}/programme-day:
    get:
      tags:
        - Workout
      summary: Get every programme's scheduled work for one date
      description: >-
        Everything the authenticated client's **multi-week calendar** programmes
        have scheduled on ONE date, plus the month dot grid that sits above the
        list.


        `programmes[]` is a LIST because a client can be on several programmes
        at once — one entry per programme that actually has something on that
        date. A programme is OMITTED when it has nothing there (the date falls
        outside its span, or its calendar authors no day for that weekday), so
        `programmes.length` is the number of cards to render. A REST day is kept
        and flagged `day.isRestDay`, since an empty rest card is still
        meaningful.


        Each `day.items[]` is produced by the same helper `GET
        /app/v1/workout/plans/client/template-with-progress/{templateId}` uses,
        so the item shape is identical between the two endpoints — including the
        nested `workout` summary with its `exercises`, and `activity` carrying
        what was logged.


        `programmeMonthCalendar` is the same shape and helper the training page
        returns, for the month containing `date`, so the calendar needs no
        second request.


        Switched-off (`Inactive`) programmes are INCLUDED, matching the month
        calendar this screen is opened from: a date that showed a dot there
        always resolves to a card here. Each entry carries `status` and
        `isActive` so the client can badge or blur a paused programme rather
        than the server hiding it. `Draft` plans are never returned.


        Scoped to `mode: "multi_week"` + `layout: "calendar_week"`: a day's
        items need per-day dates and a schedule that authors them, and only that
        combination has both. `date` omitted → today in the company's timezone.


        Requires the workout_calendar:read scope. This operation maps to
        /app/v1/workout/client/programme-day and retains its Workout V2
        permission, feature-flag, and resource-scope checks.


        The clientId path parameter identifies the client represented by the
        request context.
      operationId: publicWorkoutgetPublicV1WorkoutClientsClientIdProgrammeDay
      parameters:
        - in: query
          name: date
          required: false
          description: >-
            The day to load, canonical `YYYY-MM-DD`. Omit for today in the
            company's timezone.
          schema:
            type: string
            format: date
            pattern: ^\d{4}-\d{2}-\d{2}$
            example: '2026-09-22'
        - name: clientId
          in: path
          required: true
          schema:
            type: string
            pattern: ^[a-fA-F0-9]{24}$
          description: Client in the company bound to the Public API token.
      responses:
        '200':
          description: Every programme's work for the requested date.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PublicApiSuccessResponse'
                  - type: object
                    properties:
                      data:
                        $ref: >-
                          #/components/schemas/PublicWorkoutSourceGETAppV1WorkoutClientProgrammeDayResponse200
              examples:
                success:
                  summary: Successful response
                  value:
                    data:
                      date: '2026-09-22'
                      month: 2026-09
                      dayLabel: Tue
                      dayName: Tuesday
                      dayOfMonth: 22
                      isToday: true
                      programmeMonthCalendar:
                        month: 2026-09
                        monthLabel: September 2026
                        monthStart: '2026-09-01'
                        monthEnd: '2026-09-30'
                        gridStart: '2026-08-31'
                        gridEnd: '2026-10-04'
                        planIds:
                          - 67f1234567890abcdef1234
                        dates:
                          - date: '2026-09-22'
                            dayOfMonth: 22
                            weekday: 2
                            isCurrentMonth: true
                            isToday: true
                            isRestDay: false
                            itemCount: 3
                            statuses:
                              - completed
                              - in_process
                              - not_started
                      programmes:
                        - planId: 67f1234567890abcdef1234
                          name: Weekly Strength Program
                          thumbnail: https://cdn.example.com/plan.jpg
                          status: Active
                          weekNumber: 4
                          weekStartDate: '2026-09-21'
                          weekEndDate: '2026-09-27'
                          isWeekAvailable: true
                          planWeeks:
                            - weekNumber: 1
                              startDate: '2026-09-14'
                              endDate: '2026-09-20'
                              isSkipWeek: false
                              isCurrentWeek: true
                          day:
                            date: '2026-09-22'
                            weekday: 2
                            dayNumber: 4
                            isRestDay: false
                            itemCount: 3
                            items:
                              - _id: 67f1234567890abcdef1234
                                type: workout
                                order: 1
                                startTime: ''
                                plannedDurationMinutes: 60
                                status: completed
                                name: Upper Body
                                description: ''
                                activityType: running
                                targetDistanceMeters: 5000
                                planMomentId: 67f1234567890abcdef1234
                                workout:
                                  planMomentId: 67f1234567890abcdef1234
                                  name: Upper Body
                                  description: ''
                                  exerciseCount: 6
                                  exercises:
                                    - _id: 67f1234567890abcdef1234
                                      exerciseId: 67f1234567890abcdef1234
                                      exerciseName: Incline Dumbbell Press
                                      thumbnail: https://cdn.example.com/ex.jpg
                                      primaryMuscle: Chest
                                      equipment:
                                        - string
                                      sets: 4
                                      minReps: 8
                                      maxReps: 12
                                      rest: 90
                                      intensity: Medium
                                      difficulty: Intermediate
                                      notes: ''
                                      isFavourite: false
                                  progress:
                                    total: 6
                                    completed: 6
                                    progressPercentage: 100
                                    isCompleted: true
                                  sessionId: 67f1234567890abcdef1234
                                  sessionStatus: completed
                                  isCompleted: true
                                  scoring:
                                    scoringType: forTime
                                    descriptionOnly: true
                                    acceptsManualResult: true
                                    targetValue: null
                                    timeDomain:
                                      windowSeconds: null
                                      timeCapSeconds: 900
                                      rounds: 3
                                      intervalSeconds: null
                                      intervalCount: null
                                      workSeconds: null
                                      restSeconds: null
                                    scoreValidation:
                                      timeCapSeconds: 900
                                      maxReps: null
                                      expectedIntervals: null
                                    result:
                                      roundsCompleted: 5
                                      repsPerRound: 30
                                      extraReps: 12
                                      totalReps: 162
                                      intervalReps:
                                        - 12
                                        - 11
                                        - 10
                                      elapsedSeconds: 742
                                      finishedBeforeCap: true
                                      timeCapSeconds: 900
                                      maxLoadKg: 120
                                activity:
                                  performanceId: 67f1234567890abcdef1234
                                  status: in_progress
                                  startedAt: '2026-04-12T10:00:00.000Z'
                                  completedAt: '2026-04-12T10:00:00.000Z'
                                  actualDurationMinutes: 32
                                  actualDistanceMeters: 5100
                                  rpe: 7
                                  notes: ''
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 9
                        resetSeconds: 1
        '400':
          description: >-
            `COMPANY_ID_REQUIRED`, or a `date` that is not canonical
            `YYYY-MM-DD` (`INVALID_DATE_FORMAT`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
              examples:
                invalidRequest:
                  summary: Invalid request
                  value:
                    error:
                      code: 400
                      key: request.invalid
                      message: The request is invalid.
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 9
                        resetSeconds: 1
        '401':
          $ref: '#/components/schemas/ErrorResponse'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
              examples:
                missingBearer:
                  summary: Missing Bearer token
                  value:
                    error:
                      code: 401
                      key: auth.missing_bearer
                      message: Authorization Bearer token is required.
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 9
                        resetSeconds: 1
                invalidToken:
                  summary: Invalid or expired token
                  value:
                    error:
                      code: 401
                      key: auth.invalid_token
                      message: The access token is invalid or expired.
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 9
                        resetSeconds: 1
                invalidClient:
                  summary: Inactive or revoked client
                  value:
                    error:
                      code: 401
                      key: auth.invalid_client
                      message: The Public API client is inactive or revoked.
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 9
                        resetSeconds: 1
        '403':
          description: >-
            Workout V2 programme calendar is disabled for the active company
            (`WORKOUT_V2_PROGRAMME_CALENDAR_DISABLED`) or the caller lacks
            access.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
              examples:
                insufficientScopes:
                  summary: Missing required scope
                  value:
                    error:
                      code: 403
                      key: scopes.insufficient
                      message: The access token does not include the required scope.
                      details:
                        requiredScopes:
                          - required:scope
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 9
                        resetSeconds: 1
        '404':
          $ref: '#/components/schemas/ErrorResponse'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
              examples:
                notFound:
                  summary: Resource not found
                  value:
                    error:
                      code: 404
                      key: resource.not_found
                      message: The requested Public API resource was not found.
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 9
                        resetSeconds: 1
        '409':
          $ref: '#/components/schemas/ErrorResponse'
        '422':
          $ref: '#/components/schemas/ErrorResponse'
        '429':
          $ref: '#/components/schemas/ErrorResponse'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
              examples:
                rateLimitExceeded:
                  summary: Rate limit exceeded
                  value:
                    error:
                      code: 429
                      key: rate_limit.exceeded
                      message: Too many Public API requests. Retry later.
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 0
                        resetSeconds: 1
                        retryAfterSeconds: 1
        '500':
          description: Unexpected server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
              examples:
                serverInternalError:
                  summary: Unexpected server error
                  value:
                    error:
                      code: 500
                      key: server.internal_error
                      message: An unexpected Public API server error occurred.
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 9
                        resetSeconds: 1
      security:
        - PublicBearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: >-
            curl -X GET
            "https://api.fitsociety.io/public/v1/workout/clients/{clientId}/programme-day"
            \
              -H "Authorization: Bearer <access_token>"
components:
  schemas:
    PublicApiSuccessResponse:
      type: object
      additionalProperties: false
      required:
        - data
        - meta
      properties:
        data:
          type: object
        meta:
          $ref: '#/components/schemas/PublicApiMeta'
    PublicWorkoutSourceGETAppV1WorkoutClientProgrammeDayResponse200:
      type: object
      properties:
        date:
          type: string
          format: date
          pattern: ^\d{4}-\d{2}-\d{2}$
          example: '2026-09-22'
        month:
          type: string
          example: 2026-09
        dayLabel:
          type: string
          example: Tue
        dayName:
          type: string
          example: Tuesday
        dayOfMonth:
          type: integer
          nullable: true
          example: 22
        isToday:
          type: boolean
          example: true
        programmeMonthCalendar:
          type: object
          nullable: true
          description: >-
            The dot grid for the month containing `date` — same shape as the
            training page's field of the same name.
          properties:
            month:
              type: string
              example: 2026-09
            monthLabel:
              type: string
              example: September 2026
            monthStart:
              type: string
              format: date
              pattern: ^\d{4}-\d{2}-\d{2}$
              example: '2026-09-01'
            monthEnd:
              type: string
              format: date
              pattern: ^\d{4}-\d{2}-\d{2}$
              example: '2026-09-30'
            gridStart:
              type: string
              format: date
              pattern: ^\d{4}-\d{2}-\d{2}$
              example: '2026-08-31'
            gridEnd:
              type: string
              format: date
              pattern: ^\d{4}-\d{2}-\d{2}$
              example: '2026-10-04'
            planIds:
              type: array
              description: The programmes that contributed dots, oldest first.
              items:
                type: string
                example: 67f1234567890abcdef1234
            dates:
              type: array
              items:
                type: object
                properties:
                  date:
                    type: string
                    format: date
                    pattern: ^\d{4}-\d{2}-\d{2}$
                    example: '2026-09-22'
                  dayOfMonth:
                    type: integer
                    example: 22
                  weekday:
                    type: integer
                    minimum: 1
                    maximum: 7
                    example: 2
                  isCurrentMonth:
                    type: boolean
                    example: true
                    description: >-
                      False for the adjacent months' spill-over days in the
                      first and last rows.
                  isToday:
                    type: boolean
                    example: true
                  isRestDay:
                    type: boolean
                    example: false
                    description: True when ANY contributing programme rests that day.
                  itemCount:
                    type: integer
                    example: 3
                    description: >-
                      How many items this date actually holds, across every
                      programme. Unaffected by the de-duplication of `statuses`
                      below.
                  statuses:
                    type: array
                    description: >-
                      ONE entry per DISTINCT state, in first-seen order, across
                      ALL of the client's programmes — the grid shows a date's
                      states, not its item count, so three programmes each
                      finishing a workout that date render a single `completed`
                      dot while a mixed date still shows every state it holds. A
                      rest day is a single `rest`. Empty when nothing is
                      scheduled. Anything neither finished nor underway is
                      `not_started`. Use `itemCount` for how many items the date
                      actually has.
                    items:
                      type: string
                      enum:
                        - completed
                        - in_process
                        - not_started
                        - rest
                    example:
                      - completed
                      - in_process
                      - not_started
        programmes:
          type: array
          description: >-
            One entry per programme with something on this date, oldest
            programme first.
          items:
            type: object
            properties:
              planId:
                type: string
                example: 67f1234567890abcdef1234
              name:
                type: string
                example: Weekly Strength Program
              thumbnail:
                type: string
                example: https://cdn.example.com/plan.jpg
              status:
                type: string
                enum:
                  - Active
                  - Inactive
                example: Active
                description: >-
                  Whether this programme is switched on. `Inactive` cards ARE
                  returned — the month calendar already plots their dots, so
                  hiding them would leave a tappable date with nothing behind
                  it. Render the difference from this field; change it with
                  `PATCH
                  /app/v1/workout/plans/client/template/{templateId}/status`.
              weekNumber:
                type: integer
                minimum: 1
                example: 4
                description: Which programme week this date falls in.
              weekStartDate:
                type: string
                format: date
                pattern: ^\d{4}-\d{2}-\d{2}$
                example: '2026-09-21'
              weekEndDate:
                type: string
                format: date
                pattern: ^\d{4}-\d{2}-\d{2}$
                example: '2026-09-27'
              isWeekAvailable:
                type: boolean
                example: true
              planWeeks:
                type: array
                description: >-
                  Every week of this programme with its date span — the week
                  picker, the same shape and builder as
                  `trainingPlanAssignedSection[].planWeeks` on the training
                  page. `isCurrentWeek` is resolved against today, not the
                  requested date.
                items:
                  type: object
                  properties:
                    weekNumber:
                      type: integer
                      minimum: 1
                      example: 1
                    startDate:
                      type: string
                      format: date
                      pattern: ^\d{4}-\d{2}-\d{2}$
                      example: '2026-09-14'
                    endDate:
                      type: string
                      format: date
                      pattern: ^\d{4}-\d{2}-\d{2}$
                      example: '2026-09-20'
                    isSkipWeek:
                      type: boolean
                      example: false
                      description: >-
                        Whether the client skipped this whole week (Skip Week /
                        Resume Week). The week keeps its days and items; it just
                        renders as skipped.
                    isCurrentWeek:
                      type: boolean
                      example: true
                      description: >-
                        Whether today falls inside this week's span, in the
                        programme's own timezone. At most ONE entry is `true`;
                        none are once the programme is over or before it starts,
                        so do not assume a match exists. A week with no
                        resolvable `startDate` is never current; one with a
                        `startDate` but no `endDate` (a sequence-layout week) is
                        current from its start onwards.
              day:
                type: object
                properties:
                  date:
                    type: string
                    format: date
                    pattern: ^\d{4}-\d{2}-\d{2}$
                    example: '2026-09-22'
                  weekday:
                    type: integer
                    minimum: 1
                    maximum: 7
                    example: 2
                  dayNumber:
                    type: integer
                    nullable: true
                    example: 4
                    description: >-
                      The weekday slot within the programme week — the "Day 4"
                      in the card header, not the day of the month.
                  isRestDay:
                    type: boolean
                    example: false
                  itemCount:
                    type: integer
                    example: 3
                    description: The badge on the card.
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        _id:
                          type: string
                          example: 67f1234567890abcdef1234
                        type:
                          type: string
                          enum:
                            - workout
                            - activity
                          example: workout
                        order:
                          type: integer
                          example: 1
                        startTime:
                          type: string
                          example: ''
                          description: e.g. "10:45".
                        plannedDurationMinutes:
                          type: integer
                          nullable: true
                          example: 60
                        status:
                          type: string
                          nullable: true
                          enum:
                            - completed
                            - in_progress
                            - overdue
                            - today
                            - upcoming
                          example: completed
                          description: >-
                            The OCCURRENCE state for this date — not the
                            session's, which is `workout.sessionStatus`.
                        name:
                          type: string
                          example: Upper Body
                        description:
                          type: string
                          example: ''
                        activityType:
                          type: string
                          nullable: true
                          example: running
                          description: Activity items only; null on a workout item.
                        targetDistanceMeters:
                          type: integer
                          nullable: true
                          example: 5000
                        planMomentId:
                          type: string
                          example: 67f1234567890abcdef1234
                          nullable: true
                          description: Workout items only; null on an activity item.
                        workout:
                          type: object
                          nullable: true
                          description: >-
                            The plan day's own numbers, so a workout row needs
                            no join back to `days[]`. Null on an activity item.
                          properties:
                            planMomentId:
                              type: string
                              example: 67f1234567890abcdef1234
                            name:
                              type: string
                              example: Upper Body
                            description:
                              type: string
                              example: ''
                            exerciseCount:
                              type: integer
                              example: 6
                            exercises:
                              type: array
                              description: >-
                                The day's prescribed exercises — the same list
                                and shape as `days[].exercises`, so a week item
                                renders its exercise rows without joining back
                                to `days[]` (which is filtered to available
                                weeks and has nothing to find for a locked one).
                              items:
                                type: object
                                properties:
                                  _id:
                                    type: string
                                    example: 67f1234567890abcdef1234
                                  exerciseId:
                                    type: string
                                    example: 67f1234567890abcdef1234
                                  exerciseName:
                                    type: string
                                    example: Incline Dumbbell Press
                                  thumbnail:
                                    type: string
                                    example: https://cdn.example.com/ex.jpg
                                  primaryMuscle:
                                    type: string
                                    example: Chest
                                  equipment:
                                    type: array
                                    items:
                                      type: string
                                  sets:
                                    type: integer
                                    example: 4
                                  minReps:
                                    type: integer
                                    example: 8
                                  maxReps:
                                    type: integer
                                    example: 12
                                  rest:
                                    type: integer
                                    example: 90
                                  intensity:
                                    type: string
                                    example: Medium
                                  difficulty:
                                    type: string
                                    example: Intermediate
                                  notes:
                                    type: string
                                    example: ''
                                  isFavourite:
                                    type: boolean
                                    example: false
                            progress:
                              type: object
                              properties:
                                total:
                                  type: integer
                                  example: 6
                                completed:
                                  type: integer
                                  example: 6
                                progressPercentage:
                                  type: integer
                                  example: 100
                                isCompleted:
                                  type: boolean
                                  example: true
                            sessionId:
                              type: string
                              example: 67f1234567890abcdef1234
                              nullable: true
                            sessionStatus:
                              type: string
                              nullable: true
                              enum:
                                - in_progress
                                - paused
                                - completed
                              example: completed
                            isCompleted:
                              type: boolean
                              example: true
                            scoring:
                              type: object
                              nullable: true
                              description: >-
                                Scoring of a plan day. Null for an ordinary
                                standard day. `acceptsManualResult` is true only
                                for exercise-free scored days
                                (`descriptionOnly`), which take a `wodResult` on
                                PATCH
                                /app/v1/workout/performance/sessions/{sessionId}/complete.
                                `result` is the saved score of the selected
                                session, or null.
                              properties:
                                scoringType:
                                  type: string
                                  enum:
                                    - standard
                                    - forTime
                                    - amrap
                                    - emom
                                    - tabata
                                    - maxLoad
                                  example: forTime
                                descriptionOnly:
                                  type: boolean
                                  example: true
                                acceptsManualResult:
                                  type: boolean
                                  example: true
                                targetValue:
                                  type: number
                                  nullable: true
                                  example: null
                                timeDomain:
                                  type: object
                                  nullable: true
                                  description: >-
                                    Clock prescription, same contract as a WOD
                                    `timeDomain`. Allowed fields depend on
                                    `scoringType`: amrap → windowSeconds
                                    (required); forTime → timeCapSeconds, rounds
                                    (defaults to 1); emom → intervalSeconds,
                                    intervalCount (both required); tabata →
                                    workSeconds, restSeconds, intervalCount (all
                                    required); standard/maxLoad → none.
                                  properties:
                                    windowSeconds:
                                      type: integer
                                      nullable: true
                                      minimum: 1
                                      example: null
                                    timeCapSeconds:
                                      type: integer
                                      nullable: true
                                      minimum: 1
                                      example: 900
                                    rounds:
                                      type: integer
                                      nullable: true
                                      minimum: 1
                                      example: 3
                                    intervalSeconds:
                                      type: integer
                                      nullable: true
                                      minimum: 1
                                      example: null
                                    intervalCount:
                                      type: integer
                                      nullable: true
                                      minimum: 1
                                      example: null
                                    workSeconds:
                                      type: integer
                                      nullable: true
                                      minimum: 1
                                      example: null
                                    restSeconds:
                                      type: integer
                                      nullable: true
                                      minimum: 0
                                      example: null
                                scoreValidation:
                                  type: object
                                  nullable: true
                                  description: >-
                                    Optional result caps. timeCapSeconds and
                                    expectedIntervals are derived from
                                    `timeDomain` when one is set.
                                  properties:
                                    timeCapSeconds:
                                      type: integer
                                      nullable: true
                                      minimum: 1
                                      example: 900
                                    maxReps:
                                      type: integer
                                      nullable: true
                                      minimum: 1
                                      example: null
                                    expectedIntervals:
                                      type: integer
                                      nullable: true
                                      minimum: 1
                                      example: null
                                result:
                                  allOf:
                                    - type: object
                                      description: >-
                                        Type-specific manual score, the same
                                        shape as the WOD `wodResult`. Only the
                                        fields of the day's scoringType are
                                        accepted: amrap → roundsCompleted,
                                        repsPerRound, extraReps, totalReps
                                        (total = rounds × repsPerRound +
                                        extraReps, extraReps < repsPerRound);
                                        forTime → elapsedSeconds,
                                        finishedBeforeCap, totalReps (reps
                                        required when not finished before the
                                        cap); emom/tabata → intervalReps,
                                        totalReps (sum of intervals; count must
                                        match intervalCount when set); maxLoad →
                                        maxLoadKg. The stored copy of a forTime
                                        result also carries timeCapSeconds.
                                      properties:
                                        roundsCompleted:
                                          type: integer
                                          minimum: 0
                                          example: 5
                                        repsPerRound:
                                          type: integer
                                          minimum: 1
                                          example: 30
                                        extraReps:
                                          type: integer
                                          minimum: 0
                                          example: 12
                                        totalReps:
                                          type: integer
                                          minimum: 0
                                          example: 162
                                        intervalReps:
                                          type: array
                                          items:
                                            type: integer
                                            minimum: 0
                                          example:
                                            - 12
                                            - 11
                                            - 10
                                        elapsedSeconds:
                                          type: number
                                          minimum: 0
                                          example: 742
                                        finishedBeforeCap:
                                          type: boolean
                                          example: true
                                        timeCapSeconds:
                                          type: integer
                                          nullable: true
                                          readOnly: true
                                          example: 900
                                        maxLoadKg:
                                          type: number
                                          minimum: 0
                                          example: 120
                                  nullable: true
                        activity:
                          type: object
                          nullable: true
                          description: >-
                            What the client actually DID for this activity
                            occurrence; the planned values live on the item
                            itself. Null until logged, and always null on a
                            workout item.
                          properties:
                            performanceId:
                              type: string
                              example: 67f1234567890abcdef1234
                            status:
                              type: string
                              enum:
                                - in_progress
                                - completed
                                - cancelled
                              example: in_progress
                            startedAt:
                              type: string
                              format: date-time
                              example: '2026-04-12T10:00:00.000Z'
                              nullable: true
                            completedAt:
                              type: string
                              format: date-time
                              example: '2026-04-12T10:00:00.000Z'
                              nullable: true
                            actualDurationMinutes:
                              type: integer
                              nullable: true
                              example: 32
                            actualDistanceMeters:
                              type: integer
                              nullable: true
                              example: 5100
                            rpe:
                              type: integer
                              nullable: true
                              example: 7
                            notes:
                              type: string
                              example: ''
    PublicApiError:
      type: object
      additionalProperties: false
      required:
        - error
        - meta
      properties:
        error:
          type: object
          additionalProperties: false
          required:
            - code
            - key
            - message
          properties:
            code:
              type: integer
              example: 401
            key:
              type: string
              example: auth.invalid_token
            message:
              type: string
              example: The access token is invalid.
            details:
              type: object
              additionalProperties: true
        meta:
          $ref: '#/components/schemas/PublicApiMeta'
    ErrorResponse:
      allOf:
        - $ref: '#/components/schemas/StandardResponse'
        - example:
            status: 401
            error: true
            message: MISSING_AUTH
    PublicApiMeta:
      type: object
      additionalProperties: false
      required:
        - requestId
      properties:
        requestId:
          type: string
          description: Stable request correlation id. Mirrors `X-Request-Id` when supplied.
          example: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
        rateLimit:
          $ref: '#/components/schemas/PublicApiRateLimitMeta'
    StandardResponse:
      type: object
      properties:
        status:
          type: integer
          example: 200
        error:
          type: boolean
          example: false
        message:
          type: string
          example: SUCCESS
      required:
        - status
        - error
        - message
    PublicApiRateLimitMeta:
      type: object
      additionalProperties: false
      properties:
        limit:
          type: integer
          example: 10
        remaining:
          type: integer
          example: 9
        resetSeconds:
          type: integer
          description: Seconds until the current rate limit window resets.
          example: 1
        retryAfterSeconds:
          type: integer
          description: Present when the request was rate limited.
          example: 1
  securitySchemes:
    PublicBearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Opaque
      description: >-
        Public API access token issued by `/public/v1/oauth/token`. Example:
        `Authorization: Bearer fspt_...`. Each resource request rechecks the
        token company's current provider access. Disabling access blocks
        existing tokens with `403 auth.provider_unavailable`.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.