openapi: 3.0.0
info:
  title: Canonical GroupX Classes API
  description: >
    This specification defines *Canonical API* for GroupX Classes Service, which
    provides operations for working with Group Exercise Classes, their schedules
    and attendees.


    **WARNING:** some sections of this document are marked for Professional
    Services only or for ClubMS Provider only. Before sharing with respective
    parties, the irrelevant sections must be removed.


    ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)
    - sections marked with such icon are intended only for Professional Services
    Teams (with their all subsections)

    ## Introduction to ClubMS and Canonical APIs

    **Club Management Software (ClubMS)** is a suite of software for managing
    fitness clubs: billing system, members management, group calendars, payments
    processing, personal trainers, etc. ClubMS is also know as Membership
    Management Software (MMS).



    There are a lot of different ClubMS in the world, and they all have
    different domain models. Generally speaking, for a given fitness location,
    different services might be provided by different external ClubMS.


    **Canonical API** hides this difference by mapping to Netpulse Canonical
    Model. Implementation of Canonical API for a certain ClubMS service makes it
    compatible with Netpulse Platform.


    Some of the contracts in this Canonical API definition depend on multiple
    meta options. These meta options are not reflected by API parameters
    directly, but define conditional API contracts. Meta option values reflect
    ClubMS specifics and are provided by *Implementer of Canonical API*.
    Netpulse Platform is then configured with these option values to enable
    integration with the given canonized service. **For example:** Different
    ClubMS use different types of credentials (security schemas) for their
    operations: client secret, chain secret, or location secret. Galaxy will
    expect corresponding configuration and pass appropriate parameters depending
    on corresponding meta option value.


    The meta options are defined by a json schema that accompanies the yaml file
    (they should be sent together).


    All conditional contracts that depend on specific meta option values are
    described in this Canonical API with references like
    `metaOption::someOptionName`. Implementer of Canonical API might want to
    remove all these conditional contracts and replace them by concrete
    contracts based on ClubMS specific meta option values (that should be known
    to the Implementer of Canonical API). String "metaOption::" can be used for
    quick finding of all such conditional contracts.



    ## General API Contracts

    ### Date Format

    All dates in the API are strings in [ISO
    8601](https://en.wikipedia.org/wiki/ISO_8601) format and in **UTC time
    zone**:

    ```

    yyyy-MM-dd'T'HH:mm:ss'Z'

    ```

    Valid example:

    ```

    2010-08-21T22:31:20Z

    ```

    Invalid examples:

    ```

    2008-05-26T07:23: (missing seconds)

    2008-05-26T07:23:01.500Z (nanoseconds value is not supported)

    2008-05-26 07:23:01Z  ('T' in the middle is not specified)

    2008-05-23T07:23:01 (trailing 'Z' is missing)

    ```


    ### Additional Data HTTP Headers

    There are several HTTP Headers that must be used to provide additional data
    to every canonical operation.

    These headers presence based on *`metaOption::includeClientData`*,
    *`metaOption::includeChainData`*, *`metaOption::includeLocationData`*,
    *`metaOption::includeLocationGroupData`*, *`metaOption::includeUserData`*
    options. These options should be switched to `true` if any of the following
    applicable:

    * security access of certain level required;

    * extra configuration data is expected on some level;


    #### X-Client-ID

    This header contains Partner Client ID. It is a credential to access
    canonical API in scope of specific Partner implementation.


    It is required for every canonical operation which supports API access
    restriction on Partner level.

    In this case *`metaOption::includeClientData`* must be switched on for that
    operation.


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    &nbsp;


    #### X-Client-Secret

    This header contains Partner Client Secret. It is a credential to access
    canonical API in scope of specific Partner implementation.

    It is required for every canonical operation which supports API access
    restriction on Partner level.

    In this case *`metaOption::includeClientData`* must be switched on for that
    operation.


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    &nbsp;


    #### ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)X-NP-Client-Configuration

    This header provides Netpulse configuration associated with a Partner
    Client  mentioned in `X-Client-ID` header.

    should be used if extra client application configuration data needed to call
    operaiton on ClubMS side.

    In this case *`metaOption::includeClientData`* must be switched on for that
    operation.


    Possible reasons of validation errors:

    * missing => 400

    * badConfig => 400 (when configuration contents is invalid or there is
    external error because of wrong configuration parameters: for example
    something not found)


    &nbsp;


    #### X-Chain-ID

    This header provides ID of a Chain which we access in canonical operation.


    Required for every canonical operaiton based on Chain information (security,
    configuration etc.)

    In this case *`metaOption::includeChainData`* must be switched on for that
    operation.


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    &nbsp;


    #### X-Chain-Secret

    This header provides chain-level secret correspondent to Chain ID defined in
    `X-Chain-ID` header.


    Required if ClubMS expects access tokens or secret keys on accessing to
    Chain level information via API.

    In this case *`metaOption::includeChainData`* must be switched on for that
    operation.


    **_Additional Contracts:_** Secret can be any string of up to 1024
    characters allowed for HTTP header values (see RFC2616).


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    &nbsp;


    #### ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)X-NP-Chain-Configuration

    This header provides Netpulse configuration associated with a chain
    mentioned in `X-Chain-ID` header.

    If extra chain level configuration data needed to call operaiton on ClubMS
    side.

    In this case *`metaOption::includeChainData`* must be switched on for that
    operation.


    Possible reasons of validation errors:

    * missing => 400

    * badConfig => 400 (when configuration contents is invalid or there is
    external error because of wrong configuration parameters: for example
    something not found)


    &nbsp;


    #### X-Location-Group-ID

    This header provides ID of a Location Group which we access in canonical
    operation.

    Required for every canonical operation based on Location Group information
    (security, configuration etc.)

    In this case *`metaOption::includeLocationGroupData`* must be switched on
    for that operation.


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    &nbsp;


    #### X-Location-Group-Secret

    This header provides location group level secret correspondent to Location
    Group ID defined in `X-Location-Group-ID` header.

    Required if ClubMS expects access tokens or secret keys on accessing to
    Location Group level information via API.

    In this case *`metaOption::includeLocationGroupData`* must be switched on
    for that operation.


    **_Additional Contracts:_** Access data can be any string of up to 1024
    characters allowed for HTTP header values (see RFC2616).

     Possible reasons of validation errors:
    * missing => 400

    * invalid => 401


    &nbsp;


    #### ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)X-NP-Location-Group-Configuration

    This header provides Netpulse configuration associated with a location group
    mentioned in `X-Location-Group-ID` header.

    Required if extra location group level configuration data needed to call
    operaiton on ClubMS side.

    In this case *`metaOption::includeLocationGroupData`* must be switched on
    for that operation.


    Possible reasons of validation errors:

    * missing => 400

    * badConfig => 400 (when configuration contents is invalid or there is
    external error because of wrong configuration parameters: for example
    something not found)


    &nbsp;


    #### X-Location-ID

    This header provides ID of a Location which we access in canonical
    operation.

    Required for every canonical operaiton based on Location information
    (security, configuration etc.)

    In this case *`metaOption::includeLocationData`* must be switched on for
    that operation.


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    &nbsp;


    #### X-Location-Secret

    This header provides location-level secret correspondent to Location ID
    defined in `X-Location-ID` header.

    Required if ClubMS expects access tokens or secret keys on accessing to
    Location level information via API.

    In this case *`metaOption::includeLocationData`* must be switched on for
    that operation.


    **_Additional Contracts:_** Access data can be any string of up to 1024
    characters allowed for HTTP header values (see RFC2616).

     Possible reasons of validation errors:
    * missing => 400

    * invalid => 401


    &nbsp;


    ####  ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)X-NP-Location-Timezone

    This header provides location timezone correspondent to Location ID defined
    in `X-Location-ID` header.

    It is required if *`metaOption::includeLocationData`* switched on for the
    operation.


    Possible reasons of validation errors:

    * missing => 400

    * timezoneUnknown => 400


    &nbsp;


    #### ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)X-NP-Location-Configuration

    This header provides Netpulse configuration associated with a location
    mentioned in `X-Location-ID` header.

    If extra location level configuration data needed to call operaiton on
    ClubMS side.

    In this case *`metaOption::includeLocationData`* must be switched on for
    that operation.


    Possible reasons of validation errors:

    * missing => 400

    * badConfig => 400 (when configuration contents is invalid or there is
    external error because of wrong configuration parameters: for example
    something not found)


    &nbsp;


    #### X-User-ID

    This header contains User ID in Partner system. Required for every canonical
    operaiton which supports API access restriction on User level.

    In this case *`metaOption::includeUserData`* must be switched on for that
    operation.


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    &nbsp;


    #### X-User-Secret

    This header contains User Secret in Partner system.

    It is required for every canonical operation which supports API access
    restriction on User level.

    In this case *`metaOption::includeUserData`* must be switched on for that
    operation.


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    &nbsp;


    #### X-User-Locale

    This header contains Locale which was choosed on users phone. Required for
    every canonical operaiton which supports needs localization.

    In this case *`metaOption::includeLocalizationData`* must be switched on for
    that operation.


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    &nbsp;


    ### Errors

    Conventional HTTP response codes are used to indicate the success or failure
    of an API request.


    General Requirements:

    * The contracts of this section apply to every operation of Canonical APIs.

    * Furthermore, every operation specifies its own specific contracts which
    extend these ones.

    * Every error response has field `message`.

    * Every error response has field `cause`.
      * There are standard causes associated with corresponding HTTP status codes (4xx, 5xx).
      * And there might be also custom causes always defined on operation level and associated with 422 status code.


    #### 400: Bad Request

    Cause is `badRequest`. This cause is used for all parameter-level validation
    errors. This is often due to missing a required parameter or wrong parameter
    format. This can be also due to violation of some contract defined in the
    given specification for a certain parameter.


    Requirements:

    * Error message can simply contain "Bad Request"

    * Additional field `errors` must be present, which is a map of pairs:
    `"<parameterName>": "<reason>"`. See example.

    * Parameter names are defined in the documentation of respective canonical
    operations.

    * Possible reasons are defined in the documentation of parameters of
    respective canonical operations.


    **NOTE:** ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)
    This code must never be used to translate unexpected 4xx error occured in
    the third-party external system. Use 500 instead (with
    `cause=externalSystemUnexpectedResponse`).


    Example:

    ```

    {
      "message": "Bad Request",
      "cause": "badRequest",
      "errors": {
        "locationId": "missing",
        "startDateTime": "greaterThanEndDateTime",
        "endDateTime": "lessThanStartDateTime"
      }
    }

    ```

    &nbsp;


    #### 401: Unauthorized Access

    Cause is `unauthorizedAccess`. Bad, unexpected or expired access data (see
    'Additional Data HTTP Headers': `X-Client-ID`/`X-Client-Secret`,
    `X-Chain-ID`/`X-Chain-Secret`, `X-Location-ID`/`X-Location-Secret`,
    `X-Location-Group-ID`/`X-Location-Group-Secret`,
    `X-User-ID`/`X-User-Secret`).


    Requirements:

    * Error message must clearly indicate the reason of the failure and what is
    expected to fix it.

    * Additional field `accessLevel` must indicate the level of access requested
    that caused this error (i.e. level of access backed by correspondent access
    headers): `client`, `chain`, or `location`.


    Suggested action: Fix access data and then retry.


    Example:

    ```

    // 1st example

    {
      "message": "X-Client-Id is invalid",
      "cause": "unauthorizedAccess",
      "accessLevel": "client"
    }

    // 2nd example

    {
      "message": "X-Location-Secret is invalid",
      "cause": "unauthorizedAccess",
      "accessLevel": "location"
    }

    ```

    &nbsp;


    #### 404: Entity Not Found

    Cause is `entityNotFound`. Any referenced entity or resource is not found.


    Requirements:

    * Error message must clearly indicate the reason of the failure.

    * Additional field `parameter` must be present. Parameter indicates which
    parameter of the request has wrong value that was not found. This parameter
    is then indicated in the documentation of respective canonical operation in
    section "Possible reasons of validation errors".


    Example:

    ```

    {
      "message": "Location 'ESD3432' is not found",
      "cause": "entityNotFound",
      "parameter": "locationId"
    }

    ```

    &nbsp;


    #### 404: Resource Not Found

    Cause is `resourceNotFound`. The requested endpoint does not exist or is not
    supported.


    Example:

    ```

    {
      "message": "Requested endpoint is not supported",
      "cause": "resourceNotFound"
    }

    ```

    &nbsp;


    #### 405: Method Not Allowed

    Used HTTP method is not supported for the given endpoint. For example, POST,
    PUT, DELETE, etc.

    &nbsp;


    #### 422: Custom Cause

    The request was well-formed but could not be completed due to failed
    server-side validation checks, which can't be performed by client without
    server calls.


    This error can be used only if it is specified on operation level.

    Requirements:

    * Error message must clearly indicate the reason of the failure.

    * Additional field `cause` must indicate what exactly has caused this error.

    * Additional field `reason` must indicate the reason of the failure and is
    logically bound to the `cause` by extending it.

    * The values for `cause` and `reason` must be strictly defined at operation
    level. The values that are not defined at operation level must never be
    used.


    Examples:

    ```

    // 1st example

    {
      "message": "Cannot add an Exerciser id='E67' to a Class 'Stretching' Waitlist since the Exerciser is already in this Waitlist",
      "cause": "addToWaitlistFailed",
      "reason": "userAlreadyInWaitlist"
    }

    // 2nd example

    {
      "message": "Cannot add an Exerciser id='E67' to a Class 'Stretching' Waitlist since the Exerciser is the Class Attendee already",
      "cause": "addToWaitlistFailed",
      "reason": "userAlreadyAttendee"
    }

    // 3nd example

    {
      "message": "Class 'Yoga 24/7' canot be booked by Exerciser with id='E3471' due to lack of Product to pay for the Class",
      "cause": "bookingFailed",
      "reason": "lackOfProduct"
    }

    ```

    &nbsp;


    #### 429: Too Many Requests

    Cause is `rateLimitsExceeded`. Too many requests hit the API too quickly
    (Rate limit exceeded).


    **NOTE:** ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)
    If rate limits exeeded while calling an external ClubMS system, then error
    message must contain response returned from the external system.

    Example:

    ```

    {
      "message": "Rate limit exceeded. External system response: 'Rate limit exceeded'",
      "cause": "rateLimitsExceeded"
    }

    ```

    &nbsp;


    #### 500: Internal Server Error

    Cause is `internalUnexpectedError`. An unexpected error occurred while
    processing the request. Suggested action: Use exponential backoff.


    Detailed reason of internal server error is usually not returned in response
    to the client. Detailed reason (error stack trace) must be logged in
    internal logging system.


    Example:

    ```

    {
      "message": "Internal Server Error: NullPointerException",
      "cause": "internalUnexpectedError"
    }

    ```

    &nbsp;


    #### ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)
    500: External System Unexpected Response

    Cause is `externalSystemUnexpectedResponse`. External ClubMS system returned
    an unexpected response: 2xx, 3xx, 4xx, or 5xx.


    An unexpected response might be due to response parsing error, or due to
    missing mandatory field in response, or due to an unexpected error,
    particularly due to 400 Bad Request error, etc. But generally it might be
    any response: 2xx, 3xx, 4xx, or 5xx, - that is unexpected, other words
    expectation was that this should never happen.


    For example, 400 Bad Request error from external third-party system is not
    expected for canonical operation, because canonical operation already does
    all input validation and must not expect corresponding failure in external
    system. If this happens, then it means that some contracts are not
    considered by implementation of canonical operation and there a change must
    be performed by Professional Services Team. The reason might be an
    unexpected change on third-party side, or simply missing some edge case
    contract.


    On the other hand, 404 Not Found error from external third-party system is
    expected error in case when canonical operation knows which parameter caused
    this error and then it is translated into 404. But when canonical operation
    does not know what caused 404, then it is 500.


    **NOTE:** Unexpected response from an external system is always a permanent
    failure that requires a fix on side of implementation of canonical
    operation.


    Example:

    ```

    {
      "message": "Unexpected response from External System XYZ: 404 Not Found: no such endpoint",
      "cause": "externalSystemUnexpectedResponse"
    }

    ```

    &nbsp;


    #### ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)
    502: External System Internal Error

    Cause is `externalSystemInternalError`. Third-party external system error
    (5xx): external system returned a 500 error indicating an internal
    unexpected error on their side.

    Basically for the canonical operation this is expected outcome, which means
    that this is not a permanent failure. Suggested action: Use exponential
    backoff.


    Requirement: Error message sums up the cause and provides details about
    response from external system. This details must include the status code as
    returned by external system and its standard description, e.g. "500 Internal
    Server Error", and some other details from actual external response.

    Example:

    ```

    {
      "message": "External System internal error. Response: 500 Internal Server Error: Nullpointer exception",
      "cause": "externalSystemInternalError"
    }

    ```

    &nbsp;


    #### ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)
    502: External System Unavailable

    Cause is `externalSystemUnavailable`. Third-party external system is
    unavailable: external system returned 503 or just refused connection (I/O
    error) or indicated in some other way that it is unavailable because of
    maintenance.


    Requirement: Error message sums up the cause and provides details about
    response from external system. This details must include the status code as
    returned by external system and its standard description, e.g. "503 Service
    Unavailable", and some other details from actual external response. In case
    if connection has been refused by peer, then message must contain:
    "Connection refused by peer".


    Example:

    ```

    // 1st example

    {
      "message": "External System was unavailable. Response: Connection refused by peer",
      "cause": "externalSystemUnavailable"
    }

    // 2nd example

    {
      "message": "External System was unavailable. Response: 503 Service Unavailable: The server is down for maintenance until 2am PST.",
      "cause": "externalSystemUnavailable"
    }

    ```

    &nbsp;


    #### 503: System Unavailable

    Cause is `systemUnavailable`. The server is currently unavailable (because
    it is overloaded or down for maintenance). Generally, this is a temporary
    state.


    **NOTE:** ![Professional Services
    only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)
    This status must not be used to report any issue from an external
    third-party system, use 502 instead.


    Example:

    ```

    {
      "message": "Server is down for maintenance",
      "cause": "systemUnavailable"
    }

    ```

    &nbsp;
  version: '1.0'
paths:
  /classes:
    get:
      tags:
        - L2
      summary: Search Classes
      description: >
        This operation searches GroupX Classes by date range. It returns only
        brief information about GroupX Classes.


        #### Additional contracts

        N/A
      operationId: searchClasses
      parameters:
        - name: locationId
          in: query
          description: >
            ClubMS Location ID, which indicates Location to search Classes in.
            This ID is returned by Canonical Locations API or provided manually
            to Netpulse admins.


            ##### Possible reasons of validation errors:

            * missing => 400

            * notFound => 404
          required: true
          schema:
            type: string
        - name: endDateTime
          in: query
          description: |
            Defines end of the timerange for Class search

            ##### Possible reasons of validation errors:
            * missing => 400
            * wrongFormat => 400
            * lessThanStartDateTime => 400
          required: true
          schema:
            type: string
            format: date-time
        - name: startDateTime
          in: query
          description: |
            Defines start of the timerange for Class search

            ##### Possible reasons of validation errors:
            * missing => 400
            * wrongFormat => 400
            * greaterThanEndDateTime => 400
          required: true
          schema:
            type: string
            format: date-time
        - $ref: '#/components/parameters/userSecretHeader'
        - $ref: '#/components/parameters/userIdHeader'
        - $ref: '#/components/parameters/userLocaleHeader'
        - $ref: '#/components/parameters/locationNpConfigurationHeader'
        - $ref: '#/components/parameters/locationNpTimezoneHeader'
        - $ref: '#/components/parameters/locationSecretHeader'
        - $ref: '#/components/parameters/locationIdHeader'
        - $ref: '#/components/parameters/locationGroupNpConfigurationHeader'
        - $ref: '#/components/parameters/locationGroupSecretHeader'
        - $ref: '#/components/parameters/locationGroupIdHeader'
        - $ref: '#/components/parameters/chainNpConfigurationHeader'
        - $ref: '#/components/parameters/chainSecretHeader'
        - $ref: '#/components/parameters/chainIdHeader'
        - $ref: '#/components/parameters/clientNpConfigurationHeader'
        - $ref: '#/components/parameters/clientSecretHeader'
        - $ref: '#/components/parameters/clientIdHeader'
      responses:
        '200':
          description: >
            List of found Classes.


            ##### Contracts

            * Section `brief` is required.

            * If *`metaOption::bookingEnabled`* is true then `free` flag is
            required, optional otherwise.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    brief:
                      $ref: '#/components/schemas/GroupXClassBrief'
            .:
              examples:
                response:
                  value:
                    - brief:
                        id: ECS18
                        name: Yoga 24
                        startDateTime: '2016-08-23T16:00:00Z'
                        endDateTime: '2016-08-23T17:00:00Z'
                        locationId: ECB23
                        instructor:
                          firstName: Anna
                          lastName: Jones
                          fullName: Anna Jones
                        activity:
                          name: Yoga
                        free: true
                    - brief:
                        id: ECS97
                        name: TRX Small Group
                        startDateTime: '2016-08-24T18:00:00Z'
                        endDateTime: '2016-08-24T18:30:00Z'
                        locationId: ECB23
                        instructor:
                          firstName: Anna
                          lastName: Jones
                          fullName: Anna Jones
                        activity:
                          name: TRX
  /classes/{classId}:
    get:
      tags:
        - L2
        - L3
      summary: Get Class Details
      description: >
        This operation returns all detailed information about GroupX Class.


        **NOTE:** ![Professional Services
        only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)
        Implementation of this operation is mandatory. In that case if Partner
        API does not implement it then this implementation should be introduced
        on Anti-corruption layer. It could be based on cached data of getClasses
        call as a possible solution.


        #### Additional Contracts
         1. Parameter `exerciserId` is supported only if *`metaOption::bookingEnabled`* = true. If booking is disabled, then 400 status code must be returned when `exerciserId` is specified.
         2. If *`metaOption::bookingEnabled`* = true, parameter `exerciserId` is optional. If it is specified, then `GroupXClassAttendeeBookingDetails` is provided in response. If `exerciserId` is not specified, then response has no attendee booking details.
      operationId: getClassDetails
      parameters:
        - name: classId
          in: path
          description: |
            ClubMS Class Unique ID

            ##### Possible reasons of validation errors:
            * notFound => 404
          required: true
          schema:
            type: string
        - name: exerciserId
          in: query
          description: >
            ClubMS Exerciser Unique ID which is returned by Canonical Users API
            and/or by Canonical Members API.


            ##### Possible reasons of validation errors:

            * notSupported => 400

            * notFound => 404
          required: false
          schema:
            type: string
        - $ref: '#/components/parameters/userLocaleHeader'
        - $ref: '#/components/parameters/userSecretHeader'
        - $ref: '#/components/parameters/userIdHeader'
        - $ref: '#/components/parameters/locationNpConfigurationHeader'
        - $ref: '#/components/parameters/locationNpTimezoneHeader'
        - $ref: '#/components/parameters/locationSecretHeader'
        - $ref: '#/components/parameters/locationIdHeader'
        - $ref: '#/components/parameters/locationGroupNpConfigurationHeader'
        - $ref: '#/components/parameters/locationGroupSecretHeader'
        - $ref: '#/components/parameters/locationGroupIdHeader'
        - $ref: '#/components/parameters/chainNpConfigurationHeader'
        - $ref: '#/components/parameters/chainSecretHeader'
        - $ref: '#/components/parameters/chainIdHeader'
        - $ref: '#/components/parameters/clientNpConfigurationHeader'
        - $ref: '#/components/parameters/clientSecretHeader'
        - $ref: '#/components/parameters/clientIdHeader'
      responses:
        '200':
          description: >
            Class full information and Attendee Booking Details


            ##### Contracts

            * If *`metaOption::bookingEnabled`* is true then `free` flag is
            required, optional otherwise.

            * Section `bookingDetails` is required if
            *`metaOption::bookingEnabled`* = true, and is not supported
            otherwise.

            * Section `attendeeBookingDetails` is required only if parameter
            `exerciserId` was specified.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupXClass'
            .:
              examples:
                response:
                  value:
                    brief:
                      $ref: '#/paths/~1classes/get/responses/200/examples/./0/brief'
                    bookingDetails:
                      capacity: 10
                      booked: 3
                      waitlistCapacity: 2
                      waitlistBooked: 0
                    details:
                      description: >
                        A blend of two popular types of mind-body connected
                        exercise: Yoga and Pilates. Done to calming, relaxed
                        mode music, each discipline has postures which are
                        duplicated with the other, so a blending of these two
                        types of exercise styles is a natural.
                      room:
                        name: room 21
                        description: a gymnasium on 2nd floor
                      level:
                        name: Beginner
                        description: >
                          This level will focus on more intensive techniques,
                          patterns and longer pieces of choreography.
                      legalNotes: >
                        Only one free trial can be redeemed per person. No other
                        free trial offer in any form will be available to
                        someone who has previously used a free trial.
                      pricing:
                        price: 10
                      customInfo:
                        - key: childcare
                          value: true
                        - key: kidshours
                          value: 11am-18pm
                    attendeeBookingDetails:
                      exerciserId: EE3519
                      booked: true
                      waitlistBooked: false
                      waitlistPosition: 0
                      eligibility:
                        addToClassEligibility:
                          eligible: false
                          lackOfProduct: true
                          reason: Product Yoga-10 not available
                        removeFromClassEligibility:
                          eligible: false
                        addToWaitlistEligibility:
                          eligible: false
                          reason: No waitlist available
                        removeFromWaitlistEligibility:
                          eligible: false
  /classes/{classId}/attendees/{exerciserId}:
    post:
      tags:
        - L3
      summary: Add Attendee to Class
      description: >
        This operation books GroupX Class for the Attendee (Exerciser).


        **NOTE:** This operation is available only if
        *`metaOption::bookingEnabled`* = true (use status code 404 endpoint not
        supported).

        #### Additional Contracts

        N/A
      operationId: addAttendeeToClass
      parameters:
        - name: exerciserId
          in: path
          description: >
            ClubMS Exerciser Unique ID which is returned by Canonical Users API
            and/or by Canonical Members API.


            ##### Possible reasons of validation errors:

            * notFound => 404
          required: true
          schema:
            type: string
        - name: classId
          in: path
          description: |
            ClubMS Class Unique ID

            ##### Possible reasons of validation errors:
            * notFound => 404
          required: true
          schema:
            type: string
        - name: spot
          in: query
          description: |
            Spot identifier (e.g. spot number).

            ##### Possible reasons of validation errors:
            * noFreeSpots => 422
          required: false
          schema:
            type: string
        - $ref: '#/components/parameters/userLocaleHeader'
        - $ref: '#/components/parameters/userSecretHeader'
        - $ref: '#/components/parameters/userIdHeader'
        - $ref: '#/components/parameters/locationNpConfigurationHeader'
        - $ref: '#/components/parameters/locationNpTimezoneHeader'
        - $ref: '#/components/parameters/locationSecretHeader'
        - $ref: '#/components/parameters/locationIdHeader'
        - $ref: '#/components/parameters/locationGroupNpConfigurationHeader'
        - $ref: '#/components/parameters/locationGroupSecretHeader'
        - $ref: '#/components/parameters/locationGroupIdHeader'
        - $ref: '#/components/parameters/chainNpConfigurationHeader'
        - $ref: '#/components/parameters/chainSecretHeader'
        - $ref: '#/components/parameters/chainIdHeader'
        - $ref: '#/components/parameters/clientNpConfigurationHeader'
        - $ref: '#/components/parameters/clientSecretHeader'
        - $ref: '#/components/parameters/clientIdHeader'
      responses:
        '200':
          description: |
            Class is booked for the Attendee successfully.
            Updated GroupX Class Details returned.

            ##### Contracts
            All sections are required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupXClass'
            .:
              examples:
                response:
                  value:
                    brief:
                      $ref: '#/paths/~1classes/get/responses/200/examples/./0/brief'
                    bookingDetails:
                      capacity: 10
                      booked: 3
                      waitlistCapacity: 2
                      waitlistBooked: 0
                    details:
                      description: >
                        A blend of two popular types of mind-body connected
                        exercise: Yoga and Pilates. Done to calming, relaxed
                        mode music, each discipline has postures which are
                        duplicated with the other, so a blending of these two
                        types of exercise styles is a natural.
                      room:
                        name: room 21
                        description: a gymnasium on 2nd floor
                      level:
                        name: Beginner
                        description: >
                          This level will focus on more intensive techniques,
                          patterns and longer pieces of choreography.
                      pricing:
                        price: 10
                      legalNotes: >
                        Only one free trial can be redeemed per person. No other
                        free trial offer in any form will be available to
                        someone who has previously used a free trial.
                      customInfo:
                        - key: childcare
                          value: true
                        - key: kidshours
                          value: 11am-18pm
                    attendeeBookingDetails:
                      exerciserId: EE3519
                      booked: true
                      waitlistBooked: false
                      waitlistPosition: 0
                      eligibility:
                        addToClassEligibility:
                          eligible: false
                          lackOfProduct: false
                          reason: Booked already
                        removeFromClassEligibility:
                          eligible: true
                        addToWaitlistEligibility:
                          eligible: false
                        removeFromWaitlistEligibility:
                          eligible: false
        '422':
          description: >
            The following causes and reasons are supported (see general
            **Errors** section for more details and examples):

            * cause `bookingFailed`
              * reason `lackOfProduct` -- if operation can't be performed because of lack of Product
              * reason `noFreeSpots` -- if the Class does not have free spots in Waitlist
              * reason `userAlreadyInWaitlist` -- if Exerciser is in this Waitlist already
              * reason `userAlreadyAttendee` -- if Exerciser is an Attendee of the Class already
              * reason `userHasPenalty` -- if operation can't be performed because of user's penalty
              * reason `overlapped` -- if operation can't be performed because class is overlapped
              * reason `partnerRestriction` -- if operation can't be performed because of any other restrictions on partner side
              * reason `unknown` -- if adding to Class Waitlist is impossible due to some business rules on Partner side (`message` should contain details)
    put:
      tags:
        - L3
      summary: Update class booking
      description: >
        This operation changes booking details of GroupX Class for the Attendee
        (Exerciser).


        **NOTE:** This operation is available only if
        *`metaOption::spotBookingEnabled`* = true (use status code 404 endpoint
        not supported).

        #### Additional Contracts

        N/A
      operationId: updateBooking
      parameters:
        - name: exerciserId
          in: path
          description: >
            ClubMS Exerciser Unique ID which is returned by Canonical Users API
            and/or by Canonical Members API.


            ##### Possible reasons of validation errors:

            * notFound => 404
          required: true
          schema:
            type: string
        - name: classId
          in: path
          description: |
            ClubMS Class Unique ID

            ##### Possible reasons of validation errors:
            * notFound => 404
          required: true
          schema:
            type: string
        - name: spot
          in: query
          description: |
            Spot identifier (e.g. spot number).

            ##### Possible reasons of validation errors:
            * noFreeSpots => 422
          required: false
          schema:
            type: string
        - $ref: '#/components/parameters/userLocaleHeader'
        - $ref: '#/components/parameters/userSecretHeader'
        - $ref: '#/components/parameters/userIdHeader'
        - $ref: '#/components/parameters/locationNpConfigurationHeader'
        - $ref: '#/components/parameters/locationNpTimezoneHeader'
        - $ref: '#/components/parameters/locationSecretHeader'
        - $ref: '#/components/parameters/locationIdHeader'
        - $ref: '#/components/parameters/locationGroupNpConfigurationHeader'
        - $ref: '#/components/parameters/locationGroupSecretHeader'
        - $ref: '#/components/parameters/locationGroupIdHeader'
        - $ref: '#/components/parameters/chainNpConfigurationHeader'
        - $ref: '#/components/parameters/chainSecretHeader'
        - $ref: '#/components/parameters/chainIdHeader'
        - $ref: '#/components/parameters/clientNpConfigurationHeader'
        - $ref: '#/components/parameters/clientSecretHeader'
        - $ref: '#/components/parameters/clientIdHeader'
      responses:
        '200':
          description: |
            Class is booked for the Attendee successfully.
            Updated GroupX Class Details returned.

            ##### Contracts
            All sections are required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupXClass'
            .:
              examples:
                response:
                  value:
                    brief:
                      $ref: '#/paths/~1classes/get/responses/200/examples/./0/brief'
                    bookingDetails:
                      capacity: 10
                      booked: 3
                      waitlistCapacity: 2
                      waitlistBooked: 0
                    details:
                      description: >
                        A blend of two popular types of mind-body connected
                        exercise: Yoga and Pilates. Done to calming, relaxed
                        mode music, each discipline has postures which are
                        duplicated with the other, so a blending of these two
                        types of exercise styles is a natural.
                      room:
                        name: room 21
                        description: a gymnasium on 2nd floor
                        roomPhotoUrl: https://s3.amazonaws.com/photo.png
                      level:
                        name: Beginner
                        description: >
                          This level will focus on more intensive techniques,
                          patterns and longer pieces of choreography.
                      legalNotes: >
                        Only one free trial can be redeemed per person. No other
                        free trial offer in any form will be available to
                        someone who has previously used a free trial.
                      pricing:
                        price: 10
                      customInfo:
                        - key: childcare
                          value: true
                        - key: kidshours
                          value: 11am-18pm
                    attendeeBookingDetails:
                      exerciserId: EE3519
                      booked: true
                      waitlistBooked: false
                      spotBooked: A2
                      waitlistPosition: 0
                      eligibility:
                        addToClassEligibility:
                          eligible: false
                          lackOfProduct: false
                          reason: Booked already
                        removeFromClassEligibility:
                          eligible: true
                        addToWaitlistEligibility:
                          eligible: false
                        removeFromWaitlistEligibility:
                          eligible: false
                        updateBookingEligibility:
                          eligible: true
        '422':
          description: >
            The following causes and reasons are supported (see general
            **Errors** section for more details and examples):

            * cause `bookingFailed`
              * reason `lackOfProduct` -- if such booking cannot be done because of lack of Product
              * reason `noFreeSpots` -- if the Class does not have free spots to book or exact spot selected is already occupied
              * reason `userAlreadyAttendee` -- if Exerciser is an Attendee of the Class already
              * reason `userAlreadyInWaitlist` -- if Exerciser is in this Waitlist already
              * reason `overlapped` -- if Exerciser has booked other Class overlapping by time
              * reason `unknown` -- Class booking is impossible due to some business rules on Partner side (`message` should contain details)
    delete:
      tags:
        - L3
      summary: Remove Attendee from Class
      description: >
        This operation cancels GroupX Class for the Attendee (Exerciser).


        **NOTE:** This operation is available only if
        *`metaOption::bookingEnabled`* is true and (use status code 404 endpoint
        not supported).


        #### Additional Contracts

        N/A
      operationId: removeAttendeeFromClass
      parameters:
        - name: exerciserId
          in: path
          description: >
            ClubMS Exerciser Unique ID which is returned by Canonical Users API
            and/or by Canonical Members API.


            ##### Possible reasons of validation errors:

            * notFound => 404
          required: true
          schema:
            type: string
        - name: classId
          in: path
          description: |
            ClubMS Class Unique ID

            ##### Possible reasons of validation errors:
            * notFound => 404
          required: true
          schema:
            type: string
        - $ref: '#/components/parameters/userLocaleHeader'
        - $ref: '#/components/parameters/userSecretHeader'
        - $ref: '#/components/parameters/userIdHeader'
        - $ref: '#/components/parameters/locationNpConfigurationHeader'
        - $ref: '#/components/parameters/locationNpTimezoneHeader'
        - $ref: '#/components/parameters/locationSecretHeader'
        - $ref: '#/components/parameters/locationIdHeader'
        - $ref: '#/components/parameters/locationGroupNpConfigurationHeader'
        - $ref: '#/components/parameters/locationGroupSecretHeader'
        - $ref: '#/components/parameters/locationGroupIdHeader'
        - $ref: '#/components/parameters/chainNpConfigurationHeader'
        - $ref: '#/components/parameters/chainSecretHeader'
        - $ref: '#/components/parameters/chainIdHeader'
        - $ref: '#/components/parameters/clientNpConfigurationHeader'
        - $ref: '#/components/parameters/clientSecretHeader'
        - $ref: '#/components/parameters/clientIdHeader'
      responses:
        '200':
          description: |
            Class is cancelled for the Attendee successfully.
            Updated GroupX Class Details returned.

            ##### Contracts
            All sections are required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupXClass'
            .:
              examples:
                response:
                  value:
                    brief:
                      $ref: '#/paths/~1classes/get/responses/200/examples/./0/brief'
                    bookingDetails:
                      capacity: 10
                      booked: 3
                      waitlistCapacity: 2
                      waitlistBooked: 0
                    details:
                      description: >
                        A blend of two popular types of mind-body connected
                        exercise: Yoga and Pilates. Done to calming, relaxed
                        mode music, each discipline has postures which are
                        duplicated with the other, so a blending of these two
                        types of exercise styles is a natural.
                      room:
                        name: room 21
                        description: a gymnasium on 2nd floor
                      level:
                        name: Beginner
                        description: >
                          This level will focus on more intensive techniques,
                          patterns and longer pieces of choreography.
                      pricing:
                        price: 10
                      legalNotes: >
                        Only one free trial can be redeemed per person. No other
                        free trial offer in any form will be available to
                        someone who has previously used a free trial.
                    attendeeBookingDetails:
                      exerciserId: EE3519
                      booked: false
                      waitlistBooked: false
                      waitlistPosition: 0
                      eligibility:
                        addToClassEligibility:
                          eligible: true
                        removeFromClassEligibility:
                          eligible: false
                        addToWaitlistEligibility:
                          eligible: false
                        removeFromWaitlistEligibility:
                          eligible: false
        '422':
          description: >
            The following causes and reasons are supported (see general
            **Errors** section for more details and examples):

            * cause `unbookingFailed`
              * reason `userNotAttendee` -- if an Exerciser is not an Attendee of the Class
              * reason `unknown` -- if removing from Class is impossible due to some business rules on Partner side (`message` should contain details)
  /classes/{classId}/waitlist/attendees/{exerciserId}:
    post:
      tags:
        - L3
      summary: Add Attendee to Waitlist
      description: >
        This operation books GroupX Class Waitlist for the Attendee (Exerciser).

        Should be implemented in case if .


        **NOTE:** This operation is available only if
        *`metaOption::bookingEnabled`* is true. Use status code 404 if endpoint
        not supported.


        #### Additional Contracts

        N/A
      operationId: addAttendeeToWaitlist
      parameters:
        - name: exerciserId
          in: path
          description: >
            ClubMS Exerciser Unique ID which is returned by Canonical Users API
            and/or by Canonical Members API.


            ##### Possible reasons of validation errors:

            * notFound => 404
          required: true
          schema:
            type: string
        - name: classId
          in: path
          description: |
            ClubMS Class Unique ID

            ##### Possible reasons of validation errors:
            * notFound => 404
          required: true
          schema:
            type: string
        - $ref: '#/components/parameters/userLocaleHeader'
        - $ref: '#/components/parameters/userSecretHeader'
        - $ref: '#/components/parameters/userIdHeader'
        - $ref: '#/components/parameters/locationNpConfigurationHeader'
        - $ref: '#/components/parameters/locationNpTimezoneHeader'
        - $ref: '#/components/parameters/locationSecretHeader'
        - $ref: '#/components/parameters/locationIdHeader'
        - $ref: '#/components/parameters/locationGroupNpConfigurationHeader'
        - $ref: '#/components/parameters/locationGroupSecretHeader'
        - $ref: '#/components/parameters/locationGroupIdHeader'
        - $ref: '#/components/parameters/chainNpConfigurationHeader'
        - $ref: '#/components/parameters/chainSecretHeader'
        - $ref: '#/components/parameters/chainIdHeader'
        - $ref: '#/components/parameters/clientNpConfigurationHeader'
        - $ref: '#/components/parameters/clientSecretHeader'
        - $ref: '#/components/parameters/clientIdHeader'
      responses:
        '200':
          description: |
            Class' Waitlist is booked for the Attendee successfully.
            Updated GroupX Class Details returned.

            ##### Contracts
            All sections are required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupXClass'
            .:
              examples:
                response:
                  value:
                    brief:
                      $ref: '#/paths/~1classes/get/responses/200/examples/./1/brief'
                    bookingDetails:
                      capacity: 10
                      booked: 3
                      waitlistCapacity: 2
                      waitlistBooked: 0
                    details:
                      description: >
                        A blend of two popular types of mind-body connected
                        exercise: Yoga and Pilates. Done to calming, relaxed
                        mode music, each discipline has postures which are
                        duplicated with the other, so a blending of these two
                        types of exercise styles is a natural.
                      room:
                        name: room 21
                        description: a gymnasium on 2nd floor
                      level:
                        name: Beginner
                        description: >
                          This level will focus on more intensive techniques,
                          patterns and longer pieces of choreography.
                      pricing:
                        price: 10
                      legalNotes: >
                        Only one free trial can be redeemed per person. No other
                        free trial offer in any form will be available to
                        someone who has previously used a free trial.
                    attendeeBookingDetails:
                      exerciserId: EE3519
                      booked: false
                      waitlistBooked: true
                      waitlistPosition: 1
                      eligibility:
                        addToClassEligibility:
                          eligible: false
                          lackOfProduct: false
                          reason: Waitlisted already
                        removeFromClassEligibility:
                          eligible: false
                        addToWaitlistEligibility:
                          eligible: false
                          reason: Waitlisted already
                        removeFromWaitlistEligibility:
                          eligible: true
        '422':
          description: >
            The following causes and reasons are supported (see general
            **Errors** section for more details and examples):

            * cause `addToWaitlistFailed`
              * reason `lackOfProduct` -- if operation can't be performed because of lack of Product
              * reason `noFreeSpots` -- if the Class does not have free spots in Waitlist
              * reason `userAlreadyInWaitlist` -- if Exerciser is in this Waitlist already
              * reason `userAlreadyAttendee` -- if Exerciser is an Attendee of the Class already
              * reason `userHasPenalty` -- if operation can't be performed because of user's penalty
              * reason `overlapped` -- if operation can't be performed because class is overlapped
              * reason `partnerRestriction` -- if operation can't be performed because of user's penalty
              * reason `unknown` -- if adding to Class Waitlist is impossible due to some business rules on Partner side (`message` should contain details)
    delete:
      tags:
        - L3
      summary: Remove Attendee from Waitlist
      description: >
        This operation cancels GroupX Class Waitlist for the Attendee
        (Exerciser).


        **NOTE:** This operation is available only if
        *`metaOption::bookingEnabled`* is true (use status code 404 endpoint not
        supported).


        #### Additional Contracts

        N/A
      operationId: removeAttendeeFromWaitlist
      parameters:
        - name: exerciserId
          in: path
          description: >
            ClubMS Exerciser Unique ID which is returned by Canonical Users API
            and/or by Canonical Members API.


            ##### Possible reasons of validation errors:

            * notFound => 404
          required: true
          schema:
            type: string
        - name: classId
          in: path
          description: |
            ClubMS Class Unique ID

            ##### Possible reasons of validation errors:
            * notFound => 404
          required: true
          schema:
            type: string
        - $ref: '#/components/parameters/userLocaleHeader'
        - $ref: '#/components/parameters/userSecretHeader'
        - $ref: '#/components/parameters/userIdHeader'
        - $ref: '#/components/parameters/locationNpConfigurationHeader'
        - $ref: '#/components/parameters/locationNpTimezoneHeader'
        - $ref: '#/components/parameters/locationSecretHeader'
        - $ref: '#/components/parameters/locationIdHeader'
        - $ref: '#/components/parameters/locationGroupNpConfigurationHeader'
        - $ref: '#/components/parameters/locationGroupSecretHeader'
        - $ref: '#/components/parameters/locationGroupIdHeader'
        - $ref: '#/components/parameters/chainNpConfigurationHeader'
        - $ref: '#/components/parameters/chainSecretHeader'
        - $ref: '#/components/parameters/chainIdHeader'
        - $ref: '#/components/parameters/clientNpConfigurationHeader'
        - $ref: '#/components/parameters/clientSecretHeader'
        - $ref: '#/components/parameters/clientIdHeader'
      responses:
        '200':
          description: |
            Class' Waitlist is cancelled for the Attendee successfully.
            Updated GroupX Class Details returned.

            ##### Contracts
            All sections are required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupXClass'
            .:
              examples:
                response:
                  value:
                    brief:
                      $ref: '#/paths/~1classes/get/responses/200/examples/./1/brief'
                    bookingDetails:
                      capacity: 10
                      booked: 3
                      waitlistCapacity: 2
                      waitlistBooked: 0
                    details:
                      description: >
                        A blend of two popular types of mind-body connected
                        exercise: Yoga and Pilates. Done to calming, relaxed
                        mode music, each discipline has postures which are
                        duplicated with the other, so a blending of these two
                        types of exercise styles is a natural.
                      room:
                        name: room 21
                        description: a gymnasium on 2nd floor
                      level:
                        name: Beginner
                        description: >
                          This level will focus on more intensive techniques,
                          patterns and longer pieces of choreography.
                      pricing:
                        price: 10
                      legalNotes: >
                        Only one free trial can be redeemed per person. No other
                        free trial offer in any form will be available to
                        someone who has previously used a free trial.
                    attendeeBookingDetails:
                      exerciserId: EE3519
                      booked: false
                      waitlistBooked: false
                      waitlistPosition: 0
                      eligibility:
                        addToClassEligibility:
                          eligible: true
                        removeFromClassEligibility:
                          eligible: false
                        addToWaitlistEligibility:
                          eligible: true
                        removeFromWaitlistEligibility:
                          eligible: false
        '422':
          description: >
            The following causes and reasons are supported (see general
            **Errors** section for more details and examples):

            * cause `removeFromWaitlistFailed`
              * reason `userNotInWaitlist` -- if an Exerciser is not added to the Class Waitlist
              * reason `unknown` -- if removing from Class Waitlist is impossible due to some business rules on Partner side (`message` should contain details)
  /exercisers/{exerciserId}/schedule:
    get:
      tags:
        - L3
      summary: Get Exerciser Class Schedule
      description: >
        This operation retrieves Attendee (Exerciser) Class schedule.


        **NOTE:** This operation is available only if
        *`metaOption::bookingEnabled`* is true (use status code 404 endpoint not
        supported).
      operationId: getExerciserClassSchedule
      parameters:
        - name: exerciserId
          in: path
          description: >
            ClubMS Exerciser Unique ID which is returned by Canonical Users API
            and/or by Canonical Members API.


            ##### Possible reasons of validation errors:

            * notFound => 404
          required: true
          schema:
            type: string
        - name: endDateTime
          in: query
          description: |
            Defines end of the timerange to get Exerciser's schedule

            ##### Possible reasons of validation errors:
            * missing => 400
            * wrongFormat => 400
            * lessThanStartDateTime => 400
          required: true
          schema:
            type: string
            format: date-time
        - name: startDateTime
          in: query
          description: |
            Defines start of the timerange to get Exerciser's schedule

            ##### Possible reasons of validation errors:
            * missing => 400
            * wrongFormat => 400
            * greaterThanEndDateTime => 400
          required: true
          schema:
            type: string
            format: date-time
        - $ref: '#/components/parameters/userLocaleHeader'
        - $ref: '#/components/parameters/userSecretHeader'
        - $ref: '#/components/parameters/userIdHeader'
        - $ref: '#/components/parameters/locationNpConfigurationHeader'
        - $ref: '#/components/parameters/locationNpTimezoneHeader'
        - $ref: '#/components/parameters/locationSecretHeader'
        - $ref: '#/components/parameters/locationIdHeader'
        - $ref: '#/components/parameters/locationGroupNpConfigurationHeader'
        - $ref: '#/components/parameters/locationGroupSecretHeader'
        - $ref: '#/components/parameters/locationGroupIdHeader'
        - $ref: '#/components/parameters/chainNpConfigurationHeader'
        - $ref: '#/components/parameters/chainSecretHeader'
        - $ref: '#/components/parameters/chainIdHeader'
        - $ref: '#/components/parameters/clientNpConfigurationHeader'
        - $ref: '#/components/parameters/clientSecretHeader'
        - $ref: '#/components/parameters/clientIdHeader'
      responses:
        '200':
          description: >
            Returns list of GroupX Classes where Attendee (Exerciser) is booked
            or waitlisted into.


            ##### Contracts

            * All sections are required.

            * `free` flag is required.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/GroupXClass'
            .:
              examples:
                response:
                  value:
                    - brief:
                        $ref: '#/paths/~1classes/get/responses/200/examples/./0/brief'
                      bookingDetails:
                        capacity: 10
                        booked: 3
                        waitlistCapacity: 2
                        waitlistBooked: 0
                      details:
                        description: >
                          A blend of two popular types of mind-body connected
                          exercise: Yoga and Pilates. Done to calming, relaxed
                          mode music, each discipline has postures which are
                          duplicated with the other, so a blending of these two
                          types of exercise styles is a natural.
                        room:
                          name: room 21
                          description: a gymnasium on 2nd floor
                        level:
                          name: Beginner
                          description: >
                            This level will focus on more intensive techniques,
                            patterns and longer pieces of choreography.
                        pricing:
                          price: 10
                        legalNotes: >
                          Only one free trial can be redeemed per person. No
                          other free trial offer in any form will be available
                          to someone who has previously used a free trial.
                        customInfo:
                          - key: childcare
                            value: true
                          - key: kidshours
                            value: 11am-18pm
                      attendeeBookingDetails:
                        exerciserId: EE3519
                        booked: false
                        waitlistBooked: true
                        waitlistPosition: 1
                        eligibility:
                          addToClassEligibility:
                            eligible: false
                            lackOfProduct: false
                            reason: Booked already
                          removeFromClassEligibility:
                            eligible: true
                          addToWaitlistEligibility:
                            eligible: false
                          removeFromWaitlistEligibility:
                            eligible: false
tags:
  - name: L2
    description: Operations related to L2 level of integration
  - name: L3
    description: Operations related to L3 level of integration
externalDocs:
  url: https://github.com/netpulse/server-anticorr-contracts
  description: GroupX Class meta-options
servers:
  - url: https://example.org/%3Cpartner%3E/group-classes/v1.0
components:
  parameters:
    clientIdHeader:
      name: X-Client-ID
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
    clientSecretHeader:
      name: X-Client-Secret
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
    clientNpConfigurationHeader:
      name: X-NP-Client-Configuration
      in: header
      description: >
        ![Professional Services
        only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)see
        'Additional Data HTTP Headers' for details.
      schema:
        type: string
    chainIdHeader:
      name: X-Chain-ID
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
    chainSecretHeader:
      name: X-Chain-Secret
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
    chainNpConfigurationHeader:
      name: X-NP-Chain-Configuration
      in: header
      description: >
        ![Professional Services
        only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)see
        'Additional Data HTTP Headers' for details.
      schema:
        type: string
    locationGroupIdHeader:
      name: X-Location-Group-ID
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
    locationGroupSecretHeader:
      name: X-Location-Group-Secret
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
    locationGroupNpConfigurationHeader:
      name: X-NP-Location-Group-Configuration
      in: header
      description: >
        ![Professional Services
        only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)see
        'Additional Data HTTP Headers' for details.
      schema:
        type: string
    locationIdHeader:
      name: X-Location-ID
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
    locationSecretHeader:
      name: X-Location-Secret
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
    locationNpTimezoneHeader:
      name: X-NP-Location-Timezone
      in: header
      description: >
        ![Professional Services
        only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)see
        'Additional Data HTTP Headers' for details.
      schema:
        type: string
    locationNpConfigurationHeader:
      name: X-NP-Location-Configuration
      in: header
      description: >
        ![Professional Services
        only](http://icons.iconarchive.com/icons/graphicloads/flat-finance/32/lock-icon.png)see
        'Additional Data HTTP Headers' for details.
      schema:
        type: string
    userIdHeader:
      name: X-User-ID
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
    userSecretHeader:
      name: X-User-Secret
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
    userLocaleHeader:
      name: X-User-Locale
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
  schemas:
    GroupXClassBrief:
      type: object
      description: Brief details of the groupX class for bulk retrieval
      properties:
        id:
          type: string
          description: >-
            Unique ID of the GroupX Class in the ClubMS. This is the same ID
            that's used in `getClassDetails` operation
        name:
          type: string
          description: Name of the Class (e.g. 'Yoga 24', 'TRX Small Group', 'Body Pump')
        startDateTime:
          type: string
          description: Start date/time of the GroupX Class in UTC timezone
          format: date-time
        endDateTime:
          type: string
          description: End date/time of the GroupX Class in UTC timezone
          format: date-time
        locationId:
          type: string
          description: >
            Unique ID of the location in ClubMS that this class belongs to. This
            is the same ID as returned by Canonical Locations API or as manually
            provided to Netpulse admins for locations configuration.
        free:
          type: boolean
          description: Indicates that the class is free (not paid)
        waitlisted:
          type: boolean
          description: >-
            Indicates whether the given exerciser is in the waitlist of this
            class
        childCare:
          type: boolean
          description: Defines if child care option is available for the Class
        reservable:
          type: boolean
          description: Defines if Class is reservable
        instructor:
          type: object
          description: |
            *Required property* Information about Intructor who leads the Class
          properties:
            firstName:
              type: string
            lastName:
              type: string
            fullName:
              type: string
            customInfo:
              $ref: '#/components/schemas/CustomInfo'
          required:
            - fullName
        activity:
          type: object
          description: |
            *Required property* Information about Activity of the Class
          properties:
            name:
              type: string
              description: >-
                Name of the Class activity (e.g. 'Yoga 24', 'TRX Small Group',
                'Body Pump'), often it is the same as groupX class name, but it
                might be also a more general name (depends on ClubMS, e.g.
                'Yoga', 'TRX')
          required:
            - name
        customInfo:
          $ref: '#/components/schemas/CustomInfo'
      required:
        - id
        - name
        - startDateTime
        - endDateTime
    CustomInfo:
      type: array
      description: >
        Key-Value map to represent additional information of an entity.

        Partners could contain diverse information of same entities. This type
        designed to store that information.
      items:
        type: object
        properties:
          key:
            type: string
          value:
            type: string
        required:
          - key
          - value
    GroupXClass:
      type: object
      description: GroupX Class with all details
      properties:
        brief:
          $ref: '#/components/schemas/GroupXClassBrief'
        bookingDetails:
          $ref: '#/components/schemas/GroupXClassBookingDetails'
        details:
          $ref: '#/components/schemas/GroupXClassDetails'
        attendeeBookingDetails:
          $ref: '#/components/schemas/GroupXClassAttendeeBookingDetails'
      required:
        - brief
        - details
    GroupXClassBookingDetails:
      type: object
      description: Booking details of the GroupX Class
      properties:
        capacity:
          type: integer
          description: Capacity of the GroupX Class for booking online
          format: int32
        booked:
          type: integer
          description: Spots booked online for this GroupX Class
          format: int32
        waitlistCapacity:
          type: integer
          format: int32
        waitlistBooked:
          type: integer
          format: int32
        availableSpots:
          type: array
          items:
            type: string
      required:
        - capacity
        - booked
        - waitlistCapacity
        - waitlistBooked
    GroupXClassDetails:
      type: object
      description: Comprehensive details of the groupX class
      properties:
        description:
          type: string
          description: Long description of the groupX class
        room:
          type: object
          description: |
            **Optional property** The room where this class takes place.
          properties:
            name:
              type: string
              description: Short name of the room.
            description:
              type: string
              description: Details about this room
            roomPhotoUrl:
              type: string
              description: URL to the room scheme or photo
            customInfo:
              $ref: '#/components/schemas/CustomInfo'
          required:
            - name
        level:
          type: object
          description: >
            **Optional property** The level of the groupX class (e.g.
            'Intermediate', 'Advanced')
          properties:
            name:
              type: string
              description: Short name of the level.
            description:
              type: string
              description: Details about this level
          required:
            - name
        pricing:
          type: object
          description: >
            **Optional property** The price of paid groupX class. If the class
            is free could be omited
          properties:
            price:
              type: number
              description: price amount
              format: double
          required:
            - price
        legalNotes:
          type: string
          description: Legal notes for this class (often provider specific)
        customInfo:
          $ref: '#/components/schemas/CustomInfo'
    GroupXClassAttendeeBookingDetails:
      type: object
      description: Information about attendance of the given exerciser in this GroupX Class
      properties:
        exerciserId:
          type: string
          description: >-
            ClubMS Exerciser Unique ID which is returned by Canonical Users API
            and/or by Canonical Members API.
        booked:
          type: boolean
          description: Indicates whether this class is booked by the given exerciser
        waitlistBooked:
          type: boolean
          description: >-
            Indicates whether the given exerciser is in the waitlist of this
            class
        spotBooked:
          type: string
          description: Indicates exact spot booked by the given exerciser
        eligibility:
          $ref: '#/components/schemas/GroupXClassEligibility'
        waitlistPosition:
          type: integer
          description: Position of given exerciser in the waitlist of this class
          format: int32
      required:
        - exerciserId
        - booked
        - waitlistBooked
    GroupXClassEligibility:
      type: object
      description: >
        Represents booking/cancellation opearions eligibility for
        Class/Exerciser pair.
      properties:
        addToClassEligibility:
          $ref: '#/components/schemas/GroupXClassOperationExtendedEligibility'
        bookSpotEligibility:
          $ref: '#/components/schemas/GroupXClassOperationEligibility'
        removeFromClassEligibility:
          $ref: '#/components/schemas/GroupXClassOperationEligibility'
        addToWaitlistEligibility:
          $ref: '#/components/schemas/GroupXClassOperationExtendedEligibility'
        removeFromWaitlistEligibility:
          $ref: '#/components/schemas/GroupXClassOperationEligibility'
        updateBookingEligibility:
          $ref: '#/components/schemas/GroupXClassOperationEligibility'
      required:
        - addToClassEligibility
        - removeFromClassEligibility
        - addToWaitlistEligibility
        - removeFromWaitlistEligibility
    GroupXClassOperationExtendedEligibility:
      type: object
      description: >-
        Represents particular operation eligibility for Class/Exerciser pair
        providing extra data.
      properties:
        eligible:
          type: boolean
          description: >
            Indicates if operation on a given Class is eligible for a give
            Exerciser.
        lackOfProduct:
          type: boolean
          description: >
            Indicates that there are enough products on an Exerciser's account
            balance to pay for a Class. Products could be Class bundles, points
            etc.

            This attribute must be absent for eligible=`true`.
        userPaymentOnFile:
          type: boolean
          description: >
            Indicates that user has a valid payment source on file to pay for a
            Class.

            This attribute must be absent for eligible=`true` or
            lackOfProduct=`false`.
      required:
        - eligible
    GroupXClassOperationEligibility:
      type: object
      description: Represents particular operation eligibility for Class/Exerciser pair.
      properties:
        eligible:
          type: boolean
          description: >
            Indicates if operation on a given Class is eligible for a given
            Exerciser.
      required:
        - eligible
