EGYM Equipment Vendor API (standalone clients)

Device-to-server API for equipment vendors integrating cardio, strength and measurement hardware directly with EGYM Cloud. Covers OAuth token exchange (RFID, NFC wallet, encrypted/obfuscated user id, refresh token grants), user profile read/update, terms-and-conditions acceptance, RFID assignment, strength / cardio / open-exercise workout submission, body / cardio / flexibility measurement submission and history, cardio tests and reminders, training plans, activity levels, workout points and machine heartbeat. 31 operations, the largest EGYM surface.

OpenAPI Specification

egym-equipment-vendor-standalone-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Equipment Vendor API (for standalone clients)
  description: "At EGYM, we believe that fitness is the soul of healthy living. Work together with partners to help us bringing\
    \ new ways of working out to\nmillions of gym members, and new ways of prescribing exercises to hundred of thousands of\
    \ gym trainers, all around the world.\n\nEGYM provides a Fitness Platform for the Connected Gym so you can help us with\
    \ the mission to ***make the gym work for everyone***.\nEGYM provides a global account that is not scoped for a specific\
    \ tenant, brand or gym. The account is called EGYM ID. The EGYM ID allows\nusers to use different services of the gym.\
    \ The EGYM ID is used for the login to EGYM hardware and software products and conneceted equipment.\n\nEGYM works with\
    \ the best of breed of the fitness industry. In this documentation, we provide tools and info needed to build a variety\
    \ of workout\nexperiences that integrate directly with the EGYM Ecosystem. We are happy to welcome you as a partner of\
    \ EGYM.\n\n---\n\n# \U0001F4E6 Changelog of Documentation\n\n| Version | Changes |\n|---------|---------|\n| **1.2.0**\
    \ | ✅ Added support for **Genius Training Plans** — see [`GET /api/v1/cardio/training-plans`] and [`GET /api/v1/strength/training-plans`]|\n\
    | **1.1.0** | \U0001F510 Introduced **NFC-based login** via Apple/Google Wallet — see [`POST /api/v1/oauth/token`](#tag/OAuth/operation/token)\
    \ |\n\n---\n\n# \U0001F510 Authentication\n\nThe Equipment Vendor API authentication is based on the OAuth 2.0 as specified\
    \ in the [RFC6749](https://tools.ietf.org/html/rfc6749),\nmore concretely on the [Resource Owner Password Credentials\
    \ Grant](https://tools.ietf.org/html/rfc6749#page-37) due to constraint\nenvironment that can be found in our partner\
    \ devices, i.e. devices with no screen or using the RFID for user identification.\n\nCurrently, different methods for\
    \ obtaining the Access Token are made available:\n\n- By specifying **user credentials**\n- By specifying **RFID**\n-\
    \ **By specifying NFC (Wallet) credentials** *(since v1.1.0)*\n\nThe OAuth `client_id` and `client_secret` are issued\
    \ by EGYM to each partner (vendor) for each gym. These are used in a `Basic` authentication header as:\n\n```\nAuthorization:\
    \ Basic Base64(client_id:client_secret)\n```\n\n---\n\n## \U0001F511 User Credentials (EGYM ID)\n\n_This is the classic\
    \ Resource Owner Password Grant._\n\n\n```http\nPOST /api/v1/oauth/token\nAuthorization: Basic <Base64(client_id:client_secret)>\n\
    Content-Type: application/x-www-form-urlencoded\n\ngrant_type=password&machine_type=bike&serial_number=ser123&username=johndoe&password=•••\n\
    ```\n\n---\n\n## \U0001F4F6 User RFID\n\n\n```http\nPOST /api/v1/oauth/token\nAuthorization: Basic <Base64(client_id:client_secret)>\n\
    Content-Type: application/x-www-form-urlencoded\n\ngrant_type=rfid&machine_type=bike&serial_number=ser123&rfid=AB12CD34&rfid_format=MIFARE\n\
    ```\n\n---\n\n## \U0001F4F1 NFC Login (Apple / Google Wallet)\n\n_Introduced in v1.1.0_\n\nThis method uses NFC payloads\
    \ from Apple/Google Wallet. Use `grant_type=nfc` and supply:\n\n- `payload`: the NFC data string\n- `transponder_type`:\
    \ either `APPLE` or `GOOGLE`\n- One of:\n  - `issuer_id`: the Wallet issuer identifier (e.g., `com.egym.apple`)\n  - `configuration_index`:\
    \ the DotOrigin VTAP slot ID\n\nExamples:\n\n```APPLE\nPOST /api/v1/oauth/token\nAuthorization: Basic <Base64(client_id:client_secret)>\n\
    Content-Type: application/x-www-form-urlencoded\n\ngrant_type=nfc&machine_type=bike&serial_number=ser123&payload=abc123&transponder_type=APPLE&issuer_id=com.egym.apple\n\
    ```\n\n```GOOGLE\nPOST /api/v1/oauth/token\nAuthorization: Basic <Base64(client_id:client_secret)>\nContent-Type: application/x-www-form-urlencoded\n\
    \ngrant_type=nfc&machine_type=bike&serial_number=ser123&payload=abc123&transponder_type=GOOGLE&issuer_id=123456789\n```\n\
    \n```VTAP\nPOST /api/v1/oauth/token\nAuthorization: Basic <Base64(client_id:client_secret)>\nContent-Type: application/x-www-form-urlencoded\n\
    \ngrant_type=nfc&machine_type=bike&serial_number=ser123&payload=abc123&configuration_index=2\n```\n\n\n## \U0001F4DC Terms\
    \ and Conditions Handling\n\nSome users may not have accepted the latest EGYM Terms and Conditions (T&C). In that case,\
    \ the user details will indicate that the user did not accepted them yet and partners must handle T&C interaction:\n\n\
    ### 1. Retrieve the T&C and privacy policy\n\n```T&C\nGET /api/v1/ressources/terms-and-conditions\nContent-Type: text/html\n\
    \nlocale=en_US\n```\n\n```PP\nGET /api/v1/ressources/privacy-policy\nContent-Type: text/html\n\nlocale=en_US\n```\nResponse\
    \ will be terms.\n\n\n### 2. Prompt the user to accept or decline\n\n- If **accepted**, proceed to step 3\n- If **declined**,\
    \ exit the login flow gracefully\n\n### 3. Submit confirmation of acceptance\n\n```http\nPUT /api/v1/users/terms-and-conditions\n\
    Authorization: Bearer {access_token}\nContent-Type: application/json\n\nlocale=en_US\n```\n\n---\n\n## ⏱ Rate Limit\n\n\
    Authentication is rate-limited per `client_id`: **10 requests per second**.\n\n---\n\n# \U0001F504 Integration Flow Overview\n\
    \n```plaintext\n[Authenticate (POST /oauth/token)]\n              ↓\n[Get User Details (GET /users)]\n              ↓\n\
    \  ┌────────────────────────────┬────────────────────────────┐\n  │                            │                     \
    \       │\n  │   Fitness Equipment        │   Measurement Devices       │\n  │                            │          \
    \                  │\n  │ - Get Training Plan        │ - Submit Measurements       │\n  │   → GET /training-plans    │\
    \   → POST /measurements/*    │\n  │ - Submit Workout           │                            │\n  │   → POST /workouts\
    \         │                            │\n  └────────────────────────────┴────────────────────────────┘\n```\n\n---\n\n\
    # ⚠️ Error Handling\n\nAll endpoints return descriptive errors when something goes wrong.\n\n### Common HTTP Status Codes\n\
    \n| Code | Meaning         | Notes |\n|------|------------------|-------|\n| 200  | OK               | Success |\n| 204\
    \  | No Content       | Success, no response body |\n| 400  | Bad Request      | Validation or field error |\n| 401  |\
    \ Unauthorized     | Missing or invalid auth - credentials are invalid |\n| 403  | Forbidden        | Insufficient permission\
    \ - endpoint is not available for equipment type|\n| 404  | Not Found        | Resource doesn't exist - unknown RFID|\n\
    | 500  | Internal Error   | Something unexpected |\n\n### Sample Error Response\n\n```json\n{\n  \"message\": \"Invalid\
    \ input\",\n  \"fieldErrors\": [\n    {\n      \"name\": \"username\",\n      \"message\": \"Must not be null\"\n    }\n\
    \  ]\n}\n```\n\n---\n\nIf you have any questions or need help integrating, contact us at [integrations@egym.com](mailto:integrations@egym.com).\n\
    \n---\n\n# \U0001F4DD Integration FAQ – Standalone Devices API\n\nThis section addresses common technical integration\
    \ questions specific to the **Standalone Devices** model.\n\n## 1. Supported Login Types\n- **EGYM ID Login** (`grant_type=password`):\
    \ EGYM Username & password\n- **RFID Login** (`grant_type=rfid`): RFID number + format\n- **NFC Login** (`grant_type=nfc`):\
    \ NFC payload + issuer ID or configuration index\n\n## 2. Handling Terms & Conditions\nIf the user has not accepted the\
    \ latest Terms & Conditions (T&C):\n1. Retrieve T&C URL: `GET /users/{userId}/terms`\n2. Display link to user for acceptance/rejection\n\
    3. If accepted: `POST /users/{userId}/terms/accept`\n4. If rejected: exit the login flow gracefully\n\n## 3. Key Endpoints\
    \ for Standalone Integrations\n- Authentication: `POST /oauth/token`\n- User details: `GET /users`\n- Training plan: `GET\
    \ /training-plans`\n- Workout results: `POST /workouts`\n- Measurements: `POST /measurements/*`\n\n## 4. Error Handling\
    \ Best Practices\n- **401 Unauthorized**: Invalid/missing credentials or token\n- **403 Forbidden**: Permission issue\n\
    - **429 Too Many Requests**: Rate limit exceeded; retry after delay\n- Important: Provide meaningful error messages to\
    \ the user (not just error codes, ideally with localized description), or silently retry when user experience requires\n\
    \n## 5. Rate Limits\n- Authentication: 10 requests/second per `client_id`\n- Other endpoints: See API documentation\n\n\
    ## 6. Testing\n- Use the **EGYM Sandbox** with provided test credentials.\n- Test credentials are prodvided by EGYM\n\
    - Test login flows, training plan retrieval, workout submission, and T&C handling\n\n## 7. What if I send the same measurement\
    \ twice?**\nUse a different `uniqueMeasurementId` each time.\n\n## .When should I use `issuerId` vs `configurationIndex`\
    \ in NFC?**\nThese are alternatives for identifying the wallet pass source. Provide one depending on the integration project\
    \ with EGYM. Configuration Index is only supported when using the Dot Origin VTAP readers.\n"
  termsOfService: https://egym.com/us/terms/
  contact:
    name: EGYM GmbH
    url: https://egym.com/
    email: support@egym.com
  license:
    name: Pending License
    url: https://egym.com/
  version: 1.2.0
servers:
- url: https://partner-api.ext-1.test.co.egym.coffee
  description: Test (ext-1)
- url: https://partner-api.api.egym.com
  description: Production
paths:
  /api/v1/users:
    get:
      tags:
      - User
      summary: User Details
      description: This endpoint returns a user
      operationId: getUser
      responses:
        '200':
          description: Ok
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EquipmentUserDTO'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
    put:
      tags:
      - User
      summary: User Details
      description: This endpoint updates the current user. The endpoint is only enabled if there is a specific use case to
        update user records.
      operationId: updateUser
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserDTO'
        required: true
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
  /api/v1/users/terms-and-conditions:
    put:
      tags:
      - User
      summary: Accept Terms and Conditions
      description: This endpoint when invoked will save the information that the user accepted the eGym Terms and Conditions.
      operationId: acceptTermsAndConditions
      parameters:
      - name: locale
        in: query
        description: Defines the locale in ISO 15897 standard format.
        required: true
        schema:
          type: string
        example: en_US
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
  /api/v1/users/image:
    put:
      tags:
      - User
      summary: Set user's avatar
      description: This endpoint sets the user's avatar.
      operationId: uploadUserImage
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
              required:
              - file
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
  /api/v1/cardio/tests/{cardioTestId}:
    put:
      tags:
      - Cardio Test
      summary: Update Test
      description: This endpoint should be invoked in order to create a new step into an ongoing cardio test
      operationId: updateTest
      parameters:
      - name: cardioTestId
        in: path
        required: true
        schema:
          type: integer
          format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateCardioTestDTO'
        required: true
      responses:
        '200':
          description: Ok
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardioTestResponseDTO'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
  /api/v1/cardio/reminders:
    put:
      tags:
      - Cardio Test
      summary: Postpone Reminder
      description: This endpoint should be invoked in order to postpone the reminder of a cardio test
      operationId: postponeReminder
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
  /api/v1/users/rfid:
    post:
      tags:
      - User
      summary: Assign RFID
      description: This endpoint assigns one RFID to the user. If the RFID is already assigned to another user, it will be
        re-assigned to this user.
      operationId: assignRfid
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RfidDTO'
        required: true
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
  /api/v1/strength/workouts:
    post:
      tags:
      - Strength Workouts
      summary: Create Workout
      description: This endpoint creates a strength workout
      operationId: createWorkout
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StrengthWorkoutDTO'
        required: true
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
  /api/v1/open-exercises/workouts:
    post:
      tags:
      - Open Exercise Workouts
      summary: Create
      description: This endpoint creates an open exercise workout
      operationId: create
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OpenExerciseWorkoutDTO'
        required: true
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
  /api/v1/oauth/token:
    post:
      tags:
      - OAuth
      summary: Login
      description: This endpoint logs in the user and returns the access token
      operationId: token
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              oneOf:
              - $ref: '#/components/schemas/DeviceTokenRequestDTO'
              - $ref: '#/components/schemas/NfcTokenRequestDTO'
              - $ref: '#/components/schemas/PasswordTokenRequestDTO'
              - $ref: '#/components/schemas/RefreshTokenRequestDTO'
              - $ref: '#/components/schemas/RfidTokenRequestDTO'
              - $ref: '#/components/schemas/XidTokenRequestDTO'
      responses:
        '200':
          description: Ok
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenResponseDTO'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - partner: []
  /api/v1/measurements/flexibility:
    get:
      tags:
      - Flexibility Measurement
      summary: Get Flexibility Measurement
      description: This endpoint retrieves the latest flexibility measurement of the user
      operationId: getUserFlexibilityMeasurements
      parameters:
      - name: metrics
        in: query
        description: Subset of FlexibilityMetricType values to include in the response. When omitted, all available metric
          types are returned.
        required: false
        schema:
          type: array
          items:
            type: string
            enum:
            - RANGE_OF_MOVEMENT_SCORE
            - SYMMETRIC_SCORE
            - HARMONY_SCORE
            - TOTAL_SCORE
            - ADDUCTOR_LEFT_DEGREE
            - ADDUCTOR_LEFT_SCORE
            - ADDUCTOR_RIGHT_DEGREE
            - ADDUCTOR_RIGHT_SCORE
            - ADDUCTOR_RANGE_OF_MOTION_SCORE
            - ADDUCTOR_SYMMETRY_SCORE
            - LEG_BACKSIDE_LYING_LEFT_DEGREE
            - LEG_BACKSIDE_LYING_LEFT_SCORE
            - LEG_BACKSIDE_LYING_RIGHT_DEGREE
            - LEG_BACKSIDE_LYING_RIGHT_SCORE
            - LEG_BACKSIDE_LYING_RANGE_OF_MOTION_SCORE
            - LEG_BACKSIDE_LYING_SYMMETRY_SCORE
            - LEG_BACKSIDE_STANDING_LEFT_DEGREE
            - LEG_BACKSIDE_STANDING_LEFT_SCORE
            - LEG_BACKSIDE_STANDING_RIGHT_DEGREE
            - LEG_BACKSIDE_STANDING_RIGHT_SCORE
            - LEG_BACKSIDE_STANDING_RANGE_OF_MOTION_SCORE
            - LEG_BACKSIDE_STANDING_SYMMETRY_SCORE
            - LEG_EXTENSION_LEFT_DEGREE
            - LEG_EXTENSION_LEFT_SCORE
            - LEG_EXTENSION_RIGHT_DEGREE
            - LEG_EXTENSION_RIGHT_SCORE
            - LEG_EXTENSION_RANGE_OF_MOTION_SCORE
            - LEG_EXTENSION_SYMMETRY_SCORE
            - CHEST_LYING_LEFT_DEGREE
            - CHEST_LYING_LEFT_SCORE
            - CHEST_LYING_RIGHT_DEGREE
            - CHEST_LYING_RIGHT_SCORE
            - CHEST_LYING_RANGE_OF_MOTION_SCORE
            - CHEST_LYING_SYMMETRY_SCORE
            - CHEST_SITTING_LEFT_DEGREE
            - CHEST_SITTING_LEFT_SCORE
            - CHEST_SITTING_RIGHT_DEGREE
            - CHEST_SITTING_RIGHT_SCORE
            - CHEST_SITTING_RANGE_OF_MOTION_SCORE
            - CHEST_SITTING_SYMMETRY_SCORE
            - HIP_FLEXOR_LEFT_DEGREE
            - HIP_FLEXOR_LEFT_SCORE
            - HIP_FLEXOR_RIGHT_DEGREE
            - HIP_FLEXOR_RIGHT_SCORE
            - HIP_FLEXOR_RANGE_OF_MOTION_SCORE
            - HIP_FLEXOR_SYMMETRY_SCORE
            - TORSO_MUSCLES_LYING_LEFT_DEGREE
            - TORSO_MUSCLES_LYING_LEFT_SCORE
            - TORSO_MUSCLES_LYING_RIGHT_DEGREE
            - TORSO_MUSCLES_LYING_RIGHT_SCORE
            - TORSO_MUSCLES_LYING_RANGE_OF_MOTION_SCORE
            - TORSO_MUSCLES_LYING_SYMMETRY_SCORE
            - TORSO_MUSCLES_SITTING_LEFT_DEGREE
            - TORSO_MUSCLES_SITTING_LEFT_SCORE
            - TORSO_MUSCLES_SITTING_RIGHT_DEGREE
            - TORSO_MUSCLES_SITTING_RIGHT_SCORE
            - TORSO_MUSCLES_SITTING_RANGE_OF_MOTION_SCORE
            - TORSO_MUSCLES_SITTING_SYMMETRY_SCORE
            - SHOULDER_NECK_LEFT_DEGREE
            - SHOULDER_NECK_LEFT_SCORE
            - SHOULDER_NECK_RIGHT_DEGREE
            - SHOULDER_NECK_RIGHT_SCORE
            - SHOULDER_NECK_RANGE_OF_MOTION_SCORE
            - SHOULDER_NECK_SYMMETRY_SCORE
            - CALF_LEFT_DEGREE
            - CALF_LEFT_SCORE
            - CALF_RIGHT_DEGREE
            - CALF_RIGHT_SCORE
            - CALF_RANGE_OF_MOTION_SCORE
            - CALF_SYMMETRY_SCORE
            - TORSO_LATERAL_FLEXION_LEFT_DEGREE
            - TORSO_LATERAL_FLEXION_RIGHT_DEGREE
            - TORSO_LATERAL_FLEXION_LEFT_NORMALIZED
            - TORSO_LATERAL_FLEXION_RIGHT_NORMALIZED
            - NECK_LATERAL_FLEXION_LEFT_DEGREE
            - NECK_LATERAL_FLEXION_RIGHT_DEGREE
            - NECK_LATERAL_FLEXION_LEFT_NORMALIZED
            - NECK_LATERAL_FLEXION_RIGHT_NORMALIZED
            - CHEST_EXTENSION_LEFT_DEGREE
            - CHEST_EXTENSION_RIGHT_DEGREE
            - CHEST_EXTENSION_LEFT_NORMALIZED
            - CHEST_EXTENSION_RIGHT_NORMALIZED
            - HIP_EXTENSION_LEFT_DEGREE
            - HIP_EXTENSION_RIGHT_DEGREE
            - HIP_EXTENSION_LEFT_NORMALIZED
            - HIP_EXTENSION_RIGHT_NORMALIZED
            - HAMSTRING_EXTENSION_LEFT_DEGREE
            - HAMSTRING_EXTENSION_RIGHT_DEGREE
            - HAMSTRING_EXTENSION_LEFT_NORMALIZED
            - HAMSTRING_EXTENSION_RIGHT_NORMALIZED
            - SQUAT_DEPTH
            - SQUAT_SHOULDER_DEGREE
            - SQUAT_BACK_DEGREE
      responses:
        '200':
          description: Ok
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LatestFlexibilityMeasurementsValuesResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
    post:
      tags:
      - Flexibility Measurement
      summary: Create Flexibility Measurement
      description: This endpoint creates a Flexibility measurement for the user
      operationId: createFlexibilityMeasurement
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MeasurementDTO'
        required: true
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
  /api/v1/measurements/cardio:
    get:
      tags:
      - Cardio Measurement
      summary: Get Cardio Measurement
      description: This endpoint retrieves the latest cardio measurement of the user
      operationId: getUserCardioMeasurements
      parameters:
      - name: metrics
        in: query
        description: Subset of CardioMetricType values to include in the response. When omitted, all available metric types
          are returned.
        required: false
        schema:
          type: array
          items:
            type: string
            enum:
            - RESTING_HEART_RATE
            - VO2MAX
            - SYSTOLIC_PRESSURE
            - DIASTOLIC_PRESSURE
            - MAX_WATTS
            - TRAINING_SUITABILITY
            - CARDIO_STRESS_INDEX
            - CARDIO_FIT_LEVEL
            - HEART_RATE_ZONE_RECOVERY_LOW
            - HEART_RATE_ZONE_RECOVERY_TOP
            - HEART_RATE_ZONE_BASICI_LOW
            - HEART_RATE_ZONE_BASICI_TOP
            - HEART_RATE_ZONE_BASICII_LOW
            - HEART_RATE_ZONE_BASICII_TOP
            - HEART_RATE_ZONE_THRESHOLD_LOW
            - HEART_RATE_ZONE_THRESHOLD_TOP
            - HEART_RATE_ZONE_HIGH_INTENSIVE_LOW
            - HEART_RATE_ZONE_HIGH_INTENSIVE_TOP
            - PERFORMANCE_FIT_LEVEL
            - ABSOLUTE_VO2_MAX
            - PERFORMANCE_ZONE_RECOVERY_LOW
            - PERFORMANCE_ZONE_RECOVERY_TOP
            - PERFORMANCE_ZONE_BASICI_LOW
            - PERFORMANCE_ZONE_BASICI_TOP
            - PERFORMANCE_ZONE_BASICII_LOW
            - PERFORMANCE_ZONE_BASICII_TOP
            - PERFORMANCE_ZONE_THRESHOLD_LOW
            - PERFORMANCE_ZONE_THRESHOLD_TOP
            - PERFORMANCE_ZONE_HIGH_INTENSIVE_LOW
            - PERFORMANCE_ZONE_HIGH_INTENSIVE_TOP
            - FATTY_ACID_METABOLISM_PERCENTS
            - CARBONHYDRATE_METABOLISM_PERCENTS
            - CARBONHYDRATE_METABOLISM_RATING
            - O2_UPTAKE_PERCENTS
            - CO2_EMISSION_PERCENTS
            - O2_UPTAKE_RATING
            - CARDIO_FIT_LEVEL_MIN
            - CARDIO_FIT_LEVEL_LOW
            - CARDIO_FIT_LEVEL_MID
            - CARDIO_FIT_LEVEL_TOP
            - CARDIO_FIT_LEVEL_MAX
            - CARDIO_STRESS_INDEX_MIN
            - CARDIO_STRESS_INDEX_LOW
            - CARDIO_STRESS_INDEX_MID
            - CARDIO_STRESS_INDEX_TOP
            - CARDIO_STRESS_INDEX_MAX
            - WORKOUT_READINESS
            - RESTING_HEART_RATE_MIN
            - RESTING_HEART_RATE_LOW
            - RESTING_HEART_RATE_MID
            - RESTING_HEART_RATE_TOP
            - RESTING_HEART_RATE_MAX
            - BLOOD_OXYGEN_LEVEL_SPO2
            - BLOOD_OXYGEN_LEVEL_SPO2_MIN
            - BLOOD_OXYGEN_LEVEL_SPO2_LOW
            - BLOOD_OXYGEN_LEVEL_SPO2_MID
            - BLOOD_OXYGEN_LEVEL_SPO2_TOP
            - BLOOD_OXYGEN_LEVEL_SPO2_MAX
            - PARTNER_CARDIO_BIOAGE
            - PARTNER_CARDIO_BIOAGE_MIN
            - PARTNER_CARDIO_BIOAGE_LOW
            - PARTNER_CARDIO_BIOAGE_MID
            - PARTNER_CARDIO_BIOAGE_TOP
            - PARTNER_CARDIO_BIOAGE_MAX
            - O2_UPTAKE_PERCENTS_MIN
            - O2_UPTAKE_PERCENTS_LOW
            - O2_UPTAKE_PERCENTS_MID
            - O2_UPTAKE_PERCENTS_TOP
            - O2_UPTAKE_PERCENTS_MAX
            - PARTNER_FITNESS_LEVEL
            - ESTIMATED_FUNCTIONAL_THRESHOLD_POWER_WATT
            - FUNCTIONAL_THRESHOLD_POWER_WATT
            - ESTIMATED_MAX_HEART_RATE_BPM
            - MAX_HEART_RATE_BPM
            - HEART_RATE_BPM
            - PULSE_BPM
            - MEAN_ARTERY_PRESSURE_MMHG
            - PULSE_PRESSURE_BPM
            - RATE_PRESSURE_PRODUCT
            - INDIVIDUAL_ANAEROBIC_THRESHOLD
            - HEART_RATE_RECOVERY_RATING
            - METABOLIC_FLEXIBILITY_RATING
            - STRESS_LEVEL_METABOLISM_RATING
            - VENTILATORY_THRESHOLD_1
            - VENTILATORY_THRESHOLD_2
            - EXERCISE_INTENSITY_AT_MAXIMUM_FAT_OXIDATION
            - PEAK_POWER_WATTS
      responses:
        '200':
          description: Ok
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LatestCardioMeasurementsValuesResponseDTO'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponseDTO'
      security:
      - user: []
    post

# --- truncated at 32 KB (146 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/egym/refs/heads/main/openapi/egym-equipment-vendor-standalone-openapi.yml