> ## 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 freestyle workout-execution screen

> The freestyle (ad-hoc, no-plan) execution screen. Returns the SAME shape as the day workout endpoint, with `plan` and `day` set to `null` (freestyle has no plan/day/prescription). Keyed by the client (no params): resolves the active freestyle session — one with no `planId`/`planMomentId`/`wodId`/`groupRunId` — or the most-recent completed freestyle session. The `exercises[]` array is built entirely from the session's performances (logged + ad-hoc), grouped into supersets by `performance.groupId`; each item's `targets` is `null`. `resumeState` and the confirmation handshake behave exactly as the day endpoint.

- **Per-set placeholders.** Every `sets[]` row carries twelve extra fields: `repsPlaceholderCoach`, `weightPlaceholderCoach`, `timeSecondsPlaceholderCoach`, `distanceMetersPlaceholderCoach`, `rpePlaceholderCoach`, `restSecondsPlaceholderCoach`, and the same six without the `Coach` suffix. A placeholder is the greyed hint an EMPTY input shows.
  · `*PlaceholderCoach` is the coach's prescription for that set index (WorkoutPlan `setsData`). `null` for a metric this exercise type does not track (a `time` exercise has no reps hint), for a set beyond the prescribed count, for a metric the coach left blank, and for freestyle, which has no prescription at all.
  · `*Placeholder` is the hint to actually show. **The coach wins**: it is the `*PlaceholderCoach` value whenever there is one, and falls back to the client's own stored placeholder only where the coach prescribed nothing. So it is identical to `*PlaceholderCoach` on any prescribed set, and always reflects the CURRENT prescription — a coach editing 8 reps to 12 changes the hint immediately, with no stale client copy able to outlive it.
  · The client's stored placeholder (sent per set on `PUT /app/v1/workout/performance/sessions/{sessionId}/exercises/{exerciseId}`) is therefore a FALLBACK for sets the coach never prescribed, not an override. Send one only where `*PlaceholderCoach` is `null`; sending it elsewhere is accepted but ignored.
  · **Placeholders are never logged work** — excluded from every total, volume, PR and completion check — so a hint left showing after a value is cleared does not make the set count. They are emitted on logged rows too, because clearing a logged value is exactly when the hint has to reappear.
  · **Committing a hint.** When the athlete marks a set completed without typing, send the shown NUMERIC hint as the real value (`{ reps: 22, completed: true }`); it then counts as their performance. A RANGE hint (`"8-12"`) must NOT be submitted on a completed set — the client should prompt the athlete to enter a value and skip the call, because a range reaching a completed set is stored as its MINIMUM (`"12-24"` → 12 reps, 120 volume), silently under-crediting them. An unticked set sends its metric as `null` with `completed: false` and simply keeps showing the hint.

Requires the workout_client_plans:read scope. This operation maps to /app/v1/workout/plans/client/freestyle/workout 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}/plans/freestyle/workout
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}/plans/freestyle/workout:
    get:
      tags:
        - Workout
      summary: Get the freestyle workout-execution screen
      description: >-
        The freestyle (ad-hoc, no-plan) execution screen. Returns the SAME shape
        as the day workout endpoint, with `plan` and `day` set to `null`
        (freestyle has no plan/day/prescription). Keyed by the client (no
        params): resolves the active freestyle session — one with no
        `planId`/`planMomentId`/`wodId`/`groupRunId` — or the most-recent
        completed freestyle session. The `exercises[]` array is built entirely
        from the session's performances (logged + ad-hoc), grouped into
        supersets by `performance.groupId`; each item's `targets` is `null`.
        `resumeState` and the confirmation handshake behave exactly as the day
        endpoint.


        - **Per-set placeholders.** Every `sets[]` row carries twelve extra
        fields: `repsPlaceholderCoach`, `weightPlaceholderCoach`,
        `timeSecondsPlaceholderCoach`, `distanceMetersPlaceholderCoach`,
        `rpePlaceholderCoach`, `restSecondsPlaceholderCoach`, and the same six
        without the `Coach` suffix. A placeholder is the greyed hint an EMPTY
        input shows.
          · `*PlaceholderCoach` is the coach's prescription for that set index (WorkoutPlan `setsData`). `null` for a metric this exercise type does not track (a `time` exercise has no reps hint), for a set beyond the prescribed count, for a metric the coach left blank, and for freestyle, which has no prescription at all.
          · `*Placeholder` is the hint to actually show. **The coach wins**: it is the `*PlaceholderCoach` value whenever there is one, and falls back to the client's own stored placeholder only where the coach prescribed nothing. So it is identical to `*PlaceholderCoach` on any prescribed set, and always reflects the CURRENT prescription — a coach editing 8 reps to 12 changes the hint immediately, with no stale client copy able to outlive it.
          · The client's stored placeholder (sent per set on `PUT /app/v1/workout/performance/sessions/{sessionId}/exercises/{exerciseId}`) is therefore a FALLBACK for sets the coach never prescribed, not an override. Send one only where `*PlaceholderCoach` is `null`; sending it elsewhere is accepted but ignored.
          · **Placeholders are never logged work** — excluded from every total, volume, PR and completion check — so a hint left showing after a value is cleared does not make the set count. They are emitted on logged rows too, because clearing a logged value is exactly when the hint has to reappear.
          · **Committing a hint.** When the athlete marks a set completed without typing, send the shown NUMERIC hint as the real value (`{ reps: 22, completed: true }`); it then counts as their performance. A RANGE hint (`"8-12"`) must NOT be submitted on a completed set — the client should prompt the athlete to enter a value and skip the call, because a range reaching a completed set is stored as its MINIMUM (`"12-24"` → 12 reps, 120 volume), silently under-crediting them. An unticked set sends its metric as `null` with `completed: false` and simply keeps showing the hint.

        Requires the workout_client_plans:read scope. This operation maps to
        /app/v1/workout/plans/client/freestyle/workout 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: publicWorkoutgetPublicV1WorkoutClientsClientIdPlansFreestyleWorkout
      parameters:
        - in: query
          name: clientId
          required: false
          schema:
            type: string
            example: 67f1234567890abcdef1234
          description: Only for coach/admin callers; clients resolve from the token.
        - 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: >-
            Freestyle workout-execution payload (same shape as the day endpoint;
            plan/day null).
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PublicApiSuccessResponse'
                  - type: object
                    properties:
                      data:
                        $ref: >-
                          #/components/schemas/PublicWorkoutSourceGETAppV1WorkoutPlansClientFreestyleWorkoutResponse200
              examples:
                success:
                  summary: Successful response
                  value:
                    data:
                      plan:
                        runningPlan:
                          goal:
                            distance: 5K
                            goalTimeSec: 1
                            raceDate: '2026-07-14'
                            acceptGoalAsChallenge: true
                          goalUpdatedAt: '2026-07-14T10:00:00.000Z'
                          goalUpdatedBy: string
                          adaptationRevision: 1
                          lastReviewedWeek: 1
                          lastAdaptedAt: '2026-07-14T10:00:00.000Z'
                          generation:
                            templateKey: 5K
                            variant: true
                            runWeekdays:
                              - 1
                            qualityWeekdays:
                              - 1
                            longRunWeekday: 1
                            phases:
                              base: 1
                              threshold: 1
                              sharpen: 1
                            taperWeeks: 1
                            sourceVersion: plansjablonen-v259-1
                            policyVersion: safety-calendar-v1
                            generatedAt: '2026-07-14T10:00:00.000Z'
                            generatedBy: string
                            profileUpdatedAt: '2026-07-14T10:00:00.000Z'
                            totalWeeks: 1
                            concreteWeeks: 1
                            baselineKm: 1
                            peakKm: 1
                            thresholdSecPerKm: 1
                            warnings:
                              - string
                          weekSummaries:
                            - weekNumber: 1
                              weekStart: '2026-07-14'
                              phase: 1
                              phaseName: Base building
                              theme: Base building
                              weekKind: build
                              rotationWeek: 1
                              targetVolumeKm: 1
                              concrete: true
                              requestedVolumeKm: 1
                              allocatedKm: 1
                              remainingKm: 1
                              concreteRequested: true
                              sessions:
                                - weekday: 1
                                  code: drempel_c
                                  sessionType: threshold_continuous
                                  controlMode: hr
                                  longRunTargetMinutes: 1
                                  ladder:
                                    step: 1
                                    reps: 1
                                    kmPerRep: 1
                                  continuousMinutes: 1
                                  recoveryRangeSec:
                                    low: 1
                                    high: 1
                                  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
                                  totals:
                                    durationSec: 1
                                    distanceM: 1
                                    plannedDurationMinutes: 1
                                    targetDistanceMeters: 1
                                    zoneTimeSec: {}
                        _id: 67f1234567890abcdef1234
                        companyId: 67f1234567890abcdef1234
                        clientId: null
                        sourceTemplateId: null
                        addedBy: 67f1234567890abcdef1234
                        addedByRole: Coach
                        status: Draft
                        templateType: Template
                        name:
                          - lang: en
                            value: Full Body Strength
                          - lang: nl
                            value: Full Body Kracht
                        description:
                          - lang: en
                            value: Full Body Strength
                          - lang: nl
                            value: Full Body Kracht
                        difficulty: Intermediate
                        intensity: Medium
                        duration:
                          startDate: '2026-04-15'
                          endDate: '2026-06-15'
                          hasEndDate: true
                        images:
                          - url: https://cdn.example.com/workouts/plan-cover.jpg
                            width: 1280
                            height: 720
                        videos:
                          - url: https://cdn.example.com/workouts/demo.mp4
                            platform: s3
                            videoId: ''
                            thumbnail: https://cdn.example.com/workouts/demo-thumb.jpg
                            duration: 84
                            width: 1920
                            height: 1080
                        category: Strength
                        goal: Strength
                        periodizationType: Linear
                        popularity: 0
                        useDefaultExerciseSettings: true
                        defaultExerciseValues:
                          sets: 3
                          reps: 10-12
                          rest: 90
                          weight: 0
                          repTempo: '3010'
                          duration: 0
                        planMoments:
                          - _id: 67f1234567890abcdef1234
                            name:
                              - lang: en
                                value: Full Body Strength
                              - lang: nl
                                value: Full Body Kracht
                            description:
                              - lang: en
                                value: Full Body Strength
                              - lang: nl
                                value: Full Body Kracht
                            dayOrder: 1
                            order: 0
                            weekNumber: 1
                            sessionOrder: 1
                            date: '2026-04-15'
                            scoringType: forTime
                            targetValue: null
                            descriptionOnly: true
                            timeDomain:
                              windowSeconds: null
                              timeCapSeconds: 900
                              rounds: 3
                              intervalSeconds: null
                              intervalCount: null
                              workSeconds: null
                              restSeconds: null
                            scoreValidation:
                              timeCapSeconds: 900
                              maxReps: null
                              expectedIntervals: null
                            exercises:
                              - _id: 67f1234567890abcdef1234
                                exerciseId: 67f1234567890abcdef1234
                                type: reps
                                minReps: 6
                                maxReps: 8
                                notes: Pause 1 second on the chest.
                                sets: 4
                                metric: kg
                                rest: 120
                                intensity: High
                                difficulty: Intermediate
                                groupId: super-a
                                rpe: 8
                                rmPercentage: 75
                                tempo: '3010'
                                perSetTrackingEnabled: true
                                rpeEnabled: false
                                showSetRpe: true
                                setsData:
                                  - setNumber: 1
                                    setType: 'N'
                                    metric: '12'
                                    repetition: 8-12
                                    weight: 60
                                    rest: 90
                                    rpe: 7.5
                                    duration: 45
                                    distance: 250
                                setupSettingsEnabled: true
                                setupFields:
                                  - key: seat
                                    label: Seat
                                    type: text
                                    unit: ''
                                    options:
                                      - '1'
                                      - '2'
                                      - '3'
                                      - '4'
                                    order: 1
                                    required: false
                                    enabled: true
                                    defaultValue: 3
                                order: 0
                                isDeleted: false
                                deletedAt: null
                                createdAt: '2026-04-12T10:00:00.000Z'
                                updatedAt: '2026-04-12T10:00:00.000Z'
                            isDeleted: false
                            deletedAt: null
                            createdAt: '2026-04-12T10:00:00.000Z'
                            updatedAt: '2026-04-12T10:00:00.000Z'
                        visibility: Company
                        isDeleted: false
                        deletedAt: null
                        createdAt: '2026-04-12T10:00:00.000Z'
                        updatedAt: '2026-04-12T10:00:00.000Z'
                      day:
                        name: Day 1
                        description: Upper body push.
                        dayOrder: 1
                        order: 0
                        weekNumber: 1
                        sessionOrder: 1
                        date: '2026-04-15'
                        scoring:
                          scoringType: forTime
                          descriptionOnly: true
                          acceptsManualResult: true
                          targetValue: null
                          timeDomain:
                            windowSeconds: null
                            timeCapSeconds: 900
                            rounds: 3
                            intervalSeconds: null
                            intervalCount: null
                            workSeconds: null
                            restSeconds: null
                          scoreValidation:
                            timeCapSeconds: 900
                            maxReps: null
                            expectedIntervals: null
                          result:
                            roundsCompleted: 5
                            repsPerRound: 30
                            extraReps: 12
                            totalReps: 162
                            intervalReps:
                              - 12
                              - 11
                              - 10
                            elapsedSeconds: 742
                            finishedBeforeCap: true
                            timeCapSeconds: 900
                            maxLoadKg: 120
                        exercises:
                          - _id: 67f1234567890abcdef1234
                            exerciseId: 67f1234567890abcdef1234
                            type: reps
                            minReps: 6
                            maxReps: 8
                            notes: Pause 1 second on the chest.
                            sets: 4
                            metric: kg
                            rest: 120
                            intensity: High
                            difficulty: Intermediate
                            groupId: super-a
                            rpe: 8
                            rmPercentage: 75
                            tempo: '3010'
                            perSetTrackingEnabled: true
                            rpeEnabled: false
                            showSetRpe: true
                            setsData:
                              - setNumber: 1
                                setType: 'N'
                                metric: '12'
                                repetition: 8-12
                                weight: 60
                                rest: 90
                                rpe: 7.5
                                duration: 45
                                distance: 250
                            setupSettingsEnabled: true
                            setupFields:
                              - key: seat
                                label: Seat
                                type: text
                                unit: ''
                                options:
                                  - '1'
                                  - '2'
                                  - '3'
                                  - '4'
                                order: 1
                                required: false
                                enabled: true
                                defaultValue: 3
                            order: 0
                            isDeleted: false
                            deletedAt: null
                            createdAt: '2026-04-12T10:00:00.000Z'
                            updatedAt: '2026-04-12T10:00:00.000Z'
                        isDeleted: false
                        deletedAt: null
                        createdAt: '2026-04-12T10:00:00.000Z'
                        updatedAt: '2026-04-12T10:00:00.000Z'
                      stats:
                        durationMinutes: 0
                        exerciseCount: 0
                        expectedDurationMinutes: 110
                      exercises:
                        - type: exercise
                          planExerciseId: 67f1234567890abcdef1234
                          exerciseId: 67f1234567890abcdef1234
                          name: Dumbbell Bench Press
                          thumbnail: https://cdn.example.com/exercises/bench.jpg
                          media:
                            - type: image
                              url: https://cdn.example.com/ex/bench.jpg
                              platform: null
                              videoId: null
                              thumbnail: null
                              duration: null
                              width: 1080
                              height: 720
                          primaryMuscle: Chest
                          secondaryMuscles:
                            - Triceps
                          equipment:
                            - Dumbbell
                          groupId: ''
                          order: 0
                          isFavourite: false
                          hasHistory: false
                          targets:
                            type: reps
                            sets: 4
                            reps: 8–12
                            rest: 60
                            rpe: 8
                            rmPercentage: 0
                            tempo: ''
                            notes: Keep elbows tucked.
                          previousBestSet: 12 × 24kg
                          performanceId: 67f1234567890abcdef1234
                          isCompleted: false
                          clientNotes: ''
                          clientRestSeconds: null
                          notes: ''
                          sets:
                            - setNumber: 1
                              setType: 'N'
                              displayNumber: 1
                              displayLabel: '1'
                              previous: 12 × 22kg
                              reps: 10
                              weight: 22
                              timeSeconds: null
                              distanceMeters: null
                              rpe: null
                              completed: false
                          exerciseCount: 2
                          rounds: 4
                          data:
                            - id: 67f1234567890abcdef1234
                              name: Barbell Bench Press
                              primaryMuscle: Chest
                              secondaryMuscles:
                                - Chest
                              primaryJoint: Shoulder
                              equipment:
                                - Dumbbells
                              difficulty: Intermediate
                              intensity: Above Average
                              visibility: Company
                              tags:
                                - string
                              thumbnail: >-
                                https://cdn.example.com/exercises/bench-thumb.jpg
                      session:
                        id: 67f1234567890abcdef1234
                        status: in_progress
                        startedAt: '2026-04-12T10:00:00.000Z'
                        programmeScheduleItemId: 67f1234567890abcdef1234
                        plannedDate: '2026-09-08'
                      resumeState: create
                      requiresResumePrompt: false
                      requiresConfirmation: false
                      confirmationToken: null
                      confirmationTokenExpiresAt: null
                    meta:
                      requestId: 4f849d7d-f4f1-45cc-b4b7-3984a3d17f83
                      rateLimit:
                        limit: 10
                        remaining: 9
                        resetSeconds: 1
        '400':
          description: >-
            Company context is missing (`COMPANY_ID_REQUIRED`) or invalid client
            id (`INVALID_CLIENT_ID`).
          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':
          $ref: '#/components/schemas/ErrorResponse'
          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}/plans/freestyle/workout"
            \
              -H "Authorization: Bearer <access_token>"
components:
  schemas:
    PublicApiSuccessResponse:
      type: object
      additionalProperties: false
      required:
        - data
        - meta
      properties:
        data:
          type: object
        meta:
          $ref: '#/components/schemas/PublicApiMeta'
    PublicWorkoutSourceGETAppV1WorkoutPlansClientFreestyleWorkoutResponse200:
      type: object
      properties:
        plan:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutPlanDetail'
        day:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutPlanMomentDetail'
        stats:
          type: object
          properties:
            durationMinutes:
              type: integer
              example: 0
              description: >-
                Actual session duration (live elapsed for an active session); 0
                with no session.
            exerciseCount:
              type: integer
              example: 0
              description: Exercises logged in the current session.
            expectedDurationMinutes:
              type: integer
              example: 110
              description: Estimated from the plan-day prescription; 0 for freestyle.
          description: >-
            `expectedDurationMinutes` is always 0 for freestyle (no
            prescription).
        exercises:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
                enum:
                  - exercise
                  - superset
                example: exercise
              planExerciseId:
                type: string
                example: 67f1234567890abcdef1234
                nullable: true
                description: Null for freestyle / superset wrappers.
              exerciseId:
                type: string
                example: 67f1234567890abcdef1234
                nullable: true
              name:
                type: string
                example: Dumbbell Bench Press
              thumbnail:
                type: string
                example: https://cdn.example.com/exercises/bench.jpg
              media:
                type: array
                description: >-
                  Combined ordered media (images first, then videos) — same
                  shape as getExerciseHistory. Empty for superset wrappers.
                items:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                        - image
                        - video
                        - link
                      example: image
                    url:
                      type: string
                      example: https://cdn.example.com/ex/bench.jpg
                    platform:
                      type:
                        - string
                        - 'null'
                      example: null
                    videoId:
                      type:
                        - string
                        - 'null'
                      example: null
                    thumbnail:
                      type:
                        - string
                        - 'null'
                      example: null
                    duration:
                      type:
                        - number
                        - 'null'
                      example: null
                    width:
                      type:
                        - number
                        - 'null'
                      example: 1080
                    height:
                      type:
                        - number
                        - 'null'
                      example: 720
              primaryMuscle:
                type: string
                example: Chest
              secondaryMuscles:
                type: array
                items:
                  type: string
                example:
                  - Triceps
              equipment:
                type: array
                items:
                  type: string
                example:
                  - Dumbbell
              groupId:
                type: string
                example: ''
                description: Superset group id (empty when standalone).
              order:
                type: integer
                example: 0
              isFavourite:
                type: boolean
                example: false
              hasHistory:
                type: boolean
                example: false
                description: >-
                  Whether this exercise has viewable completed-session history
                  (same basis as getExerciseHistory). Exercise items only;
                  omitted from superset wrappers.
              targets:
                type: object
                nullable: true
                description: >-
                  Plan-prescribed targets. `null` for freestyle and superset
                  wrappers.
                properties:
                  type:
                    type: string
                    example: reps
                  sets:
                    type: integer
                    example: 4
                  reps:
                    type: string
                    example: 8–12
                  rest:
                    type: integer
                    example: 60
                    description: Prescribed rest seconds.
                  rpe:
                    type: number
                    example: 8
                  rmPercentage:
                    type: number
                    example: 0
                  tempo:
                    type: string
                    example: ''
                  notes:
                    type: string
                    example: Keep elbows tucked.
                    description: Coach's prescribed note for this exercise.
              previousBestSet:
                type: string
                nullable: true
                example: 12 × 24kg
              performanceId:
                type: string
                example: 67f1234567890abcdef1234
                nullable: true
                description: Current-session performance id; null if not started.
              isCompleted:
                type: boolean
                example: false
              clientNotes:
                type: string
                example: ''
                description: Client's own note for this exercise (this session).
              clientRestSeconds:
                type:
                  - number
                  - 'null'
                example: null
                description: >-
                  Client's own exercise-level rest this session (does NOT fall
                  back to targets.rest).
              notes:
                type: string
                example: ''
                description: Superset-wrapper note (always empty for exercise items).
              sets:
                type: array
                items:
                  type: object
                  properties:
                    setNumber:
                      type: integer
                      example: 1
                    setType:
                      type: string
                      enum:
                        - 'N'
                        - W
                        - D
                        - F
                      example: 'N'
                    displayNumber:
                      type: integer
                      nullable: true
                      example: 1
                      description: >-
                        Sequential number for normal sets only. Warm-up, drop
                        set, and failure sets return null.
                    displayLabel:
                      type: string
                      example: '1'
                      description: >-
                        Backend-ready display string: normal sets use their
                        sequential number, other set types use W, D, or F.
                    previous:
                      type: string
                      nullable: true
                      example: 12 × 22kg
                      description: >-
                        Same-index set from the last performance of this
                        exercise (`reps × weightkg`, `30s`, `100m`), or null.
                    reps:
                      type: integer
                      nullable: true
                      example: 10
                    weight:
                      type: number
                      nullable: true
                      example: 22
                    timeSeconds:
                      type: number
                      nullable: true
                      example: null
                    distanceMeters:
                      type: number
                      nullable: true
                      example: null
                    rpe:
                      type: number
                      nullable: true
                      example: null
                    completed:
                      type: boolean
                      example: false
              exerciseCount:
                type: integer
                example: 2
                description: Superset wrappers only.
              rounds:
                type: integer
                example: 4
                description: Superset wrappers only.
              data:
                type: array
                description: >-
                  Empty for a standalone exercise; the member exercise items for
                  a `type: "superset"` block.
                items:
                  $ref: >-
                    #/components/schemas/PublicWorkoutSourceWorkoutGroupedExerciseItem
        session:
          type: object
          nullable: true
          description: >-
            The current/navigation session, or null. Recurring sequence days
            select only the newest active attempt and return null after
            completion. Multi-week/calendar programmes fall back to the latest
            completed attempt. Stopped/cancelled attempts are excluded from
            current/resumable selection.
          properties:
            id:
              type: string
              example: 67f1234567890abcdef1234
            status:
              type: string
              enum:
                - in_progress
                - paused
                - completed
              example: in_progress
            startedAt:
              type: string
              format: date-time
              example: '2026-04-12T10:00:00.000Z'
              nullable: true
            programmeScheduleItemId:
              oneOf:
                - type: string
                  example: 67f1234567890abcdef1234
                - type: 'null'
            plannedDate:
              type: string
              format: date
              pattern: ^\d{4}-\d{2}-\d{2}$
              example: '2026-09-08'
        resumeState:
          type: string
          enum:
            - create
            - start
            - continue
            - completed
          example: create
        requiresResumePrompt:
          type: boolean
          example: false
        requiresConfirmation:
          type: boolean
          example: false
        confirmationToken:
          type: string
          example: null
          nullable: true
        confirmationTokenExpiresAt:
          type: string
          format: date-time
          example: null
          nullable: true
    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'
    PublicWorkoutSourceWorkoutPlanDetail:
      type: object
      properties:
        runningPlan:
          $ref: '#/components/schemas/PublicWorkoutSourceRunningPlanMetadata'
          description: >-
            Optional running race goal; omitted when the cardio feature gate is
            disabled.
        _id:
          type: string
          example: 67f1234567890abcdef1234
        companyId:
          type: string
          example: 67f1234567890abcdef1234
        clientId:
          type:
            - string
            - 'null'
          example: null
        sourceTemplateId:
          type:
            - string
            - 'null'
          example: null
        addedBy:
          type: string
          example: 67f1234567890abcdef1234
        addedByRole:
          type: string
          enum:
            - Coach
            - Client
            - Fitsociety
            - Admin
          example: Coach
        status:
          type: string
          enum:
            - Active
            - Inactive
            - Draft
          example: Draft
        templateType:
          type: string
          enum:
            - Template
            - Assigned
          example: Template
        name:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutLocalizedTextArray'
        description:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutLocalizedTextArray'
        difficulty:
          type: string
          enum:
            - Beginner
            - Intermediate
            - Advanced
          example: Intermediate
        intensity:
          type: string
          enum:
            - Low
            - Medium
            - High
          example: Medium
        duration:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutPlanDuration'
        images:
          type: array
          items:
            $ref: '#/components/schemas/PublicWorkoutSourceWorkoutImageAsset'
        videos:
          type: array
          items:
            $ref: '#/components/schemas/PublicWorkoutSourceWorkoutVideoAsset'
        category:
          type: string
          enum:
            - Agility & Speed
            - Strength
            - Hypertrophy
            - Strength - Dynamic
            - Strength - Explosive
            - Strength - Static
            - Cardio
            - Cardio - Duration
            - Cardio - Interval
            - HIIT
            - Crossfit
            - Mobility
            - Stretching
            - Core
            - Coordination & Balance
            - Movement Prep
            - Functional Training
            - Recovery
            - Sports
            - Martial Arts
            - Yoga
            - Other
            - GROUP_WORKOUT_TEMPLATE
            - Plyometric
            - Cycling
            - Cardio - interval
            - Mobilisation
            - Stabilisation
            - Daily Living
            - Target zone
            - Respiration
            - Breathing
            - Massage
            - Outdoor sports
            - Indoor sports
            - Dance
            - Group Lessons
            - Martial arts
            - Material Arts
            - Fight skills
            - Mind and body
            - ''
            - default
          example: Strength
        goal:
          type: string
          enum:
            - Weight Loss
            - Hypertrophy
            - Endurance
            - Flexibility
            - General Fitness
            - Strength
          example: Strength
        periodizationType:
          type: string
          enum:
            - Linear
            - Non-Linear
            - Block
            - Undulating
            - None
          example: Linear
        popularity:
          type: number
          example: 0
        useDefaultExerciseSettings:
          type: boolean
          example: true
        defaultExerciseValues:
          oneOf:
            - $ref: >-
                #/components/schemas/PublicWorkoutSourceWorkoutDefaultExerciseValues
            - type: 'null'
        planMoments:
          type: array
          items:
            $ref: '#/components/schemas/PublicWorkoutSourceWorkoutPlanMomentDocument'
        visibility:
          type: string
          enum:
            - Everyone
            - Company
            - Fitsociety
          example: Company
        isDeleted:
          type: boolean
          example: false
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
          example: null
        createdAt:
          type: string
          format: date-time
          example: '2026-04-12T10:00:00.000Z'
        updatedAt:
          type: string
          format: date-time
          example: '2026-04-12T10:00:00.000Z'
    PublicWorkoutSourceWorkoutPlanMomentDetail:
      type: object
      properties:
        name:
          type: string
          example: Day 1
        description:
          type: string
          example: Upper body push.
        dayOrder:
          type: number
          example: 1
        order:
          type: number
          example: 0
        weekNumber:
          type: integer
          minimum: 1
          example: 1
        sessionOrder:
          type: integer
          minimum: 1
          example: 1
        date:
          type: string
          example: '2026-04-15'
        scoring:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutPlanMomentScoring'
        exercises:
          type: array
          items:
            $ref: >-
              #/components/schemas/PublicWorkoutSourceWorkoutWorkoutExerciseDocument
        isDeleted:
          type: boolean
          example: false
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
          example: null
        createdAt:
          type: string
          format: date-time
          example: '2026-04-12T10:00:00.000Z'
        updatedAt:
          type: string
          format: date-time
          example: '2026-04-12T10:00:00.000Z'
    PublicWorkoutSourceWorkoutGroupedExerciseItem:
      type: object
      properties:
        id:
          type: string
          example: 67f1234567890abcdef1234
        name:
          type: string
          example: Barbell Bench Press
        primaryMuscle:
          type: string
          enum:
            - Chest
            - Back
            - Lats
            - Traps
            - Shoulders
            - Biceps
            - Triceps
            - Forearms
            - Core
            - Abs
            - Obliques
            - Glutes
            - Quads
            - Hamstrings
            - Calves
            - Adductors
            - Abductors
            - Hip Flexors
            - Full Body
            - Cardio / Conditioning
            - Neck
            - Lower Back
          example: Chest
        secondaryMuscles:
          type: array
          items:
            type: string
            enum:
              - Chest
              - Back
              - Lats
              - Traps
              - Shoulders
              - Biceps
              - Triceps
              - Forearms
              - Core
              - Abs
              - Obliques
              - Glutes
              - Quads
              - Hamstrings
              - Calves
              - Adductors
              - Abductors
              - Hip Flexors
              - Full Body
              - Cardio / Conditioning
              - Neck
              - Lower Back
        primaryJoint:
          type: string
          enum:
            - ''
            - Ankle
            - Combination
            - Core
            - Elbow
            - Fingers
            - Hip
            - Knee
            - Neck
            - Shoulder
            - Spine
            - Wrist
          example: Shoulder
        equipment:
          type: array
          items:
            type: string
            enum:
              - Dumbbells
              - AdjustableDumbbells
              - Kettlebell
              - AdjustableKettlebell
              - CompetitionKettlebell
              - Medicineball
              - SlamBall
              - WallBall
              - Weightplate
              - BumperPlates
              - FractionalPlates
              - LoadableDumbbellHandle
              - Sandbag
              - StrongmanSandbag
              - Bulgarianbag
              - Aquabag
              - Aquaball
              - Hydrovest
              - MagneticBell
              - Macebell
              - SteelClub
              - IndianClub
              - Barbell
              - OlympicBarbell
              - TechniqueBar
              - EZBar
              - TrapBar
              - SafetySquatBar
              - SwissBar
              - CamberedBar
              - AxleBar
              - Landmine
              - Bench
              - FlatBench
              - AdjustableBench
              - InclineBench
              - DeclineBench
              - SealRowBench
              - HipThrustBench
              - BenchPressRack
              - SquatRack
              - SquatStand
              - PowerRack
              - WallMountedRack
              - HalfRack
              - SmithMachine
              - Monolift
              - JammerArms
              - BarbellJack
              - WeightTree
              - PlateStorage
              - DeadliftPlatform
              - Rig
              - StrengthMachinesPlateloaded
              - StrengthMachinesWeightstack
              - StrengthMachinesPneumatic
              - MultiGym
              - LegPressMachine
              - VerticalLegPressMachine
              - LeverageSquatMachine
              - LinearHackSquatMachine
              - BeltSquatMachine
              - PendulumSquatMachine
              - VSquatMachine
              - HackSquatMachine
              - LegExtensionMachine
              - LegCurlMachine
              - SeatedLegCurlMachine
              - LyingLegCurlMachine
              - StandingLegCurlMachine
              - StandingCalfRaiseMachine
              - SeatedCalfRaiseMachine
              - CalfPressMachine
              - HipThrustMachine
              - GluteDriveMachine
              - GluteKickbackMachine
              - HipExtensionMachine
              - HipAbductionMachine
              - HipAdductionMachine
              - ChestPressMachine
              - VerticalChestPressMachine
              - InclineChestPressMachine
              - DeclineChestPressMachine
              - IsoLateralChestPressMachine
              - IsoLateralInclinePressMachine
              - ShoulderPressMachine
              - IsoLateralShoulderPressMachine
              - MultiPressMachine
              - LateralRaiseMachine
              - RearDeltMachine
              - PecDeckMachine
              - PulloverMachine
              - LatPulldownMachine
              - IsoLateralLatPulldownMachine
              - AssistedPullupMachine
              - AssistedDipMachine
              - SeatedDipMachine
              - SeatedRowMachine
              - LowRowMachine
              - HighRowMachine
              - IsoLateralRowMachine
              - ChestSupportedRowMachine
              - TBarRowMachine
              - BicepsCurlMachine
              - PreacherCurlMachine
              - TricepsExtensionMachine
              - AbCrunchMachine
              - AbCoasterMachine
              - RotaryTorsoMachine
              - BackExtensionMachine
              - SeatedBackExtensionMachine
              - HyperextensionBench
              - ReverseHyper
              - GHD
              - Kinesis
              - Pulley
              - CableMachine
              - CableStation
              - CableColumn
              - CableCrossover
              - DualAdjustablePulley
              - SingleCableTower
              - FunctionalTrainer
              - TotalGymGTS
              - Gymstick
              - ViPR
              - RipTrainer
              - Battlerope
              - ProwlerSled
              - FarmersHandles
              - Yoke
              - Tire
              - Sledgehammer
              - TorqueTank
              - SledTrack
              - WallBallTarget
              - AgilityPoles
              - MiniHurdles
              - SprintParachute
              - PullUpBar
              - Parallelbars
              - DipBars
              - Equalizer
              - Suspensiontrainer
              - SuspensionSlingTrainer
              - GymnasticRings
              - MonkeyBars
              - PegBoard
              - RopeClimb
              - Wall
              - StallBars
              - DoorPullUpBar
              - PushUpHandles
              - AbStraps
              - Boxstep
              - SoftPlyoBox
              - Hurdle
              - Speedladder
              - Parallettes
              - NordicBench
              - SissySquatBench
              - Cardio
              - Treadmill
              - CurvedTreadmill
              - AirRunner
              - AssaultRunner
              - StationaryBike
              - UprightBike
              - RecumbentBike
              - BikeErg
              - SpinBike
              - AirBike
              - Rower
              - WaterRower
              - FanRower
              - ArmErgometer
              - SkiErg
              - Elliptical
              - ArcTrainer
              - NuStep
              - StairClimber
              - StepMill
              - JacobsLadder
              - VersaClimber
              - Bosu
              - Balanceball
              - Exerciseball
              - PilatesTennisball
              - PilatesRing
              - YogaMat
              - YogaBlock
              - YogaWheel
              - StretchStrap
              - MobilityStick
              - MassageBall
              - PeanutMassageBall
              - Airpad
              - Balanceboard
              - BalancePad
              - WobbleBoard
              - Glidedisc
              - Foamroller
              - Elasticbands
              - TherapyBand
              - Resistanceband
              - MiniBand
              - PullUpAssistBand
              - Powertube
              - AnkleWeights
              - SlantBoard
              - Vibrationtraining
              - CableRope
              - StraightBarAttachment
              - CurlBarAttachment
              - LatBarAttachment
              - TricepsBarAttachment
              - RowHandle
              - DHandle
              - DoubleDHandle
              - AnkleCuff
              - CableCuff
              - LandmineHandle
              - MagGripAttachment
              - DipBelt
              - AbWheel
              - WristRoller
              - FatGrip
              - Chain
              - DoorAnchor
              - JumpRope
              - SpeedRope
              - WeightedJumpRope
              - SledHarness
              - LiftingStraps
              - LiftingHooks
              - WristWraps
              - WeightliftingBelt
              - Clubbel
              - Stick
              - Bodybow
              - BuddySystem
              - Multinet
              - Flowin
              - Aerialhoop
              - Dancingpole
              - Trapeze
              - HulaHoop
              - Trampoline
              - XCO
              - PilatesReformer
              - PilatesChair
              - PilatesCadillac
              - PilatesBarrel
              - PilatesSpringboard
              - BalanceBeam
              - TreatmentTable
              - RehabTable
              - SlideBoard
        difficulty:
          type: string
          enum:
            - ''
            - Beginner
            - Intermediate
            - Advanced
          example: Intermediate
        intensity:
          type: string
          enum:
            - ''
            - Beginner
            - Below Average
            - Average
            - Above Average
            - High Intensity
          example: Above Average
        visibility:
          type: string
          enum:
            - Everyone
            - Company
            - Fitsociety
          example: Company
        tags:
          type: array
          items:
            type: string
        thumbnail:
          type:
            - string
            - 'null'
          format: uri
          example: https://cdn.example.com/exercises/bench-thumb.jpg
    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
    PublicWorkoutSourceRunningPlanMetadata:
      type: object
      properties:
        goal:
          $ref: '#/components/schemas/PublicWorkoutSourceRunningPlanGoal'
        goalUpdatedAt:
          type: string
          format: date-time
          readOnly: true
        goalUpdatedBy:
          type: string
          readOnly: true
        adaptationRevision:
          type: integer
          minimum: 0
          readOnly: true
        lastReviewedWeek:
          type: integer
          minimum: 0
          maximum: 104
          readOnly: true
        lastAdaptedAt:
          type: string
          format: date-time
          readOnly: true
        generation:
          $ref: '#/components/schemas/PublicWorkoutSourceRunningPlanGeneration'
        weekSummaries:
          type: array
          items:
            $ref: '#/components/schemas/PublicWorkoutSourceRunningPlanPreviewWeek'
    PublicWorkoutSourceWorkoutLocalizedTextArray:
      type: array
      minItems: 1
      items:
        $ref: '#/components/schemas/PublicWorkoutSourceWorkoutLocalizedTextEntry'
      example:
        - lang: en
          value: Full Body Strength
        - lang: nl
          value: Full Body Kracht
    PublicWorkoutSourceWorkoutPlanDuration:
      type: object
      properties:
        startDate:
          type: string
          example: '2026-04-15'
        endDate:
          type: string
          example: '2026-06-15'
        hasEndDate:
          type: boolean
          example: true
    PublicWorkoutSourceWorkoutImageAsset:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          format: uri
          example: https://cdn.example.com/workouts/plan-cover.jpg
        width:
          type:
            - number
            - 'null'
          example: 1280
        height:
          type:
            - number
            - 'null'
          example: 720
    PublicWorkoutSourceWorkoutVideoAsset:
      type: object
      required:
        - url
        - platform
      properties:
        url:
          type: string
          format: uri
          example: https://cdn.example.com/workouts/demo.mp4
        platform:
          type: string
          enum:
            - s3
            - youtube
            - tiktok
          example: s3
        videoId:
          type: string
          example: ''
        thumbnail:
          type: string
          format: uri
          example: https://cdn.example.com/workouts/demo-thumb.jpg
        duration:
          type:
            - number
            - 'null'
          example: 84
        width:
          type:
            - number
            - 'null'
          example: 1920
        height:
          type:
            - number
            - 'null'
          example: 1080
    PublicWorkoutSourceWorkoutDefaultExerciseValues:
      type: object
      required:
        - sets
        - reps
        - rest
        - repTempo
      properties:
        sets:
          type: number
          minimum: 1
          example: 3
        reps:
          oneOf:
            - type: string
              pattern: ^\d+(-\d+)?$
            - type: number
              minimum: 1
          example: 10-12
        rest:
          type: number
          minimum: 0
          example: 90
        weight:
          type: number
          example: 0
        repTempo:
          type: string
          example: '3010'
        duration:
          type: number
          example: 0
    PublicWorkoutSourceWorkoutPlanMomentDocument:
      type: object
      properties:
        _id:
          type: string
          example: 67f1234567890abcdef1234
        name:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutLocalizedTextArray'
        description:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutLocalizedTextArray'
        dayOrder:
          type: number
          example: 1
        order:
          type: number
          example: 0
        weekNumber:
          type: integer
          minimum: 1
          example: 1
        sessionOrder:
          type: integer
          minimum: 1
          example: 1
        date:
          type: string
          example: '2026-04-15'
        scoringType:
          type: string
          enum:
            - standard
            - forTime
            - amrap
            - emom
            - tabata
            - maxLoad
          default: standard
          example: forTime
          description: >-
            Scoring mechanism. Must not be `standard` when `descriptionOnly` is
            true.
        targetValue:
          type: number
          nullable: true
          minimum: 0
          example: null
        descriptionOnly:
          type: boolean
          default: false
          example: true
          description: >-
            Marks an exercise-free scored day: the full workout lives in
            `description` (required), `exercises` must stay empty, `scoringType`
            must not be standard, and amrap/emom/tabata require their full
            `timeDomain`. Completing the day requires a manual `wodResult`.
            Enforced on every write path, including client day edits. Moments
            that merely have no exercises are NOT scored unless this is true.
        timeDomain:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutScoringTimeDomain'
        scoreValidation:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutScoreValidation'
        exercises:
          type: array
          items:
            $ref: >-
              #/components/schemas/PublicWorkoutSourceWorkoutWorkoutExerciseDocument
        isDeleted:
          type: boolean
          example: false
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
          example: null
        createdAt:
          type: string
          format: date-time
          example: '2026-04-12T10:00:00.000Z'
        updatedAt:
          type: string
          format: date-time
          example: '2026-04-12T10:00:00.000Z'
    PublicWorkoutSourceWorkoutPlanMomentScoring:
      type: object
      nullable: true
      description: >-
        Scoring of a plan day. Null for an ordinary standard day.
        `acceptsManualResult` is true only for exercise-free scored days
        (`descriptionOnly`), which take a `wodResult` on PATCH
        /app/v1/workout/performance/sessions/{sessionId}/complete. `result` is
        the saved score of the selected session, or null.
      properties:
        scoringType:
          type: string
          enum:
            - standard
            - forTime
            - amrap
            - emom
            - tabata
            - maxLoad
          example: forTime
        descriptionOnly:
          type: boolean
          example: true
        acceptsManualResult:
          type: boolean
          example: true
        targetValue:
          type: number
          nullable: true
          example: null
        timeDomain:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutScoringTimeDomain'
        scoreValidation:
          $ref: '#/components/schemas/PublicWorkoutSourceWorkoutScoreValidation'
        result:
          allOf:
            - $ref: '#/components/schemas/PublicWorkoutSourceWorkoutManualWodResult'
          nullable: true
    PublicWorkoutSourceWorkoutWorkoutExerciseDocument:
      type: object
      properties:
        _id:
          type: string
          example: 67f1234567890abcdef1234
        exerciseId:
          type: string
          example: 67f1234567890abcdef1234
        type:
          type: string
          enum:
            - reps
            - time
            - distance
          example: reps
        minReps:
          type: number
          example: 6
        maxReps:
          type: number
          example: 8
        notes:
          type: string
          example: Pause 1 second on the chest.
        sets:
          type: number
          example: 4
        metric:
          type: string
          example: kg
        rest:
          type: number
          example: 120
        intensity:
          type: string
          enum:
            - Low
            - Medium
            - High
          example: High
        difficulty:
          type: string
          enum:
            - Beginner
            - Intermediate
            - Advanced
          example: Intermediate
        groupId:
          type: string
          example: super-a
        rpe:
          type: number
          example: 8
        rmPercentage:
          type: number
          example: 75
        tempo:
          type: string
          example: '3010'
        perSetTrackingEnabled:
          type: boolean
          example: true
        rpeEnabled:
          type: boolean
          example: false
          description: >-
            Master RPE switch for this plan exercise. False hides current
            targets and inputs without clearing prescriptions or recorded
            history. Missing legacy values retain RPE when an exercise target or
            per-set preference exists. Independent from showSetRpe.
        showSetRpe:
          type: boolean
          example: true
          description: >-
            Stored per-set RPE preference. Live input is visible only when RPE
            is enabled; authoring retains this preference while rpeEnabled is
            false.
        setsData:
          type: array
          items:
            $ref: '#/components/schemas/PublicWorkoutSourceWorkoutSetData'
        setupSettingsEnabled:
          type: boolean
          example: true
          description: >-
            Enables the exercise-level machine or equipment setup settings
            block.
        setupFields:
          type: array
          maxItems: 8
          items:
            $ref: '#/components/schemas/PublicWorkoutSourceWorkoutExerciseSetupField'
        order:
          type: number
          example: 0
        isDeleted:
          type: boolean
          example: false
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
          example: null
        createdAt:
          type: string
          format: date-time
          example: '2026-04-12T10:00:00.000Z'
        updatedAt:
          type: string
          format: date-time
          example: '2026-04-12T10:00:00.000Z'
    PublicWorkoutSourceRunningPlanGoal:
      type: object
      additionalProperties: false
      required:
        - distance
        - goalTimeSec
        - raceDate
      properties:
        distance:
          type: string
          enum:
            - 5K
            - 10K
            - half
            - marathon
        goalTimeSec:
          type: number
          exclusiveMinimum: 0
          description: >-
            Finish time in seconds. Localized numeric strings are accepted on
            input.
        raceDate:
          type: string
          format: date
          description: Canonical YYYY-MM-DD athlete calendar date.
        acceptGoalAsChallenge:
          type: boolean
          default: false
    PublicWorkoutSourceRunningPlanGeneration:
      type: object
      readOnly: true
      properties:
        templateKey:
          type: string
          enum:
            - 5K
            - 10K
            - half
            - marathon
        variant:
          type: boolean
        runWeekdays:
          type: array
          uniqueItems: true
          items:
            type: integer
            minimum: 1
            maximum: 7
        qualityWeekdays:
          type: array
          uniqueItems: true
          items:
            type: integer
            minimum: 1
            maximum: 7
        longRunWeekday:
          type: integer
          minimum: 1
          maximum: 7
        phases:
          type: object
          properties:
            base:
              type: integer
            threshold:
              type: integer
            sharpen:
              type: integer
        taperWeeks:
          type: integer
          enum:
            - 1
            - 2
        sourceVersion:
          type: string
          enum:
            - plansjablonen-v259-1
        policyVersion:
          type: string
          enum:
            - safety-calendar-v1
        generatedAt:
          type: string
          format: date-time
        generatedBy:
          type: string
        profileUpdatedAt:
          type: string
          format: date-time
        totalWeeks:
          type: integer
          minimum: 1
          maximum: 104
        concreteWeeks:
          type: integer
          minimum: 1
          maximum: 3
        baselineKm:
          type: number
        peakKm:
          type: number
        thresholdSecPerKm:
          type: number
        warnings:
          type: array
          items:
            type: string
    PublicWorkoutSourceRunningPlanPreviewWeek:
      type: object
      properties:
        weekNumber:
          type: integer
        weekStart:
          type: string
          format: date
        phase:
          type: integer
          enum:
            - 1
            - 2
            - 3
        phaseName:
          type: string
          enum:
            - Base building
            - Threshold development
            - Sharpening
        theme:
          type: string
          enum:
            - Base building
            - Threshold development
            - Sharpening
        weekKind:
          type: string
          enum:
            - build
            - race
            - taper
            - sharpen
            - deload
        rotationWeek:
          type: integer
          enum:
            - 1
            - 2
            - 3
        targetVolumeKm:
          type: number
        concrete:
          type: boolean
        requestedVolumeKm:
          type: number
        allocatedKm:
          type: number
        remainingKm:
          type: number
        concreteRequested:
          type: boolean
        sessions:
          type: array
          items:
            $ref: '#/components/schemas/PublicWorkoutSourceRunningPlanPreviewSession'
    PublicWorkoutSourceWorkoutLocalizedTextEntry:
      type: object
      required:
        - lang
        - value
      properties:
        lang:
          type: string
          enum:
            - en
            - nl
            - fr
            - de
            - es
          example: en
        value:
          type: string
          example: Full Body Strength
    PublicWorkoutSourceWorkoutScoringTimeDomain:
      type: object
      nullable: true
      description: >-
        Clock prescription, same contract as a WOD `timeDomain`. Allowed fields
        depend on `scoringType`: amrap → windowSeconds (required); forTime →
        timeCapSeconds, rounds (defaults to 1); emom → intervalSeconds,
        intervalCount (both required); tabata → workSeconds, restSeconds,
        intervalCount (all required); standard/maxLoad → none.
      properties:
        windowSeconds:
          type: integer
          nullable: true
          minimum: 1
          example: null
        timeCapSeconds:
          type: integer
          nullable: true
          minimum: 1
          example: 900
        rounds:
          type: integer
          nullable: true
          minimum: 1
          example: 3
        intervalSeconds:
          type: integer
          nullable: true
          minimum: 1
          example: null
        intervalCount:
          type: integer
          nullable: true
          minimum: 1
          example: null
        workSeconds:
          type: integer
          nullable: true
          minimum: 1
          example: null
        restSeconds:
          type: integer
          nullable: true
          minimum: 0
          example: null
    PublicWorkoutSourceWorkoutScoreValidation:
      type: object
      nullable: true
      description: >-
        Optional result caps. timeCapSeconds and expectedIntervals are derived
        from `timeDomain` when one is set.
      properties:
        timeCapSeconds:
          type: integer
          nullable: true
          minimum: 1
          example: 900
        maxReps:
          type: integer
          nullable: true
          minimum: 1
          example: null
        expectedIntervals:
          type: integer
          nullable: true
          minimum: 1
          example: null
    PublicWorkoutSourceWorkoutManualWodResult:
      type: object
      description: >-
        Type-specific manual score, the same shape as the WOD `wodResult`. Only
        the fields of the day's scoringType are accepted: amrap →
        roundsCompleted, repsPerRound, extraReps, totalReps (total = rounds ×
        repsPerRound + extraReps, extraReps < repsPerRound); forTime →
        elapsedSeconds, finishedBeforeCap, totalReps (reps required when not
        finished before the cap); emom/tabata → intervalReps, totalReps (sum of
        intervals; count must match intervalCount when set); maxLoad →
        maxLoadKg. The stored copy of a forTime result also carries
        timeCapSeconds.
      properties:
        roundsCompleted:
          type: integer
          minimum: 0
          example: 5
        repsPerRound:
          type: integer
          minimum: 1
          example: 30
        extraReps:
          type: integer
          minimum: 0
          example: 12
        totalReps:
          type: integer
          minimum: 0
          example: 162
        intervalReps:
          type: array
          items:
            type: integer
            minimum: 0
          example:
            - 12
            - 11
            - 10
        elapsedSeconds:
          type: number
          minimum: 0
          example: 742
        finishedBeforeCap:
          type: boolean
          example: true
        timeCapSeconds:
          type: integer
          nullable: true
          readOnly: true
          example: 900
        maxLoadKg:
          type: number
          minimum: 0
          example: 120
    PublicWorkoutSourceWorkoutSetData:
      type: object
      properties:
        setNumber:
          type: integer
          minimum: 1
          example: 1
        setType:
          type: string
          enum:
            - 'N'
            - W
            - D
            - F
          example: 'N'
          description: 'Planned set type: N normal, W warm-up, D drop set, F to failure.'
        metric:
          type: string
          example: '12'
        repetition:
          type: string
          example: 8-12
        weight:
          type: number
          example: 60
        rest:
          type: number
          example: 90
        rpe:
          type:
            - number
            - 'null'
          minimum: 0
          maximum: 10
          example: 7.5
          description: >-
            Optional target RPE for this set. It does not inherit the
            exercise-level RPE value.
        duration:
          type: number
          example: 45
        distance:
          type: number
          example: 250
    PublicWorkoutSourceWorkoutExerciseSetupField:
      type: object
      required:
        - key
        - label
      properties:
        key:
          type: string
          example: seat
        label:
          type: string
          example: Seat
        type:
          type: string
          enum:
            - text
            - number
            - select
          example: text
        unit:
          type: string
          example: ''
        options:
          type: array
          items:
            type: string
          example:
            - '1'
            - '2'
            - '3'
            - '4'
        order:
          type: number
          example: 1
        required:
          type: boolean
          example: false
        enabled:
          type: boolean
          example: true
        defaultValue:
          oneOf:
            - type: string
            - type: number
          example: 3
    PublicWorkoutSourceRunningPlanPreviewSession:
      type: object
      properties:
        weekday:
          type: integer
          minimum: 1
          maximum: 7
        code:
          type: string
          enum:
            - drempel_c
            - drempel_r
            - interval
            - doeltempo
            - zone2
            - long_run
        sessionType:
          type: string
          enum:
            - threshold_continuous
            - threshold_reps
            - interval
            - race_pace
            - zone2
            - long_run
        controlMode:
          type: string
          enum:
            - hr
            - pace
        longRunTargetMinutes:
          type: number
        ladder:
          $ref: '#/components/schemas/PublicWorkoutSourceCardioLadderStep'
        continuousMinutes:
          type: number
        recoveryRangeSec:
          type: object
          properties:
            low:
              type: number
            high:
              type: number
        cardio:
          $ref: '#/components/schemas/PublicWorkoutSourceProgrammeScheduleItemCardio'
        totals:
          type: object
          properties:
            durationSec:
              type: number
              minimum: 0
            distanceM:
              type: number
              minimum: 0
            plannedDurationMinutes:
              type: number
              minimum: 0
            targetDistanceMeters:
              type: number
              minimum: 0
            zoneTimeSec:
              type: object
              additionalProperties:
                type: number
                minimum: 0
          additionalProperties: false
    PublicWorkoutSourceCardioLadderStep:
      type: object
      required:
        - step
        - reps
        - kmPerRep
      properties:
        step:
          type: integer
          minimum: 1
          maximum: 8
        reps:
          type: integer
          minimum: 1
        kmPerRep:
          type: number
          exclusiveMinimum: 0
    PublicWorkoutSourceProgrammeScheduleItemCardio:
      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:
            $ref: '#/components/schemas/PublicWorkoutSourceCardioBlock'
          default: []
        sourceTemplateId:
          type:
            - string
            - 'null'
          example: null
    PublicWorkoutSourceCardioBlock:
      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:
            $ref: '#/components/schemas/PublicWorkoutSourceCardioStep'
          default: []
    PublicWorkoutSourceCardioStep:
      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:
          $ref: '#/components/schemas/PublicWorkoutSourceCardioTarget'
          description: >-
            Binding target. When the session has a controlMode, its kind must
            match it (pace: paceZone/pacePct/pace; hr: hrZone/hrPct/hr).
        secondaryTarget:
          $ref: '#/components/schemas/PublicWorkoutSourceCardioTarget'
          description: >-
            Informational guidance only, never a second hard limit. With a
            controlMode it must use the other signal and requires target.
        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:
          $ref: '#/components/schemas/PublicWorkoutSourceCardioCadence'
          description: Cycling rpm or rowing strokes/minute only.
    PublicWorkoutSourceCardioTarget:
      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
    PublicWorkoutSourceCardioCadence:
      type: object
      additionalProperties: false
      required:
        - low
        - high
      properties:
        low:
          type: number
          minimum: 0
        high:
          type: number
          minimum: 0
  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.