openapi: 3.0.0
info:
  title: My Account API Blueprint
  description: >
    # Introduction


    This specification defines *API Blueprint* for "My Account" functionallity.
    The methods and data models in this specification should serve as a
    blueprint that *can* be implemented by member management systems to allow
    for an easy connection of EGYM platform to their systems. **So, this is not
    an API specification of an API on EGYM's servers**. EGYM can, however, also
    adapt to other methods and data structures. However, there are limitations
    on the supported authentication approaches (only API key authentication, no
    single-user authorization) as well as to the nature of the supported API
    architectures (only backend-to-backend APIs are supported, so API calls can
    be done in the background and without authentication of each single user).


    More on why these limitations exist can be found in the API Overview where
    we also explain the data privacy concept behind this decision.


    # What this API is about

    The My Account API should provide access to the gym's base member profile
    data. The main use-case is to allow EGYM to view and to update members'
    profiles in the member management software. Typical operations include
    changing the users' name, birthday, picture or



    # API architecture requirements

    This API needs to be impleneted for a **server-to-server** use-case. That
    means: Authentication needs to be done on a per-gym level (or
    per-location/per-chain), but not on a per user level with individual logins.

    The reason for the architecture choice is rooted in the data privacy model:
    we are operating on "gym data" which belongs to the gym and not to an
    individual user as per our definition of the data privacy model. This allows
    us to also implement use-cases where e.g. a trainer would manage pieces of
    this information from the EGYM trainer app on the user's behalf.


    # General API Contracts

    ## Authentication

    This API uses **token-based authorization only** while the level of
    authentication may differ e.g. single a single token for a gym chain, or a
    gym location/individual club.


    ### Authentication HTTP Headers

    There are several standard HTTP Headers listed below that may be used and
    can easily be configured in order to provide authentication data to every
    operation.


    #### 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.)


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    #### X-Chain-Secret

    This header provides chain-level secret ("API key") correspondent to the
    chain ID defined in `X-Chain-ID` header.


    Required if API expects access tokens Chain level.


    #### 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.)


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    #### X-Location-Secret

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

    Required if API expects access tokens on Location level.


    #### X-Client-Secret

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

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


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    #### X-User-ID

    This header provides ID of a user which is accessing his/her data.


    Possible reasons of validation errors:

    * missing => 400

    * invalid => 401


    ### 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)

    2010-08-21T22-31-20Z (time separated with '-')

    ```

    ### Errors

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


    General Requirements:

    * 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.



    Example:

    ```

    {
      "message": "Bad Request",
      "cause": "badRequest",
      "errors": {
        "locationId": "missing",
        "firstName": "missing"
      }
    }

    ```


    #### 401: Unauthorized Access

    Cause is `unauthorizedAccess`. Bad, unexpected or expired access data (see
    'Authentication HTTP Headers': `X-Client-Secret`,
    `X-Chain-ID`/`X-Chain-Secret`, `X-Location-ID`/`X-Location-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"
    }

    ```



    #### 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.


    Example:

    ```

    // 1st example

    {
      "message": "Cannot create a my account for the user as it was already created",
      "cause": "guestPassAlreadyCreated",
      "reason": "guestPassAlreadyCreated"
    }

    ```

    &nbsp;


    #### 429: Too Many Requests

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


    Example:

    ```

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

    ```


    #### 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"
    }

    ```


    foo.    
  version: '1.0'
paths:
  /{member_id}/personal:
    get:
      tags:
        - My Account
      summary: Get My Account Information
      description: |
        This operation retrieves users membership details info
      operationId: getMyAccount
      parameters:
        - name: member_id
          in: path
          description: Member ID of user that is accessing data
          required: true
          schema:
            type: string
        - $ref: '#/components/parameters/userIdHeader'
        - $ref: '#/components/parameters/locationSecretHeader'
        - $ref: '#/components/parameters/locationIdHeader'
        - $ref: '#/components/parameters/chainSecretHeader'
        - $ref: '#/components/parameters/chainIdHeader'
        - $ref: '#/components/parameters/clientSecretHeader'
      responses:
        '200':
          description: |
            My Account is created successfuly
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AccountInfo'
        '400':
          description: |
            Error code returned in case validation failed
        '401':
          description: |
            Error code returned in case authentication failed
    post:
      tags:
        - My Account
      summary: Update My Account Info
      description: |
        This operation updates users membership details info
      operationId: updateMyAccount
      parameters:
        - name: member_id
          in: path
          description: Member ID of user that is accessing data
          required: true
          schema:
            type: string
        - $ref: '#/components/parameters/userIdHeader'
        - $ref: '#/components/parameters/locationSecretHeader'
        - $ref: '#/components/parameters/locationIdHeader'
        - $ref: '#/components/parameters/chainSecretHeader'
        - $ref: '#/components/parameters/chainIdHeader'
        - $ref: '#/components/parameters/clientSecretHeader'
      requestBody:
        content:
          application/json:
            schema: {}
        description: Data needed to update my account
      responses:
        '200':
          description: |
            Updated My Account info
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AccountInfo'
        '400':
          description: |
            Error code returned in case validation failed
        '401':
          description: |
            Error code returned in case authentication failed
tags:
  - name: My Account
    description: >-
      Operations related to the user's profile within the member management
      system
servers:
  - url: https://example.org/%3Cpartner%3E/members/v1.0
components:
  parameters:
    clientSecretHeader:
      name: X-Client-Secret
      in: header
      description: 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
    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
    userIdHeader:
      name: X-User-ID
      in: header
      description: see 'Additional Data HTTP Headers' for details.
      schema:
        type: string
  schemas:
    AccountInfo:
      type: object
      description: Users bank info
      properties:
        personalInfo:
          $ref: '#/components/schemas/PersonalInfo'
        agreementInfo:
          $ref: '#/components/schemas/AgreementInfo'
        contactInfo:
          $ref: '#/components/schemas/ContactInfo'
        bankInfo:
          $ref: '#/components/schemas/BankInfo'
    PersonalInfo:
      type: object
      description: User personal info data
      properties:
        firstName:
          type: string
          description: First Name of the user
        lastName:
          type: string
          description: Last Name of the user
        email:
          type: string
          description: Email of the user
        country:
          type: string
          description: User's country, optional
        city:
          type: string
          description: User's city, optional
        address:
          type: string
          description: User's street name and building number, optional
        zipCode:
          type: string
          description: User's zipcode, optional
    AgreementInfo:
      type: object
      description: >-
        This object represents agreement details that is currently linked to
        this membership i.e. single membership may have a lot of monthly or
        yearly agreements that will change over time while membership will
        remain the same
      properties:
        agreementNumber:
          type: string
          description: Agreement Number of the user
        agreementBegan:
          type: string
          description: Date when agreement was started
          format: date
        agreementEnd:
          type: string
          description: Date when agreement ends
          format: date
        agreementType:
          type: string
          description: Agreement Type
        renewalType:
          type: string
          description: Renewal Type
        membershipStatus:
          type: string
          description: User's membership status
        membershipType:
          type: string
          description: User's membership type
        membershipSince:
          type: string
          description: Date when membership started
          format: date
    ContactInfo:
      type: object
      description: Users contact info
      properties:
        email:
          type: string
          description: Users email
        privatePhone:
          type: string
          description: Users private phone
          format: phone
        mobilePhone:
          type: string
          description: Users mobile phone
          format: phone
        workPhone1:
          type: string
          description: Users primary work phone
          format: phone
        workPhone2:
          type: string
          description: Users secandary work phone
          format: phone
    BankInfo:
      type: object
      description: Users bank info
      properties:
        accountHolder:
          type: string
          description: Account holder full name
        iban:
          type: string
          description: Account IBAN
        bic:
          type: string
          description: Account BIC
