> ## 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 the client's merged programme calendar week

> Returns exactly seven company-local Monday-through-Sunday days for the authenticated client. Active assigned calendar programmes are merged without accepting client or company scope overrides. Recurring programmes repeat their authored week; multi-week programmes expose only the authored week matching `selectedWeekStart`. Plans outside their assignment range are omitted. Future programme weeks remain visible with `isAvailable: false`. Rest is plan-day metadata, so one plan's rest day can coexist with another plan's items.

Requires the workout_calendar:read scope. This operation maps to /app/v1/workout/client/programme-calendar 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-calendar
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-calendar:
    get:
      tags:
        - Workout
      summary: Get the client's merged programme calendar week
      description: >-
        Returns exactly seven company-local Monday-through-Sunday days for the
        authenticated client. Active assigned calendar programmes are merged
        without accepting client or company scope overrides. Recurring
        programmes repeat their authored week; multi-week programmes expose only
        the authored week matching `selectedWeekStart`. Plans outside their
        assignment range are omitted. Future programme weeks remain visible with
        `isAvailable: false`. Rest is plan-day metadata, so one plan's rest day
        can coexist with another plan's items.


        Requires the workout_calendar:read scope. This operation maps to
        /app/v1/workout/client/programme-calendar 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: publicWorkoutgetPublicV1WorkoutClientsClientIdProgrammeCalendar
      parameters:
        - in: query
          name: selectedWeekStart
          required: false
          description: >-
            Canonical company-local Monday for the requested programme week or
            recurring cycle. Omit to use the current company-local week.
          schema:
            type: string
            format: date
            pattern: ^\d{4}-\d{2}-\d{2}$
            example: '2026-09-14'
        - 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: Merged client programme calendar week.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PublicApiSuccessResponse'
                  - type: object
                    properties:
                      data:
                        $ref: >-
                          #/components/schemas/PublicWorkoutSourceGETAppV1WorkoutClientProgrammeCalendarResponse200
              examples:
                success:
                  summary: Successful response
                  value:
                    data:
                      timeZone: Europe/Amsterdam
                      selectedWeekStart: '2026-09-08'
                      selectedWeekEnd: '2026-09-08'
                      previousWeekStart: '2026-09-08'
                      nextWeekStart: '2026-09-08'
                      plans:
                        - planId: 67f1234567890abcdef1234
                          name: Hybrid programme
                          mode: recurring
                          startDate: '2026-09-08'
                          weekNumber: 1
                          isAvailable: true
                      days:
                        - weekday: 1
                          date: '2026-09-08'
                          planDays:
                            - planId: 67f1234567890abcdef1234
                              planName: Hybrid programme
                              weekNumber: 2
                              isAvailable: true
                              isBeforeStart: false
                              isRestDay: false
                              items:
                                - programmeScheduleItemId: 67f1234567890abcdef1234
                                  plannedDate: '2026-09-08'
                                  scheduledDate: '2026-09-08'
                                  source: programme
                                  clientAdjustment:
                                    action: moved
                                    occurrenceDate: '2026-09-08'
                                    scheduledDate: string
                                    changedAt: '2026-07-14T10:00:00.000Z'
                                  canClientMove: true
                                  canClientSkip: true
                                  canClientRestore: true
                                  type: workout
                                  order: 1
                                  title: Upper body
                                  description: Strength session
                                  startTime: '18:00'
                                  plannedDurationMinutes: 45
                                  status: today
                                  isAvailable: true
                                  planMomentId: null
                                  activityType: running
                                  targetDistanceMeters: 5000
                                  performance:
                                    workBlocks:
                                      - blockId: 66f7b8b1e13c8d25f4d3d90a
                                        stepId: 66f7b8b1e13c8d25f4d3d90a
                                        repIndex: 1
                                        durationSec: 1
                                        distanceM: 1
                                        avgPaceSecPerKm: 1
                                        avgHrBpm: 1
                                    avgHrBpm: 1
                                    missedReason: sick
                                    conditions:
                                      temperatureC: 1
                                      windNote: string
                                      elevationGainM: 1
                                      preFatigueNote: string
                                    niggle:
                                      note: string
                                    source: manual
                                    completedOnTarget: true
                                    workBlockEvaluation:
                                      reasonCodes:
                                        - SESSION_NOT_COMPLETED
                                      blocks:
                                        - blockId: 66f7b8b1e13c8d25f4d3d90a
                                          stepId: 66f7b8b1e13c8d25f4d3d90a
                                          repIndex: 1
                                          onTarget: true
                                          reasonCode: string
                                    resolvedTargetsSnapshot:
                                      source: execution_snapshot
                                      paceUnit: s/km
                                      sessionType: easy
                                      controlMode: pace
                                      blocks:
                                        - _id: 66f7b8b1e13c8d25f4d3d90a
                                          repeat: 1
                                          steps:
                                            - _id: 66f7b8b1e13c8d25f4d3d90a
                                              kind: warmup
                                              durationType: time
                                              durationValue: 1
                                              target:
                                                kind: paceZone
                                                zone: E
                                                basis: lthr
                                                low: 1
                                                high: 1
                                              secondaryTarget:
                                                kind: paceZone
                                                zone: E
                                                basis: lthr
                                                low: 1
                                                high: 1
                                              targetReasonCode: string
                                              secondaryTargetReasonCode: string
                                    externalWorkoutRef: string
                                    id: 67f1234567890abcdef1234
                                    planId: 67f1234567890abcdef1234
                                    programmeScheduleItemId: 67f1234567890abcdef1234
                                    plannedDate: '2026-09-08'
                                    status: completed
                                    startedAt: null
                                    completedAt: null
                                    actualDurationMinutes: 45
                                    actualDistanceMeters: 8000
                                    notes: Felt smooth.
                                    rpe: 7
                                  cardio:
                                    slotKey: string
                                    sessionType: easy
                                    controlMode: pace
                                    ladderStep: 1
                                    poolLengthM: 25
                                    blocks:
                                      - _id: 67f1234567890abcdef1234
                                        repeat: 1
                                        steps:
                                          - _id: 67f1234567890abcdef1234
                                            kind: warmup
                                            durationType: time
                                            durationValue: 1
                                            target:
                                              kind: paceZone
                                              zone: E
                                              basis: lthr
                                              low: 1
                                              high: 1
                                            secondaryTarget:
                                              kind: paceZone
                                              zone: E
                                              basis: lthr
                                              low: 1
                                              high: 1
                                            notes: string
                                            stroke: free
                                            equipment:
                                              - pullBuoy
                                            restMode: rest
                                            sendOffSec: 1
                                            cadence:
                                              low: 1
                                              high: 1
                                    sourceTemplateId: null
                                  resolvedTargets:
                                    paceUnit: s/km
                                    source: string
                                    reasonCodes:
                                      - CARDIO_PROFILE_INVALID
                                    blocks:
                                      - _id: 66f7b8b1e13c8d25f4d3d90a
                                        repeat: 1
                                        steps:
                                          - _id: 66f7b8b1e13c8d25f4d3d90a
                                            kind: string
                                            target:
                                              kind: paceZone
                                              zone: E
                                              basis: lthr
                                              low: 1
                                              high: 1
                                            secondaryTarget:
                                              kind: paceZone
                                              zone: E
                                              basis: lthr
                                              low: 1
                                              high: 1
                                            targetReasonCode: CARDIO_PROFILE_INVALID
                                            secondaryTargetReasonCode: CARDIO_PROFILE_INVALID
                          clientItems:
                            - clientCalendarItemId: 67f1234567890abcdef1234
                              source: client
                              type: activity
                              scheduledDate: '2026-09-08'
                              plannedDate: '2026-09-08'
                              startTime: string
                              title: string
                              description: Example description
                              activityType: string
                              plannedDurationMinutes: 1
                              targetDistanceMeters: 1
                              actualDurationMinutes: 1
                              actualDistanceMeters: 1
                              rpe: 1
                              notes: string
                              status: upcoming
                              isAvailable: true
                              workoutSessionId: null
                              canEdit: true
                              canDelete: true
                              canStart: true
                      skippedOccurrences:
                        - programmeScheduleItemId: 67f1234567890abcdef1234
                          plannedDate: '2026-09-08'
                          scheduledDate: '2026-09-08'
                          source: programme
                          clientAdjustment:
                            action: skipped
                            occurrenceDate: '2026-09-08'
                            scheduledDate: ''
                            changedAt: '2026-07-14T10:00:00.000Z'
                          canClientMove: true
                          canClientSkip: true
                          canClientRestore: true
                          type: workout
                          order: 1
                          title: Upper body
                          description: Strength session
                          startTime: '18:00'
                          plannedDurationMinutes: 45
                          status: today
                          isAvailable: true
                          planMomentId: null
                          activityType: running
                          targetDistanceMeters: 5000
                          performance:
                            workBlocks:
                              - blockId: 66f7b8b1e13c8d25f4d3d90a
                                stepId: 66f7b8b1e13c8d25f4d3d90a
                                repIndex: 1
                                durationSec: 1
                                distanceM: 1
                                avgPaceSecPerKm: 1
                                avgHrBpm: 1
                            avgHrBpm: 1
                            missedReason: sick
                            conditions:
                              temperatureC: 1
                              windNote: string
                              elevationGainM: 1
                              preFatigueNote: string
                            niggle:
                              note: string
                            source: manual
                            completedOnTarget: true
                            workBlockEvaluation:
                              reasonCodes:
                                - SESSION_NOT_COMPLETED
                              blocks:
                                - blockId: 66f7b8b1e13c8d25f4d3d90a
                                  stepId: 66f7b8b1e13c8d25f4d3d90a
                                  repIndex: 1
                                  onTarget: true
                                  reasonCode: string
                            resolvedTargetsSnapshot:
                              source: execution_snapshot
                              paceUnit: s/km
                              sessionType: easy
                              controlMode: pace
                              blocks:
                                - _id: 66f7b8b1e13c8d25f4d3d90a
                                  repeat: 1
                                  steps:
                                    - _id: 66f7b8b1e13c8d25f4d3d90a
                                      kind: warmup
                                      durationType: time
                                      durationValue: 1
                                      target:
                                        kind: paceZone
                                        zone: E
                                        basis: lthr
                                        low: 1
                                        high: 1
                                      secondaryTarget:
                                        kind: paceZone
                                        zone: E
                                        basis: lthr
                                        low: 1
                                        high: 1
                                      targetReasonCode: string
                                      secondaryTargetReasonCode: string
                            externalWorkoutRef: string
                            id: 67f1234567890abcdef1234
                            planId: 67f1234567890abcdef1234
                            programmeScheduleItemId: 67f1234567890abcdef1234
                            plannedDate: '2026-09-08'
                            status: completed
                            startedAt: null
                            completedAt: null
                            actualDurationMinutes: 45
                            actualDistanceMeters: 8000
                            notes: Felt smooth.
                            rpe: 7
                          cardio:
                            slotKey: string
                            sessionType: easy
                            controlMode: pace
                            ladderStep: 1
                            poolLengthM: 25
                            blocks:
                              - _id: 67f1234567890abcdef1234
                                repeat: 1
                                steps:
                                  - _id: 67f1234567890abcdef1234
                                    kind: warmup
                                    durationType: time
                                    durationValue: 1
                                    target:
                                      kind: paceZone
                                      zone: E
                                      basis: lthr
                                      low: 1
                                      high: 1
                                    secondaryTarget:
                                      kind: paceZone
                                      zone: E
                                      basis: lthr
                                      low: 1
                                      high: 1
                                    notes: string
                                    stroke: free
                                    equipment:
                                      - pullBuoy
                                    restMode: rest
                                    sendOffSec: 1
                                    cadence:
                                      low: 1
                                      high: 1
                            sourceTemplateId: null
                          resolvedTargets:
                            paceUnit: s/km
                            source: string
                            reasonCodes:
                              - CARDIO_PROFILE_INVALID
                            blocks:
                              - _id: 66f7b8b1e13c8d25f4d3d90a
                                repeat: 1
                                steps:
                                  - _id: 66f7b8b1e13c8d25f4d3d90a
                                    kind: string
                                    target:
                                      kind: paceZone
                                      zone: E
                                      basis: lthr
                                      low: 1
                                      high: 1
                                    secondaryTarget:
                                      kind: paceZone
                                      zone: E
                                      basis: lthr
                                      low: 1
                                      high: 1
                                    targetReasonCode: CARDIO_PROFILE_INVALID
                                    secondaryTargetReasonCode: CARDIO_PROFILE_INVALID
                          planId: 67f1234567890abcdef1234
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 9
                        resetSeconds: 1
        '400':
          description: >-
            Invalid selected Monday (`WORKOUTPLAN_SELECTED_WEEK_START_INVALID`),
            invalid authenticated scope (`COMPANY_ID_REQUIRED` or
            `INVALID_CLIENT_ID`), or forbidden query scope override
            (`PROGRAMME_CALENDAR_SCOPE_OVERRIDE_INVALID`).
          x-errorCodes:
            - WORKOUTPLAN_SELECTED_WEEK_START_INVALID
            - COMPANY_ID_REQUIRED
            - INVALID_CLIENT_ID
            - PROGRAMME_CALENDAR_SCOPE_OVERRIDE_INVALID
          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-calendar"
            \
              -H "Authorization: Bearer <access_token>"
components:
  schemas:
    PublicApiSuccessResponse:
      type: object
      additionalProperties: false
      required:
        - data
        - meta
      properties:
        data:
          type: object
        meta:
          $ref: '#/components/schemas/PublicApiMeta'
    PublicWorkoutSourceGETAppV1WorkoutClientProgrammeCalendarResponse200:
      type: object
      required:
        - timeZone
        - selectedWeekStart
        - selectedWeekEnd
        - previousWeekStart
        - nextWeekStart
        - plans
        - days
      properties:
        timeZone:
          type: string
          example: Europe/Amsterdam
        selectedWeekStart:
          type: string
          format: date
          pattern: ^\d{4}-\d{2}-\d{2}$
          example: '2026-09-08'
        selectedWeekEnd:
          type: string
          format: date
          pattern: ^\d{4}-\d{2}-\d{2}$
          example: '2026-09-08'
        previousWeekStart:
          type: string
          format: date
          pattern: ^\d{4}-\d{2}-\d{2}$
          example: '2026-09-08'
        nextWeekStart:
          type: string
          format: date
          pattern: ^\d{4}-\d{2}-\d{2}$
          example: '2026-09-08'
        plans:
          type: array
          items:
            type: object
            required:
              - planId
              - name
              - mode
              - startDate
              - weekNumber
              - isAvailable
            properties:
              planId:
                type: string
                example: 67f1234567890abcdef1234
              name:
                type: string
                example: Hybrid programme
              mode:
                type: string
                enum:
                  - recurring
                  - multi_week
              startDate:
                type: string
                format: date
                pattern: ^\d{4}-\d{2}-\d{2}$
                example: '2026-09-08'
              weekNumber:
                type: integer
                minimum: 1
              isAvailable:
                type: boolean
        days:
          type: array
          minItems: 7
          maxItems: 7
          items:
            type: object
            required:
              - weekday
              - date
              - planDays
            properties:
              weekday:
                type: integer
                minimum: 1
                maximum: 7
              date:
                type: string
                format: date
                pattern: ^\d{4}-\d{2}-\d{2}$
                example: '2026-09-08'
              planDays:
                type: array
                items:
                  type: object
                  required:
                    - planId
                    - planName
                    - weekNumber
                    - isAvailable
                    - isRestDay
                    - items
                  properties:
                    planId:
                      type: string
                      example: 67f1234567890abcdef1234
                    planName:
                      type: string
                      example: Hybrid programme
                    weekNumber:
                      type: integer
                      minimum: 1
                      example: 2
                    isAvailable:
                      type: boolean
                      example: true
                    isBeforeStart:
                      type: boolean
                      example: false
                      description: >-
                        True for days before a mid-week multi-week startDate;
                        returned as a rest day with no items.
                    isRestDay:
                      type: boolean
                      example: false
                    items:
                      type: array
                      items:
                        type: object
                        required:
                          - programmeScheduleItemId
                          - plannedDate
                          - type
                          - order
                          - title
                          - description
                          - startTime
                          - plannedDurationMinutes
                          - status
                          - isAvailable
                          - planMomentId
                          - activityType
                          - targetDistanceMeters
                          - performance
                        properties:
                          programmeScheduleItemId:
                            type: string
                            example: 67f1234567890abcdef1234
                          plannedDate:
                            type: string
                            format: date
                            pattern: ^\d{4}-\d{2}-\d{2}$
                            example: '2026-09-08'
                          scheduledDate:
                            type: string
                            format: date
                            pattern: ^\d{4}-\d{2}-\d{2}$
                            example: '2026-09-08'
                          source:
                            type: string
                            enum:
                              - programme
                            example: programme
                          clientAdjustment:
                            oneOf:
                              - type: object
                                properties:
                                  action:
                                    type: string
                                    enum:
                                      - moved
                                      - skipped
                                  occurrenceDate:
                                    type: string
                                    format: date
                                    pattern: ^\d{4}-\d{2}-\d{2}$
                                    example: '2026-09-08'
                                  scheduledDate:
                                    type: string
                                    pattern: ^$|^\d{4}-\d{2}-\d{2}$
                                  changedAt:
                                    type:
                                      - string
                                      - 'null'
                                    format: date-time
                              - type: 'null'
                          canClientMove:
                            type: boolean
                          canClientSkip:
                            type: boolean
                          canClientRestore:
                            type: boolean
                            description: >-
                              True when this occurrence has a client adjustment
                              that may be restored.
                          type:
                            type: string
                            enum:
                              - workout
                              - activity
                          order:
                            type: integer
                            minimum: 1
                            example: 1
                          title:
                            type: string
                            example: Upper body
                          description:
                            type: string
                            example: Strength session
                          startTime:
                            type: string
                            pattern: ^(?:[01]\d|2[0-3]):[0-5]\d$|^$
                            example: '18:00'
                          plannedDurationMinutes:
                            type:
                              - number
                              - 'null'
                            minimum: 0
                            example: 45
                          status:
                            type: string
                            enum:
                              - upcoming
                              - today
                              - overdue
                              - in_progress
                              - completed
                            example: today
                          isAvailable:
                            type: boolean
                            example: true
                          planMomentId:
                            type:
                              - string
                              - 'null'
                            example: null
                          activityType:
                            type:
                              - string
                              - 'null'
                            enum:
                              - running
                              - cycling
                              - walking
                              - swimming
                              - rowing
                              - padel
                              - mobility
                              - other
                              - null
                          targetDistanceMeters:
                            type:
                              - number
                              - 'null'
                            minimum: 0
                            example: 5000
                          performance:
                            oneOf:
                              - type: object
                                properties:
                                  workBlocks:
                                    type: array
                                    maxItems: 1000
                                    items:
                                      type: object
                                      additionalProperties: false
                                      required:
                                        - blockId
                                        - stepId
                                        - repIndex
                                      properties:
                                        blockId:
                                          type: string
                                          pattern: ^[a-fA-F0-9]{24}$
                                        stepId:
                                          type: string
                                          pattern: ^[a-fA-F0-9]{24}$
                                        repIndex:
                                          type: integer
                                          minimum: 1
                                          maximum: 50
                                        durationSec:
                                          type: number
                                          exclusiveMinimum: 0
                                          description: Measured work-step seconds.
                                        distanceM:
                                          type: number
                                          exclusiveMinimum: 0
                                          description: Measured work-step metres.
                                        avgPaceSecPerKm:
                                          type: number
                                          exclusiveMinimum: 0
                                          description: >-
                                            Measured work-step mean pace in
                                            seconds/km.
                                        avgHrBpm:
                                          type: number
                                          exclusiveMinimum: 0
                                          description: Measured work-step mean HR in bpm.
                                      description: >-
                                        At least one measured metric is
                                        required. Positive finite numbers and
                                        localized decimal strings are accepted.
                                    description: >-
                                      Work steps only, identified by persisted
                                      block/step ids and a one-based repetition
                                      index. Recovery and whole-activity
                                      averages cannot supply work evidence.
                                      Omission preserves existing entries; an
                                      explicit array replaces them.
                                  avgHrBpm:
                                    type: number
                                    exclusiveMinimum: 0
                                    description: >-
                                      Whole-activity mean HR, informational
                                      only; never compared with a work-step
                                      band.
                                  missedReason:
                                    type: string
                                    enum:
                                      - sick
                                      - away
                                      - injured
                                      - interrupted
                                      - too_hard
                                      - other
                                  conditions:
                                    type: object
                                    additionalProperties: false
                                    properties:
                                      temperatureC:
                                        type: number
                                        description: >-
                                          Measured temperature in degrees Celsius;
                                          no automatic heat correction is
                                          inferred.
                                      windNote:
                                        type: string
                                        maxLength: 2000
                                        description: >-
                                          Recorded wind conditions; an explicit
                                          empty string means no wind effect
                                          reported.
                                      elevationGainM:
                                        type: number
                                        minimum: 0
                                        description: Recorded elevation gain in metres.
                                      preFatigueNote:
                                        type: string
                                        maxLength: 2000
                                        description: >-
                                          Recorded pre-fatigue; an explicit empty
                                          string means none reported.
                                  niggle:
                                    type: object
                                    additionalProperties: false
                                    required:
                                      - note
                                    properties:
                                      note:
                                        type: string
                                        maxLength: 2000
                                    description: >-
                                      Authenticated athlete only. Sets the
                                      profile niggle active before saving the
                                      log. Clearing requires the dedicated
                                      athlete endpoint; coaches cannot clear it.
                                  source:
                                    type: string
                                    enum:
                                      - manual
                                    description: >-
                                      Public writes are manual. Consented
                                      wearable import is a later phase.
                                  completedOnTarget:
                                    type:
                                      - boolean
                                      - 'null'
                                    readOnly: true
                                    description: >-
                                      Server computed from every prescribed work
                                      repetition and its primary signal and
                                      duration. Missing evidence or a
                                      single-value pace target with unspecified
                                      tolerance returns null. Secondary guidance
                                      and activity averages are never binding.
                                  workBlockEvaluation:
                                    type: object
                                    readOnly: true
                                    properties:
                                      reasonCodes:
                                        type: array
                                        items:
                                          type: string
                                          enum:
                                            - SESSION_NOT_COMPLETED
                                            - WORK_PRESCRIPTION_MISSING
                                            - WORK_BLOCK_MISSING
                                            - WORK_TARGET_UNRESOLVED
                                            - CONTROL_MODE_MISMATCH
                                            - PACE_TOLERANCE_UNSPECIFIED
                                            - WORK_METRIC_MISSING
                                            - WORK_DURATION_MISSING
                                      blocks:
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            blockId:
                                              type: string
                                            stepId:
                                              type: string
                                            repIndex:
                                              type: integer
                                              minimum: 1
                                            onTarget:
                                              type:
                                                - boolean
                                                - 'null'
                                            reasonCode:
                                              type: string
                                  resolvedTargetsSnapshot:
                                    type: object
                                    readOnly: true
                                    properties:
                                      source:
                                        type: string
                                        enum:
                                          - execution_snapshot
                                      paceUnit:
                                        type: string
                                        enum:
                                          - s/km
                                      sessionType:
                                        type: string
                                        enum:
                                          - easy
                                          - zone2
                                          - long_run
                                          - threshold_continuous
                                          - threshold_reps
                                          - interval
                                          - race_pace
                                          - time_trial
                                          - race
                                      controlMode:
                                        type: string
                                        enum:
                                          - pace
                                          - hr
                                      blocks:
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            _id:
                                              type: string
                                            repeat:
                                              type: integer
                                              minimum: 1
                                              maximum: 50
                                            steps:
                                              type: array
                                              items:
                                                type: object
                                                properties:
                                                  _id:
                                                    type: string
                                                  kind:
                                                    type: string
                                                    enum:
                                                      - warmup
                                                      - work
                                                      - recovery
                                                      - rest
                                                      - cooldown
                                                  durationType:
                                                    type: string
                                                    enum:
                                                      - time
                                                      - distance
                                                      - open
                                                  durationValue:
                                                    type:
                                                      - number
                                                      - 'null'
                                                    minimum: 0
                                                  target:
                                                    type: object
                                                    additionalProperties: false
                                                    required:
                                                      - kind
                                                    description: >-
                                                      Allowed kinds and zones depend on the
                                                      sport. Zone targets require zone; other
                                                      targets require ordered low/high bounds.
                                                      Pace is seconds/km for running/walking,
                                                      seconds/500m for rowing, seconds/100m
                                                      for swimming. Percentages are percent
                                                      values; HR is bpm, power is watts, RPE
                                                      is 1–10. Numeric strings with dot or
                                                      comma decimals are accepted.
                                                    properties:
                                                      kind:
                                                        type: string
                                                        enum:
                                                          - paceZone
                                                          - pacePct
                                                          - pace
                                                          - hrZone
                                                          - hrPct
                                                          - hr
                                                          - powerZone
                                                          - powerPct
                                                          - power
                                                          - rpe
                                                      zone:
                                                        type: string
                                                        enum:
                                                          - E
                                                          - T
                                                          - I
                                                          - R
                                                          - RP
                                                          - Z1
                                                          - Z2
                                                          - Z3
                                                          - Z4
                                                          - Z5
                                                          - Z6
                                                          - Z7
                                                          - easy
                                                          - endurance
                                                          - threshold
                                                          - speed
                                                        description: >-
                                                          Run pace: E (easy), T (threshold), I
                                                          (interval), R (repetition), RP (race
                                                          pace = goal time / goal distance, never
                                                          derived from T). Running has no HR
                                                          zones; HR bands are absolute bpm from
                                                          athlete data. Walking/rowing pace and
                                                          five-zone HR: Z1–Z5. Bike/row power:
                                                          Z1–Z7. Swimming pace: easy, endurance,
                                                          threshold, speed.
                                                      basis:
                                                        type: string
                                                        enum:
                                                          - lthr
                                                          - maxHr
                                                        description: HR zone/percentage targets only.
                                                      low:
                                                        type: number
                                                        minimum: 0
                                                      high:
                                                        type: number
                                                        minimum: 0
                                                  secondaryTarget:
                                                    type: object
                                                    additionalProperties: false
                                                    required:
                                                      - kind
                                                    description: >-
                                                      Allowed kinds and zones depend on the
                                                      sport. Zone targets require zone; other
                                                      targets require ordered low/high bounds.
                                                      Pace is seconds/km for running/walking,
                                                      seconds/500m for rowing, seconds/100m
                                                      for swimming. Percentages are percent
                                                      values; HR is bpm, power is watts, RPE
                                                      is 1–10. Numeric strings with dot or
                                                      comma decimals are accepted.
                                                    properties:
                                                      kind:
                                                        type: string
                                                        enum:
                                                          - paceZone
                                                          - pacePct
                                                          - pace
                                                          - hrZone
                                                          - hrPct
                                                          - hr
                                                          - powerZone
                                                          - powerPct
                                                          - power
                                                          - rpe
                                                      zone:
                                                        type: string
                                                        enum:
                                                          - E
                                                          - T
                                                          - I
                                                          - R
                                                          - RP
                                                          - Z1
                                                          - Z2
                                                          - Z3
                                                          - Z4
                                                          - Z5
                                                          - Z6
                                                          - Z7
                                                          - easy
                                                          - endurance
                                                          - threshold
                                                          - speed
                                                        description: >-
                                                          Run pace: E (easy), T (threshold), I
                                                          (interval), R (repetition), RP (race
                                                          pace = goal time / goal distance, never
                                                          derived from T). Running has no HR
                                                          zones; HR bands are absolute bpm from
                                                          athlete data. Walking/rowing pace and
                                                          five-zone HR: Z1–Z5. Bike/row power:
                                                          Z1–Z7. Swimming pace: easy, endurance,
                                                          threshold, speed.
                                                      basis:
                                                        type: string
                                                        enum:
                                                          - lthr
                                                          - maxHr
                                                        description: HR zone/percentage targets only.
                                                      low:
                                                        type: number
                                                        minimum: 0
                                                      high:
                                                        type: number
                                                        minimum: 0
                                                  targetReasonCode:
                                                    type: string
                                                  secondaryTargetReasonCode:
                                                    type: string
                                    description: >-
                                      First logging captures the prescribed
                                      structure and resolved targets. Later
                                      profile or schedule edits never replace
                                      this snapshot. Client writes are rejected.
                                  externalWorkoutRef:
                                    type: string
                                    readOnly: true
                                    description: >-
                                      Reserved for a future consented server
                                      import; rejected in public writes.
                                  id:
                                    type: string
                                    example: 67f1234567890abcdef1234
                                  planId:
                                    type: string
                                    example: 67f1234567890abcdef1234
                                  programmeScheduleItemId:
                                    type: string
                                    example: 67f1234567890abcdef1234
                                  plannedDate:
                                    type: string
                                    format: date
                                    pattern: ^\d{4}-\d{2}-\d{2}$
                                    example: '2026-09-08'
                                  status:
                                    type: string
                                    enum:
                                      - in_progress
                                      - completed
                                      - cancelled
                                    example: completed
                                  startedAt:
                                    type:
                                      - string
                                      - 'null'
                                    format: date-time
                                    example: null
                                  completedAt:
                                    type:
                                      - string
                                      - 'null'
                                    format: date-time
                                    example: null
                                  actualDurationMinutes:
                                    type:
                                      - number
                                      - 'null'
                                    minimum: 0
                                    example: 45
                                    description: Actual activity duration in minutes.
                                  actualDistanceMeters:
                                    type:
                                      - number
                                      - 'null'
                                    minimum: 0
                                    example: 8000
                                    description: Actual activity distance in meters.
                                  notes:
                                    type: string
                                    example: Felt smooth.
                                  rpe:
                                    type:
                                      - number
                                      - 'null'
                                    minimum: 1
                                    maximum: 10
                                    example: 7
                                required:
                                  - id
                                  - planId
                                  - programmeScheduleItemId
                                  - plannedDate
                                  - status
                                  - startedAt
                                  - completedAt
                                  - actualDurationMinutes
                                  - actualDistanceMeters
                                  - notes
                                  - rpe
                              - type: 'null'
                          cardio:
                            type: object
                            additionalProperties: false
                            description: >-
                              Optional structured activity prescription.
                              Requires workoutsectionv2 +
                              workoutV2ProgrammeCalendar +
                              workoutV2CardioBuilder. Omitted from disabled
                              reads. Supported sports: running (paceZone
                              E/T/I/R/RP, absolute pace, absolute HR, RPE),
                              walking (pace, HR, RPE), cycling (power, HR, RPE),
                              rowing (pace, power, HR, RPE), swimming (pace,
                              RPE). Rejected for workout, padel, mobility and
                              other items. Totals overwrite planned
                              duration/distance; unknown time or distance
                              contributes zero.
                            properties:
                              slotKey:
                                type: string
                                description: >-
                                  Generated when missing; retain across edits,
                                  copies and weeks.
                              sessionType:
                                type: string
                                enum:
                                  - easy
                                  - zone2
                                  - long_run
                                  - threshold_continuous
                                  - threshold_reps
                                  - interval
                                  - race_pace
                                  - time_trial
                                  - race
                                description: >-
                                  Running only. Template session codes:
                                  threshold_continuous = drempel_c,
                                  threshold_reps = drempel_r, interval,
                                  race_pace = doeltempo, zone2. A typed session
                                  with empty blocks is a skeleton to be filled
                                  later.
                              controlMode:
                                type: string
                                enum:
                                  - pace
                                  - hr
                                description: >-
                                  Binding signal. Defaults from sessionType: hr
                                  for easy, zone2 and long_run; pace for
                                  threshold_continuous, threshold_reps, interval
                                  and race_pace; none for time_trial and race. A
                                  contradicting value is rejected.
                              ladderStep:
                                type: integer
                                minimum: 1
                                description: >-
                                  Ladder position: interval 1–8, threshold_reps
                                  1–7, threshold_continuous 1–5 (15/18/20/22/25
                                  min). Rejected for other session types.
                              poolLengthM:
                                type: number
                                enum:
                                  - 25
                                  - 50
                                description: Swimming only.
                              blocks:
                                type: array
                                maxItems: 10
                                items:
                                  type: object
                                  additionalProperties: false
                                  properties:
                                    _id:
                                      type: string
                                      example: 67f1234567890abcdef1234
                                    repeat:
                                      type: integer
                                      minimum: 1
                                      maximum: 50
                                      default: 1
                                    steps:
                                      type: array
                                      maxItems: 20
                                      items:
                                        type: object
                                        additionalProperties: false
                                        required:
                                          - kind
                                          - durationType
                                        properties:
                                          _id:
                                            type: string
                                            example: 67f1234567890abcdef1234
                                          kind:
                                            type: string
                                            enum:
                                              - warmup
                                              - work
                                              - recovery
                                              - rest
                                              - cooldown
                                          durationType:
                                            type: string
                                            enum:
                                              - time
                                              - distance
                                              - open
                                          durationValue:
                                            type:
                                              - number
                                              - 'null'
                                            minimum: 0
                                            default: null
                                            description: >-
                                              Required seconds for time or metres for
                                              distance; null/omitted for open.
                                          target:
                                            type: object
                                            additionalProperties: false
                                            required:
                                              - kind
                                            description: >-
                                              Allowed kinds and zones depend on the
                                              sport. Zone targets require zone; other
                                              targets require ordered low/high bounds.
                                              Pace is seconds/km for running/walking,
                                              seconds/500m for rowing, seconds/100m
                                              for swimming. Percentages are percent
                                              values; HR is bpm, power is watts, RPE
                                              is 1–10. Numeric strings with dot or
                                              comma decimals are accepted.
                                            properties:
                                              kind:
                                                type: string
                                                enum:
                                                  - paceZone
                                                  - pacePct
                                                  - pace
                                                  - hrZone
                                                  - hrPct
                                                  - hr
                                                  - powerZone
                                                  - powerPct
                                                  - power
                                                  - rpe
                                              zone:
                                                type: string
                                                enum:
                                                  - E
                                                  - T
                                                  - I
                                                  - R
                                                  - RP
                                                  - Z1
                                                  - Z2
                                                  - Z3
                                                  - Z4
                                                  - Z5
                                                  - Z6
                                                  - Z7
                                                  - easy
                                                  - endurance
                                                  - threshold
                                                  - speed
                                                description: >-
                                                  Run pace: E (easy), T (threshold), I
                                                  (interval), R (repetition), RP (race
                                                  pace = goal time / goal distance, never
                                                  derived from T). Running has no HR
                                                  zones; HR bands are absolute bpm from
                                                  athlete data. Walking/rowing pace and
                                                  five-zone HR: Z1–Z5. Bike/row power:
                                                  Z1–Z7. Swimming pace: easy, endurance,
                                                  threshold, speed.
                                              basis:
                                                type: string
                                                enum:
                                                  - lthr
                                                  - maxHr
                                                description: HR zone/percentage targets only.
                                              low:
                                                type: number
                                                minimum: 0
                                              high:
                                                type: number
                                                minimum: 0
                                          secondaryTarget:
                                            type: object
                                            additionalProperties: false
                                            required:
                                              - kind
                                            description: >-
                                              Allowed kinds and zones depend on the
                                              sport. Zone targets require zone; other
                                              targets require ordered low/high bounds.
                                              Pace is seconds/km for running/walking,
                                              seconds/500m for rowing, seconds/100m
                                              for swimming. Percentages are percent
                                              values; HR is bpm, power is watts, RPE
                                              is 1–10. Numeric strings with dot or
                                              comma decimals are accepted.
                                            properties:
                                              kind:
                                                type: string
                                                enum:
                                                  - paceZone
                                                  - pacePct
                                                  - pace
                                                  - hrZone
                                                  - hrPct
                                                  - hr
                                                  - powerZone
                                                  - powerPct
                                                  - power
                                                  - rpe
                                              zone:
                                                type: string
                                                enum:
                                                  - E
                                                  - T
                                                  - I
                                                  - R
                                                  - RP
                                                  - Z1
                                                  - Z2
                                                  - Z3
                                                  - Z4
                                                  - Z5
                                                  - Z6
                                                  - Z7
                                                  - easy
                                                  - endurance
                                                  - threshold
                                                  - speed
                                                description: >-
                                                  Run pace: E (easy), T (threshold), I
                                                  (interval), R (repetition), RP (race
                                                  pace = goal time / goal distance, never
                                                  derived from T). Running has no HR
                                                  zones; HR bands are absolute bpm from
                                                  athlete data. Walking/rowing pace and
                                                  five-zone HR: Z1–Z5. Bike/row power:
                                                  Z1–Z7. Swimming pace: easy, endurance,
                                                  threshold, speed.
                                              basis:
                                                type: string
                                                enum:
                                                  - lthr
                                                  - maxHr
                                                description: HR zone/percentage targets only.
                                              low:
                                                type: number
                                                minimum: 0
                                              high:
                                                type: number
                                                minimum: 0
                                          notes:
                                            type: string
                                            default: ''
                                          stroke:
                                            type: string
                                            enum:
                                              - free
                                              - back
                                              - breast
                                              - fly
                                              - im
                                              - choice
                                              - kick
                                              - drill
                                            description: Swimming only.
                                          equipment:
                                            type: array
                                            items:
                                              type: string
                                              enum:
                                                - pullBuoy
                                                - paddles
                                                - fins
                                                - kickboard
                                                - snorkel
                                            description: Swimming only.
                                          restMode:
                                            type: string
                                            enum:
                                              - rest
                                              - sendOff
                                            description: >-
                                              Swimming only. sendOff requires
                                              sendOffSec.
                                          sendOffSec:
                                            type: number
                                            minimum: 1
                                            description: Swimming sendOff only.
                                          cadence:
                                            type: object
                                            additionalProperties: false
                                            required:
                                              - low
                                              - high
                                            properties:
                                              low:
                                                type: number
                                                minimum: 0
                                              high:
                                                type: number
                                                minimum: 0
                                      default: []
                                default: []
                              sourceTemplateId:
                                type:
                                  - string
                                  - 'null'
                                example: null
                          resolvedTargets:
                            type: object
                            readOnly: true
                            description: >-
                              Resolved running targets alongside the original
                              cardio prescription. Targets use current athlete
                              measurements, except persisted execution snapshots
                              are preserved. Missing measurements/goal return
                              null for only the affected target with a reason
                              code. Absolute HR remains literal; E/T/I/R use
                              threshold, RP uses the independent running goal.
                              An RP goal over 60 minutes faster than measured
                              threshold returns GOAL_NOT_FEASIBLE unless
                              accepted as a challenge. Omitted while cardio is
                              disabled.
                            properties:
                              paceUnit:
                                type: string
                                enum:
                                  - s/km
                              source:
                                type: string
                              reasonCodes:
                                type: array
                                items:
                                  type: string
                                  enum:
                                    - CARDIO_PROFILE_INVALID
                                    - THRESHOLD_MEASUREMENT_REQUIRED
                                    - THRESHOLD_OFFSET_UNRESOLVED
                                    - RUNNING_GOAL_REQUIRED
                                    - GOAL_NOT_FEASIBLE
                              blocks:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    _id:
                                      type: string
                                    repeat:
                                      type: number
                                    steps:
                                      type: array
                                      items:
                                        type: object
                                        properties:
                                          _id:
                                            type: string
                                          kind:
                                            type: string
                                          target:
                                            anyOf:
                                              - type: object
                                                additionalProperties: false
                                                required:
                                                  - kind
                                                description: >-
                                                  Allowed kinds and zones depend on the
                                                  sport. Zone targets require zone; other
                                                  targets require ordered low/high bounds.
                                                  Pace is seconds/km for running/walking,
                                                  seconds/500m for rowing, seconds/100m
                                                  for swimming. Percentages are percent
                                                  values; HR is bpm, power is watts, RPE
                                                  is 1–10. Numeric strings with dot or
                                                  comma decimals are accepted.
                                                properties:
                                                  kind:
                                                    type: string
                                                    enum:
                                                      - paceZone
                                                      - pacePct
                                                      - pace
                                                      - hrZone
                                                      - hrPct
                                                      - hr
                                                      - powerZone
                                                      - powerPct
                                                      - power
                                                      - rpe
                                                  zone:
                                                    type: string
                                                    enum:
                                                      - E
                                                      - T
                                                      - I
                                                      - R
                                                      - RP
                                                      - Z1
                                                      - Z2
                                                      - Z3
                                                      - Z4
                                                      - Z5
                                                      - Z6
                                                      - Z7
                                                      - easy
                                                      - endurance
                                                      - threshold
                                                      - speed
                                                    description: >-
                                                      Run pace: E (easy), T (threshold), I
                                                      (interval), R (repetition), RP (race
                                                      pace = goal time / goal distance, never
                                                      derived from T). Running has no HR
                                                      zones; HR bands are absolute bpm from
                                                      athlete data. Walking/rowing pace and
                                                      five-zone HR: Z1–Z5. Bike/row power:
                                                      Z1–Z7. Swimming pace: easy, endurance,
                                                      threshold, speed.
                                                  basis:
                                                    type: string
                                                    enum:
                                                      - lthr
                                                      - maxHr
                                                    description: HR zone/percentage targets only.
                                                  low:
                                                    type: number
                                                    minimum: 0
                                                  high:
                                                    type: number
                                                    minimum: 0
                                              - type: 'null'
                                          secondaryTarget:
                                            anyOf:
                                              - type: object
                                                additionalProperties: false
                                                required:
                                                  - kind
                                                description: >-
                                                  Allowed kinds and zones depend on the
                                                  sport. Zone targets require zone; other
                                                  targets require ordered low/high bounds.
                                                  Pace is seconds/km for running/walking,
                                                  seconds/500m for rowing, seconds/100m
                                                  for swimming. Percentages are percent
                                                  values; HR is bpm, power is watts, RPE
                                                  is 1–10. Numeric strings with dot or
                                                  comma decimals are accepted.
                                                properties:
                                                  kind:
                                                    type: string
                                                    enum:
                                                      - paceZone
                                                      - pacePct
                                                      - pace
                                                      - hrZone
                                                      - hrPct
                                                      - hr
                                                      - powerZone
                                                      - powerPct
                                                      - power
                                                      - rpe
                                                  zone:
                                                    type: string
                                                    enum:
                                                      - E
                                                      - T
                                                      - I
                                                      - R
                                                      - RP
                                                      - Z1
                                                      - Z2
                                                      - Z3
                                                      - Z4
                                                      - Z5
                                                      - Z6
                                                      - Z7
                                                      - easy
                                                      - endurance
                                                      - threshold
                                                      - speed
                                                    description: >-
                                                      Run pace: E (easy), T (threshold), I
                                                      (interval), R (repetition), RP (race
                                                      pace = goal time / goal distance, never
                                                      derived from T). Running has no HR
                                                      zones; HR bands are absolute bpm from
                                                      athlete data. Walking/rowing pace and
                                                      five-zone HR: Z1–Z5. Bike/row power:
                                                      Z1–Z7. Swimming pace: easy, endurance,
                                                      threshold, speed.
                                                  basis:
                                                    type: string
                                                    enum:
                                                      - lthr
                                                      - maxHr
                                                    description: HR zone/percentage targets only.
                                                  low:
                                                    type: number
                                                    minimum: 0
                                                  high:
                                                    type: number
                                                    minimum: 0
                                              - type: 'null'
                                          targetReasonCode:
                                            type: string
                                            enum:
                                              - CARDIO_PROFILE_INVALID
                                              - THRESHOLD_MEASUREMENT_REQUIRED
                                              - THRESHOLD_OFFSET_UNRESOLVED
                                              - RUNNING_GOAL_REQUIRED
                                              - GOAL_NOT_FEASIBLE
                                          secondaryTargetReasonCode:
                                            type: string
                                            enum:
                                              - CARDIO_PROFILE_INVALID
                                              - THRESHOLD_MEASUREMENT_REQUIRED
                                              - THRESHOLD_OFFSET_UNRESOLVED
                                              - RUNNING_GOAL_REQUIRED
                                              - GOAL_NOT_FEASIBLE
              clientItems:
                type: array
                description: Client-owned personal agenda rows for this date.
                items:
                  type: object
                  description: >-
                    A client-owned agenda item. It is always available because
                    personal items are not governed by a programme release
                    window.
                  required:
                    - clientCalendarItemId
                    - source
                    - type
                    - scheduledDate
                    - plannedDate
                    - title
                    - description
                    - status
                    - isAvailable
                    - canEdit
                    - canDelete
                    - canStart
                  properties:
                    clientCalendarItemId:
                      type: string
                      example: 67f1234567890abcdef1234
                    source:
                      type: string
                      enum:
                        - client
                    type:
                      type: string
                      enum:
                        - activity
                        - freestyle_workout
                    scheduledDate:
                      type: string
                      format: date
                      pattern: ^\d{4}-\d{2}-\d{2}$
                      example: '2026-09-08'
                    plannedDate:
                      type: string
                      format: date
                      pattern: ^\d{4}-\d{2}-\d{2}$
                      example: '2026-09-08'
                    startTime:
                      type: string
                    title:
                      type: string
                    description:
                      type: string
                    activityType:
                      type:
                        - string
                        - 'null'
                    plannedDurationMinutes:
                      type:
                        - number
                        - 'null'
                      minimum: 0
                    targetDistanceMeters:
                      type:
                        - number
                        - 'null'
                      minimum: 0
                    actualDurationMinutes:
                      type:
                        - number
                        - 'null'
                      minimum: 0
                    actualDistanceMeters:
                      type:
                        - number
                        - 'null'
                      minimum: 0
                    rpe:
                      type:
                        - number
                        - 'null'
                      minimum: 1
                      maximum: 10
                    notes:
                      type: string
                    status:
                      type: string
                      enum:
                        - upcoming
                        - today
                        - overdue
                        - in_progress
                        - completed
                        - cancelled
                    isAvailable:
                      type: boolean
                      enum:
                        - true
                    workoutSessionId:
                      type:
                        - string
                        - 'null'
                      example: null
                    canEdit:
                      type: boolean
                    canDelete:
                      type: boolean
                    canStart:
                      type: boolean
        skippedOccurrences:
          type: array
          description: Full client-skipped programme occurrences that can be restored.
          items:
            allOf:
              - type: object
                required:
                  - programmeScheduleItemId
                  - plannedDate
                  - type
                  - order
                  - title
                  - description
                  - startTime
                  - plannedDurationMinutes
                  - status
                  - isAvailable
                  - planMomentId
                  - activityType
                  - targetDistanceMeters
                  - performance
                properties:
                  programmeScheduleItemId:
                    type: string
                    example: 67f1234567890abcdef1234
                  plannedDate:
                    type: string
                    format: date
                    pattern: ^\d{4}-\d{2}-\d{2}$
                    example: '2026-09-08'
                  scheduledDate:
                    type: string
                    format: date
                    pattern: ^\d{4}-\d{2}-\d{2}$
                    example: '2026-09-08'
                  source:
                    type: string
                    enum:
                      - programme
                    example: programme
                  clientAdjustment:
                    oneOf:
                      - type: object
                        properties:
                          action:
                            type: string
                            enum:
                              - moved
                              - skipped
                          occurrenceDate:
                            type: string
                            format: date
                            pattern: ^\d{4}-\d{2}-\d{2}$
                            example: '2026-09-08'
                          scheduledDate:
                            type: string
                            pattern: ^$|^\d{4}-\d{2}-\d{2}$
                          changedAt:
                            type:
                              - string
                              - 'null'
                            format: date-time
                      - type: 'null'
                  canClientMove:
                    type: boolean
                  canClientSkip:
                    type: boolean
                  canClientRestore:
                    type: boolean
                    description: >-
                      True when this occurrence has a client adjustment that may
                      be restored.
                  type:
                    type: string
                    enum:
                      - workout
                      - activity
                  order:
                    type: integer
                    minimum: 1
                    example: 1
                  title:
                    type: string
                    example: Upper body
                  description:
                    type: string
                    example: Strength session
                  startTime:
                    type: string
                    pattern: ^(?:[01]\d|2[0-3]):[0-5]\d$|^$
                    example: '18:00'
                  plannedDurationMinutes:
                    type:
                      - number
                      - 'null'
                    minimum: 0
                    example: 45
                  status:
                    type: string
                    enum:
                      - upcoming
                      - today
                      - overdue
                      - in_progress
                      - completed
                    example: today
                  isAvailable:
                    type: boolean
                    example: true
                  planMomentId:
                    type:
                      - string
                      - 'null'
                    example: null
                  activityType:
                    type:
                      - string
                      - 'null'
                    enum:
                      - running
                      - cycling
                      - walking
                      - swimming
                      - rowing
                      - padel
                      - mobility
                      - other
                      - null
                  targetDistanceMeters:
                    type:
                      - number
                      - 'null'
                    minimum: 0
                    example: 5000
                  performance:
                    oneOf:
                      - type: object
                        properties:
                          workBlocks:
                            type: array
                            maxItems: 1000
                            items:
                              type: object
                              additionalProperties: false
                              required:
                                - blockId
                                - stepId
                                - repIndex
                              properties:
                                blockId:
                                  type: string
                                  pattern: ^[a-fA-F0-9]{24}$
                                stepId:
                                  type: string
                                  pattern: ^[a-fA-F0-9]{24}$
                                repIndex:
                                  type: integer
                                  minimum: 1
                                  maximum: 50
                                durationSec:
                                  type: number
                                  exclusiveMinimum: 0
                                  description: Measured work-step seconds.
                                distanceM:
                                  type: number
                                  exclusiveMinimum: 0
                                  description: Measured work-step metres.
                                avgPaceSecPerKm:
                                  type: number
                                  exclusiveMinimum: 0
                                  description: Measured work-step mean pace in seconds/km.
                                avgHrBpm:
                                  type: number
                                  exclusiveMinimum: 0
                                  description: Measured work-step mean HR in bpm.
                              description: >-
                                At least one measured metric is required.
                                Positive finite numbers and localized decimal
                                strings are accepted.
                            description: >-
                              Work steps only, identified by persisted
                              block/step ids and a one-based repetition index.
                              Recovery and whole-activity averages cannot supply
                              work evidence. Omission preserves existing
                              entries; an explicit array replaces them.
                          avgHrBpm:
                            type: number
                            exclusiveMinimum: 0
                            description: >-
                              Whole-activity mean HR, informational only; never
                              compared with a work-step band.
                          missedReason:
                            type: string
                            enum:
                              - sick
                              - away
                              - injured
                              - interrupted
                              - too_hard
                              - other
                          conditions:
                            type: object
                            additionalProperties: false
                            properties:
                              temperatureC:
                                type: number
                                description: >-
                                  Measured temperature in degrees Celsius; no
                                  automatic heat correction is inferred.
                              windNote:
                                type: string
                                maxLength: 2000
                                description: >-
                                  Recorded wind conditions; an explicit empty
                                  string means no wind effect reported.
                              elevationGainM:
                                type: number
                                minimum: 0
                                description: Recorded elevation gain in metres.
                              preFatigueNote:
                                type: string
                                maxLength: 2000
                                description: >-
                                  Recorded pre-fatigue; an explicit empty string
                                  means none reported.
                          niggle:
                            type: object
                            additionalProperties: false
                            required:
                              - note
                            properties:
                              note:
                                type: string
                                maxLength: 2000
                            description: >-
                              Authenticated athlete only. Sets the profile
                              niggle active before saving the log. Clearing
                              requires the dedicated athlete endpoint; coaches
                              cannot clear it.
                          source:
                            type: string
                            enum:
                              - manual
                            description: >-
                              Public writes are manual. Consented wearable
                              import is a later phase.
                          completedOnTarget:
                            type:
                              - boolean
                              - 'null'
                            readOnly: true
                            description: >-
                              Server computed from every prescribed work
                              repetition and its primary signal and duration.
                              Missing evidence or a single-value pace target
                              with unspecified tolerance returns null. Secondary
                              guidance and activity averages are never binding.
                          workBlockEvaluation:
                            type: object
                            readOnly: true
                            properties:
                              reasonCodes:
                                type: array
                                items:
                                  type: string
                                  enum:
                                    - SESSION_NOT_COMPLETED
                                    - WORK_PRESCRIPTION_MISSING
                                    - WORK_BLOCK_MISSING
                                    - WORK_TARGET_UNRESOLVED
                                    - CONTROL_MODE_MISMATCH
                                    - PACE_TOLERANCE_UNSPECIFIED
                                    - WORK_METRIC_MISSING
                                    - WORK_DURATION_MISSING
                              blocks:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    blockId:
                                      type: string
                                    stepId:
                                      type: string
                                    repIndex:
                                      type: integer
                                      minimum: 1
                                    onTarget:
                                      type:
                                        - boolean
                                        - 'null'
                                    reasonCode:
                                      type: string
                          resolvedTargetsSnapshot:
                            type: object
                            readOnly: true
                            properties:
                              source:
                                type: string
                                enum:
                                  - execution_snapshot
                              paceUnit:
                                type: string
                                enum:
                                  - s/km
                              sessionType:
                                type: string
                                enum:
                                  - easy
                                  - zone2
                                  - long_run
                                  - threshold_continuous
                                  - threshold_reps
                                  - interval
                                  - race_pace
                                  - time_trial
                                  - race
                              controlMode:
                                type: string
                                enum:
                                  - pace
                                  - hr
                              blocks:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    _id:
                                      type: string
                                    repeat:
                                      type: integer
                                      minimum: 1
                                      maximum: 50
                                    steps:
                                      type: array
                                      items:
                                        type: object
                                        properties:
                                          _id:
                                            type: string
                                          kind:
                                            type: string
                                            enum:
                                              - warmup
                                              - work
                                              - recovery
                                              - rest
                                              - cooldown
                                          durationType:
                                            type: string
                                            enum:
                                              - time
                                              - distance
                                              - open
                                          durationValue:
                                            type:
                                              - number
                                              - 'null'
                                            minimum: 0
                                          target:
                                            type: object
                                            additionalProperties: false
                                            required:
                                              - kind
                                            description: >-
                                              Allowed kinds and zones depend on the
                                              sport. Zone targets require zone; other
                                              targets require ordered low/high bounds.
                                              Pace is seconds/km for running/walking,
                                              seconds/500m for rowing, seconds/100m
                                              for swimming. Percentages are percent
                                              values; HR is bpm, power is watts, RPE
                                              is 1–10. Numeric strings with dot or
                                              comma decimals are accepted.
                                            properties:
                                              kind:
                                                type: string
                                                enum:
                                                  - paceZone
                                                  - pacePct
                                                  - pace
                                                  - hrZone
                                                  - hrPct
                                                  - hr
                                                  - powerZone
                                                  - powerPct
                                                  - power
                                                  - rpe
                                              zone:
                                                type: string
                                                enum:
                                                  - E
                                                  - T
                                                  - I
                                                  - R
                                                  - RP
                                                  - Z1
                                                  - Z2
                                                  - Z3
                                                  - Z4
                                                  - Z5
                                                  - Z6
                                                  - Z7
                                                  - easy
                                                  - endurance
                                                  - threshold
                                                  - speed
                                                description: >-
                                                  Run pace: E (easy), T (threshold), I
                                                  (interval), R (repetition), RP (race
                                                  pace = goal time / goal distance, never
                                                  derived from T). Running has no HR
                                                  zones; HR bands are absolute bpm from
                                                  athlete data. Walking/rowing pace and
                                                  five-zone HR: Z1–Z5. Bike/row power:
                                                  Z1–Z7. Swimming pace: easy, endurance,
                                                  threshold, speed.
                                              basis:
                                                type: string
                                                enum:
                                                  - lthr
                                                  - maxHr
                                                description: HR zone/percentage targets only.
                                              low:
                                                type: number
                                                minimum: 0
                                              high:
                                                type: number
                                                minimum: 0
                                          secondaryTarget:
                                            type: object
                                            additionalProperties: false
                                            required:
                                              - kind
                                            description: >-
                                              Allowed kinds and zones depend on the
                                              sport. Zone targets require zone; other
                                              targets require ordered low/high bounds.
                                              Pace is seconds/km for running/walking,
                                              seconds/500m for rowing, seconds/100m
                                              for swimming. Percentages are percent
                                              values; HR is bpm, power is watts, RPE
                                              is 1–10. Numeric strings with dot or
                                              comma decimals are accepted.
                                            properties:
                                              kind:
                                                type: string
                                                enum:
                                                  - paceZone
                                                  - pacePct
                                                  - pace
                                                  - hrZone
                                                  - hrPct
                                                  - hr
                                                  - powerZone
                                                  - powerPct
                                                  - power
                                                  - rpe
                                              zone:
                                                type: string
                                                enum:
                                                  - E
                                                  - T
                                                  - I
                                                  - R
                                                  - RP
                                                  - Z1
                                                  - Z2
                                                  - Z3
                                                  - Z4
                                                  - Z5
                                                  - Z6
                                                  - Z7
                                                  - easy
                                                  - endurance
                                                  - threshold
                                                  - speed
                                                description: >-
                                                  Run pace: E (easy), T (threshold), I
                                                  (interval), R (repetition), RP (race
                                                  pace = goal time / goal distance, never
                                                  derived from T). Running has no HR
                                                  zones; HR bands are absolute bpm from
                                                  athlete data. Walking/rowing pace and
                                                  five-zone HR: Z1–Z5. Bike/row power:
                                                  Z1–Z7. Swimming pace: easy, endurance,
                                                  threshold, speed.
                                              basis:
                                                type: string
                                                enum:
                                                  - lthr
                                                  - maxHr
                                                description: HR zone/percentage targets only.
                                              low:
                                                type: number
                                                minimum: 0
                                              high:
                                                type: number
                                                minimum: 0
                                          targetReasonCode:
                                            type: string
                                          secondaryTargetReasonCode:
                                            type: string
                            description: >-
                              First logging captures the prescribed structure
                              and resolved targets. Later profile or schedule
                              edits never replace this snapshot. Client writes
                              are rejected.
                          externalWorkoutRef:
                            type: string
                            readOnly: true
                            description: >-
                              Reserved for a future consented server import;
                              rejected in public writes.
                          id:
                            type: string
                            example: 67f1234567890abcdef1234
                          planId:
                            type: string
                            example: 67f1234567890abcdef1234
                          programmeScheduleItemId:
                            type: string
                            example: 67f1234567890abcdef1234
                          plannedDate:
                            type: string
                            format: date
                            pattern: ^\d{4}-\d{2}-\d{2}$
                            example: '2026-09-08'
                          status:
                            type: string
                            enum:
                              - in_progress
                              - completed
                              - cancelled
                            example: completed
                          startedAt:
                            type:
                              - string
                              - 'null'
                            format: date-time
                            example: null
                          completedAt:
                            type:
                              - string
                              - 'null'
                            format: date-time
                            example: null
                          actualDurationMinutes:
                            type:
                              - number
                              - 'null'
                            minimum: 0
                            example: 45
                            description: Actual activity duration in minutes.
                          actualDistanceMeters:
                            type:
                              - number
                              - 'null'
                            minimum: 0
                            example: 8000
                            description: Actual activity distance in meters.
                          notes:
                            type: string
                            example: Felt smooth.
                          rpe:
                            type:
                              - number
                              - 'null'
                            minimum: 1
                            maximum: 10
                            example: 7
                        required:
                          - id
                          - planId
                          - programmeScheduleItemId
                          - plannedDate
                          - status
                          - startedAt
                          - completedAt
                          - actualDurationMinutes
                          - actualDistanceMeters
                          - notes
                          - rpe
                      - type: 'null'
                  cardio:
                    type: object
                    additionalProperties: false
                    description: >-
                      Optional structured activity prescription. Requires
                      workoutsectionv2 + workoutV2ProgrammeCalendar +
                      workoutV2CardioBuilder. Omitted from disabled reads.
                      Supported sports: running (paceZone E/T/I/R/RP, absolute
                      pace, absolute HR, RPE), walking (pace, HR, RPE), cycling
                      (power, HR, RPE), rowing (pace, power, HR, RPE), swimming
                      (pace, RPE). Rejected for workout, padel, mobility and
                      other items. Totals overwrite planned duration/distance;
                      unknown time or distance contributes zero.
                    properties:
                      slotKey:
                        type: string
                        description: >-
                          Generated when missing; retain across edits, copies
                          and weeks.
                      sessionType:
                        type: string
                        enum:
                          - easy
                          - zone2
                          - long_run
                          - threshold_continuous
                          - threshold_reps
                          - interval
                          - race_pace
                          - time_trial
                          - race
                        description: >-
                          Running only. Template session codes:
                          threshold_continuous = drempel_c, threshold_reps =
                          drempel_r, interval, race_pace = doeltempo, zone2. A
                          typed session with empty blocks is a skeleton to be
                          filled later.
                      controlMode:
                        type: string
                        enum:
                          - pace
                          - hr
                        description: >-
                          Binding signal. Defaults from sessionType: hr for
                          easy, zone2 and long_run; pace for
                          threshold_continuous, threshold_reps, interval and
                          race_pace; none for time_trial and race. A
                          contradicting value is rejected.
                      ladderStep:
                        type: integer
                        minimum: 1
                        description: >-
                          Ladder position: interval 1–8, threshold_reps 1–7,
                          threshold_continuous 1–5 (15/18/20/22/25 min).
                          Rejected for other session types.
                      poolLengthM:
                        type: number
                        enum:
                          - 25
                          - 50
                        description: Swimming only.
                      blocks:
                        type: array
                        maxItems: 10
                        items:
                          type: object
                          additionalProperties: false
                          properties:
                            _id:
                              type: string
                              example: 67f1234567890abcdef1234
                            repeat:
                              type: integer
                              minimum: 1
                              maximum: 50
                              default: 1
                            steps:
                              type: array
                              maxItems: 20
                              items:
                                type: object
                                additionalProperties: false
                                required:
                                  - kind
                                  - durationType
                                properties:
                                  _id:
                                    type: string
                                    example: 67f1234567890abcdef1234
                                  kind:
                                    type: string
                                    enum:
                                      - warmup
                                      - work
                                      - recovery
                                      - rest
                                      - cooldown
                                  durationType:
                                    type: string
                                    enum:
                                      - time
                                      - distance
                                      - open
                                  durationValue:
                                    type:
                                      - number
                                      - 'null'
                                    minimum: 0
                                    default: null
                                    description: >-
                                      Required seconds for time or metres for
                                      distance; null/omitted for open.
                                  target:
                                    type: object
                                    additionalProperties: false
                                    required:
                                      - kind
                                    description: >-
                                      Allowed kinds and zones depend on the
                                      sport. Zone targets require zone; other
                                      targets require ordered low/high bounds.
                                      Pace is seconds/km for running/walking,
                                      seconds/500m for rowing, seconds/100m for
                                      swimming. Percentages are percent values;
                                      HR is bpm, power is watts, RPE is 1–10.
                                      Numeric strings with dot or comma decimals
                                      are accepted.
                                    properties:
                                      kind:
                                        type: string
                                        enum:
                                          - paceZone
                                          - pacePct
                                          - pace
                                          - hrZone
                                          - hrPct
                                          - hr
                                          - powerZone
                                          - powerPct
                                          - power
                                          - rpe
                                      zone:
                                        type: string
                                        enum:
                                          - E
                                          - T
                                          - I
                                          - R
                                          - RP
                                          - Z1
                                          - Z2
                                          - Z3
                                          - Z4
                                          - Z5
                                          - Z6
                                          - Z7
                                          - easy
                                          - endurance
                                          - threshold
                                          - speed
                                        description: >-
                                          Run pace: E (easy), T (threshold), I
                                          (interval), R (repetition), RP (race
                                          pace = goal time / goal distance, never
                                          derived from T). Running has no HR
                                          zones; HR bands are absolute bpm from
                                          athlete data. Walking/rowing pace and
                                          five-zone HR: Z1–Z5. Bike/row power:
                                          Z1–Z7. Swimming pace: easy, endurance,
                                          threshold, speed.
                                      basis:
                                        type: string
                                        enum:
                                          - lthr
                                          - maxHr
                                        description: HR zone/percentage targets only.
                                      low:
                                        type: number
                                        minimum: 0
                                      high:
                                        type: number
                                        minimum: 0
                                  secondaryTarget:
                                    type: object
                                    additionalProperties: false
                                    required:
                                      - kind
                                    description: >-
                                      Allowed kinds and zones depend on the
                                      sport. Zone targets require zone; other
                                      targets require ordered low/high bounds.
                                      Pace is seconds/km for running/walking,
                                      seconds/500m for rowing, seconds/100m for
                                      swimming. Percentages are percent values;
                                      HR is bpm, power is watts, RPE is 1–10.
                                      Numeric strings with dot or comma decimals
                                      are accepted.
                                    properties:
                                      kind:
                                        type: string
                                        enum:
                                          - paceZone
                                          - pacePct
                                          - pace
                                          - hrZone
                                          - hrPct
                                          - hr
                                          - powerZone
                                          - powerPct
                                          - power
                                          - rpe
                                      zone:
                                        type: string
                                        enum:
                                          - E
                                          - T
                                          - I
                                          - R
                                          - RP
                                          - Z1
                                          - Z2
                                          - Z3
                                          - Z4
                                          - Z5
                                          - Z6
                                          - Z7
                                          - easy
                                          - endurance
                                          - threshold
                                          - speed
                                        description: >-
                                          Run pace: E (easy), T (threshold), I
                                          (interval), R (repetition), RP (race
                                          pace = goal time / goal distance, never
                                          derived from T). Running has no HR
                                          zones; HR bands are absolute bpm from
                                          athlete data. Walking/rowing pace and
                                          five-zone HR: Z1–Z5. Bike/row power:
                                          Z1–Z7. Swimming pace: easy, endurance,
                                          threshold, speed.
                                      basis:
                                        type: string
                                        enum:
                                          - lthr
                                          - maxHr
                                        description: HR zone/percentage targets only.
                                      low:
                                        type: number
                                        minimum: 0
                                      high:
                                        type: number
                                        minimum: 0
                                  notes:
                                    type: string
                                    default: ''
                                  stroke:
                                    type: string
                                    enum:
                                      - free
                                      - back
                                      - breast
                                      - fly
                                      - im
                                      - choice
                                      - kick
                                      - drill
                                    description: Swimming only.
                                  equipment:
                                    type: array
                                    items:
                                      type: string
                                      enum:
                                        - pullBuoy
                                        - paddles
                                        - fins
                                        - kickboard
                                        - snorkel
                                    description: Swimming only.
                                  restMode:
                                    type: string
                                    enum:
                                      - rest
                                      - sendOff
                                    description: >-
                                      Swimming only. sendOff requires
                                      sendOffSec.
                                  sendOffSec:
                                    type: number
                                    minimum: 1
                                    description: Swimming sendOff only.
                                  cadence:
                                    type: object
                                    additionalProperties: false
                                    required:
                                      - low
                                      - high
                                    properties:
                                      low:
                                        type: number
                                        minimum: 0
                                      high:
                                        type: number
                                        minimum: 0
                              default: []
                        default: []
                      sourceTemplateId:
                        type:
                          - string
                          - 'null'
                        example: null
                  resolvedTargets:
                    type: object
                    readOnly: true
                    description: >-
                      Resolved running targets alongside the original cardio
                      prescription. Targets use current athlete measurements,
                      except persisted execution snapshots are preserved.
                      Missing measurements/goal return null for only the
                      affected target with a reason code. Absolute HR remains
                      literal; E/T/I/R use threshold, RP uses the independent
                      running goal. An RP goal over 60 minutes faster than
                      measured threshold returns GOAL_NOT_FEASIBLE unless
                      accepted as a challenge. Omitted while cardio is disabled.
                    properties:
                      paceUnit:
                        type: string
                        enum:
                          - s/km
                      source:
                        type: string
                      reasonCodes:
                        type: array
                        items:
                          type: string
                          enum:
                            - CARDIO_PROFILE_INVALID
                            - THRESHOLD_MEASUREMENT_REQUIRED
                            - THRESHOLD_OFFSET_UNRESOLVED
                            - RUNNING_GOAL_REQUIRED
                            - GOAL_NOT_FEASIBLE
                      blocks:
                        type: array
                        items:
                          type: object
                          properties:
                            _id:
                              type: string
                            repeat:
                              type: number
                            steps:
                              type: array
                              items:
                                type: object
                                properties:
                                  _id:
                                    type: string
                                  kind:
                                    type: string
                                  target:
                                    anyOf:
                                      - type: object
                                        additionalProperties: false
                                        required:
                                          - kind
                                        description: >-
                                          Allowed kinds and zones depend on the
                                          sport. Zone targets require zone; other
                                          targets require ordered low/high bounds.
                                          Pace is seconds/km for running/walking,
                                          seconds/500m for rowing, seconds/100m
                                          for swimming. Percentages are percent
                                          values; HR is bpm, power is watts, RPE
                                          is 1–10. Numeric strings with dot or
                                          comma decimals are accepted.
                                        properties:
                                          kind:
                                            type: string
                                            enum:
                                              - paceZone
                                              - pacePct
                                              - pace
                                              - hrZone
                                              - hrPct
                                              - hr
                                              - powerZone
                                              - powerPct
                                              - power
                                              - rpe
                                          zone:
                                            type: string
                                            enum:
                                              - E
                                              - T
                                              - I
                                              - R
                                              - RP
                                              - Z1
                                              - Z2
                                              - Z3
                                              - Z4
                                              - Z5
                                              - Z6
                                              - Z7
                                              - easy
                                              - endurance
                                              - threshold
                                              - speed
                                            description: >-
                                              Run pace: E (easy), T (threshold), I
                                              (interval), R (repetition), RP (race
                                              pace = goal time / goal distance, never
                                              derived from T). Running has no HR
                                              zones; HR bands are absolute bpm from
                                              athlete data. Walking/rowing pace and
                                              five-zone HR: Z1–Z5. Bike/row power:
                                              Z1–Z7. Swimming pace: easy, endurance,
                                              threshold, speed.
                                          basis:
                                            type: string
                                            enum:
                                              - lthr
                                              - maxHr
                                            description: HR zone/percentage targets only.
                                          low:
                                            type: number
                                            minimum: 0
                                          high:
                                            type: number
                                            minimum: 0
                                      - type: 'null'
                                  secondaryTarget:
                                    anyOf:
                                      - type: object
                                        additionalProperties: false
                                        required:
                                          - kind
                                        description: >-
                                          Allowed kinds and zones depend on the
                                          sport. Zone targets require zone; other
                                          targets require ordered low/high bounds.
                                          Pace is seconds/km for running/walking,
                                          seconds/500m for rowing, seconds/100m
                                          for swimming. Percentages are percent
                                          values; HR is bpm, power is watts, RPE
                                          is 1–10. Numeric strings with dot or
                                          comma decimals are accepted.
                                        properties:
                                          kind:
                                            type: string
                                            enum:
                                              - paceZone
                                              - pacePct
                                              - pace
                                              - hrZone
                                              - hrPct
                                              - hr
                                              - powerZone
                                              - powerPct
                                              - power
                                              - rpe
                                          zone:
                                            type: string
                                            enum:
                                              - E
                                              - T
                                              - I
                                              - R
                                              - RP
                                              - Z1
                                              - Z2
                                              - Z3
                                              - Z4
                                              - Z5
                                              - Z6
                                              - Z7
                                              - easy
                                              - endurance
                                              - threshold
                                              - speed
                                            description: >-
                                              Run pace: E (easy), T (threshold), I
                                              (interval), R (repetition), RP (race
                                              pace = goal time / goal distance, never
                                              derived from T). Running has no HR
                                              zones; HR bands are absolute bpm from
                                              athlete data. Walking/rowing pace and
                                              five-zone HR: Z1–Z5. Bike/row power:
                                              Z1–Z7. Swimming pace: easy, endurance,
                                              threshold, speed.
                                          basis:
                                            type: string
                                            enum:
                                              - lthr
                                              - maxHr
                                            description: HR zone/percentage targets only.
                                          low:
                                            type: number
                                            minimum: 0
                                          high:
                                            type: number
                                            minimum: 0
                                      - type: 'null'
                                  targetReasonCode:
                                    type: string
                                    enum:
                                      - CARDIO_PROFILE_INVALID
                                      - THRESHOLD_MEASUREMENT_REQUIRED
                                      - THRESHOLD_OFFSET_UNRESOLVED
                                      - RUNNING_GOAL_REQUIRED
                                      - GOAL_NOT_FEASIBLE
                                  secondaryTargetReasonCode:
                                    type: string
                                    enum:
                                      - CARDIO_PROFILE_INVALID
                                      - THRESHOLD_MEASUREMENT_REQUIRED
                                      - THRESHOLD_OFFSET_UNRESOLVED
                                      - RUNNING_GOAL_REQUIRED
                                      - GOAL_NOT_FEASIBLE
              - type: object
                description: >-
                  A full programme item removed from its day by a client skip,
                  retained for restore UI.
                required:
                  - planId
                  - programmeScheduleItemId
                  - plannedDate
                  - scheduledDate
                  - clientAdjustment
                properties:
                  planId:
                    type: string
                    example: 67f1234567890abcdef1234
                  programmeScheduleItemId:
                    type: string
                    example: 67f1234567890abcdef1234
                  plannedDate:
                    type: string
                    format: date
                    pattern: ^\d{4}-\d{2}-\d{2}$
                    example: '2026-09-08'
                  scheduledDate:
                    type: string
                    format: date
                    pattern: ^\d{4}-\d{2}-\d{2}$
                    example: '2026-09-08'
                  clientAdjustment:
                    type: object
                    required:
                      - action
                      - occurrenceDate
                      - scheduledDate
                      - changedAt
                    properties:
                      action:
                        type: string
                        enum:
                          - skipped
                      occurrenceDate:
                        type: string
                        format: date
                        pattern: ^\d{4}-\d{2}-\d{2}$
                        example: '2026-09-08'
                      scheduledDate:
                        type: string
                        enum:
                          - ''
                      changedAt:
                        type:
                          - string
                          - 'null'
                        format: date-time
    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.