consulbit
2/7/2017 - 6:38 AM

OpenAPI Specification (fka Swagger Specification) tutorial files from [API Handyman blog](http://apihandyman.io)

OpenAPI Specification (fka Swagger Specification) tutorial files from API Handyman blog

swagger: "2.0"
  
info:
  version: 1.0.0
  title: Legacy Sub-API
  description: Legacy operations

securityDefinitions:
  $ref: commons.yaml#/securityDefinitions

paths:
  /js-less-consumer-persons:
    parameters:
      - $ref: 'commons.yaml#/parameters/userAgent'
    post:
      summary: Creates a person
      description: For JS-less partners
      operationId: createUserJS
      deprecated: true
      tags:
        - JSLess
        - Persons
      security:
        - OauthSecurity:
          - admin
        - LegacySecurity: []
      consumes:
        - application/x-www-form-urlencoded
      produces:
        - text/html
      parameters:
        - name: username
          in: formData
          required: true
          pattern: '[a-z0-9]{8,64}'
          minLength: 8
          maxLength: 64
          type: string
        - name: firstname
          in: formData
          type: string
        - name: lastname
          in: formData
          type: string
        - name: dateOfBirth
          in: formData
          type: string
          format: date
      responses:
        '204':
          description: Person succesfully created.
          headers:
            $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
        '400':
          description: Person couldn't have been created.
          headers:
            $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
        '500':
          description: An error occured.
          headers:
            $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
        default:
          $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
swagger: "2.0"
  
info:
  version: 1.0.0
  title: Images Sub-API
  description: images operations

securityDefinitions:
  $ref: commons.yaml#/securityDefinitions

paths: 
  /images:
    parameters:
      - $ref: 'commons.yaml#/parameters/userAgent'
    post:
      summary: Uploads an image
      description: Upload an image, will return an image id. 
      operationId: storeImage
      externalDocs:
        description: How to upload media
        url: http://doc.simple.api/media/upload
      tags:
        - Media
      security:
        - MediaSecurity: []
      consumes:
        - multipart/form-data
      parameters:
        - name: image
          in: formData
          type: file
      responses:
        '200':
          description: Image's ID
          schema:
            properties:
              imageId:
                type: string
          headers:
            $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
        '500':
          $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
        default:
          $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
  /images/{imageId}:
    parameters:
      - $ref: 'commons.yaml#/parameters/userAgent'
    get:
      summary: Gets an image
      description: Return an image 
      operationId: readImage
      tags:
        - Media
      parameters:
        - name: imageId
          in: path
          required: true
          type: string
      produces:
        - image/png
        - image/gif
        - image/jpeg
        - application/json
        - application/x-yaml
      responses:
        '200':
          description: The image
          headers:
            $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
        '404':
          description: Image do not exists
          headers:
            $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
        '500':
          $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
        default:
          $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
swagger: "2.0"
  
info:
  version: 1.0.0
  title: Persons Sub-API
  description: Persons operations, definitions, parameters and responses

securityDefinitions:
  $ref: commons.yaml#/securityDefinitions

paths:
  '/persons':
      parameters:
        - $ref: 'commons.yaml#/parameters/userAgent'
      get:
        summary: Gets some persons
        description: Returns a list containing all persons. The list supports paging.
        operationId: searchUsers
        tags:
          - Persons
        parameters:
          - $ref: 'commons.yaml#/parameters/pageSize'
          - $ref: 'commons.yaml#/parameters/pageNumber'
          - $ref: '#/parameters/includeNonVerifiedUsers'
          - $ref: '#/parameters/sortPersons'
        responses:
          '200':
            description: A list of Person
            schema:
              $ref: '#/definitions/Persons'
            headers:
              $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
          '500':
            $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
          default:
            $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
      post:
        summary: Creates a person
        description: Adds a new person to the persons list.
        operationId: createUser
        tags:
          - Persons
        security:
          - OauthSecurity:
            - admin
          - LegacySecurity: []
        parameters:
          - name: person
            in: body
            required: true
            description: The person to create.
            schema:
              $ref: '#/definitions/Person'
        responses:
          '204':
            description: Person succesfully created.
            headers:
              $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
          '400':
            description: Person couldn't have been created.
            headers:
              $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
          '500':
            $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
          default:
            $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
  '/persons/{username}':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: 'commons.yaml#/parameters/userAgent'
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      operationId: readPerson
      tags:
        - Persons
      responses:
        '200':
          description: A Person
          schema:
            $ref: '#/definitions/Person'
          headers:
            $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
        default:
          $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      operationId: deletePerson
      tags:
        - Persons
      responses:
        '204':
          description: Person successfully deleted.
          headers:
            $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
        default:
          $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/friends':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: 'commons.yaml#/parameters/userAgent'
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      operationId: readPersonsFriends
      tags:
        - Persons
      parameters:
        - $ref: 'commons.yaml#/parameters/pageSize'
        - $ref: 'commons.yaml#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A person's friends list
          schema:
            $ref: '#/definitions/PagedPersons'
          headers:
            $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
        default:
          $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'

  '/persons/{username}/collecting-items':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: 'commons.yaml#/parameters/userAgent'
    get:
      summary: Gets a person's collecting items list
      description: |
        Returns a list containing all items this person is looking for.  
        The list supports paging.
      operationId: readPersonsCollectingItems
      tags:
        - Items
      parameters:
        - $ref: 'commons.yaml#/parameters/pageSize'
        - $ref: 'commons.yaml#/parameters/pageNumber'
        - $ref: '#/parameters/filterItemTypes'
      responses:
        '200':
          description: A collected items list
          schema:
            $ref: '#/definitions/PagedCollectingItems'
          headers:
            $ref: 'commons.yaml#/responses/DefaultHeaders/headers'
          examples:
            application/json:
              {
                "totalItems": 10,
                "totalPage": 4,
                "pageSize": 3,
                "currentPage": 2,
                "items": 
                [
                  { 
                    "itemType": "Vinyl",
                    "maxPrice": 20,
                    "imageId": "98096838-04eb-4bac-b32e-cd5b7196de71",
                    "albumName": "Captain Future Original Soundtrack",
                    "artist": "Yuji Ohno"
                  },
                  { 
                    "itemType": "VHS",
                    "maxPrice": 10,
                    "imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
                    "movieTitle": "Star Crash",
                    "director": "Luigi Cozzi"
                  },
                  { 
                    "itemType": "AudioCassette",
                    "maxPrice": 10,
                    "imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
                    "albumName": "Star Wars",
                    "artist": "John Williams"
                  }
                ]
              }
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
        default:
          $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'

definitions:
  Person:
    title: Human
    description: A person which can be the user itself or one of his friend
    required:
      - username
    properties:
      firstName:
        description: first name
        type: string
        example: John
      lastName:
        description: last name
        type: string
        example: Doe
      username:
        description: Username used to connect to the service
        type: string
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
        example: john1doe6
      dateOfBirth:
        description: Date of birth
        type: string
        format: date
        example: 1978-06-21
      lastTimeOnline:
        description: The last time this person was connected to the service as a 
        type: string
        format: date-time
        readOnly: true
        example: 2016-06-10T12:36:58.014Z
      avatarBase64PNG:
        description: An avatar PNG image as a base64 encoded string ready to use as an src in img html tag
        type: string
        format: byte
        default: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAC4jAAAuIwF4pT92AAABy2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBJbWFnZVJlYWR5PC94bXA6Q3JlYXRvclRvb2w+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgqyI37xAAAU3UlEQVR4AeVbeXRc1Xn/zZt90UgajXbJ1mYtNraM95XF2AbbFINLg1sgBCg9JicnpDk9TciBAzQlFDds56T0QE45PTkQTNkhTmnslthhMWAweMObbGuzJdmythnNPtPfd9+MLEWyZFkj8keu/d685b577/f71vvdK0POwmsS+DMu2p8x7Yr0Px0AiUGCJ9fqftCzb4gzpm+oH70bIdJgADQNPCeJ5iPep0hPDAFD1ZrUIX5DAAh5JNpIgYtGEe/3IRrwIxIOKcJNRiM0oxlGqw0aD5gtrG5EIh6fVOKl8UkHQJFOYhCNIHLuHAJtzQj3dV2QMM2gwZpbBJs3H6aMLMRFYpR6XPCTCb2YVAAU8SQo3tsNX+NRhH3d+mD5TKmC8F8qCZFSSGg8EUego0UdjrwSOEorkBCJmCQQJhUA8h3h9hb0nPha0SdiTblOHvojdRYQBhcBiHahn0BE/b1w186eNBAmzQsYyNUQxV0RL4QLl+Oxi+MkQTLEorQZJoQJgL/5OLRJkoD0A8CBilWPnutAb+MRgERcNOFJKTDRWLrsFrgsGj83K3WI+XqUVKRbFdIPAIlHKIi+hv06OcL1QWUkx5Z6ZjUbUZKbCavRgL5AWB1ZDhMyzEB/Z4cuBSl7MajNiVym1wYkuR/q7iTT4yguzIfZRHcmIk29joTD8Pv6EAxHEY2LwaO08J/TakJWhgNNHd1oOUNOs2y8bol69/J7H6r77P4uxCJhGNJsENMLgHAnFkO8+wzcTitaT7erwY90spkMcLFOMBRFL7ktx5y6ctz7rdVYXF8Nb1YGQTPg+7euxYP/tgXbd+1DUTyKEKxs7o+t5kg9XNyztAOgkUv+c2dU70/+9MeYXlOl7F9Pnw+nW09h/6c78NnBRnzZGkCwV+f2t1YvxvoV87F4VjVyszMoMQnGSzGSmcDsmqn4l/tuxbxdP4aBsYRmMyjJoVW9OArHqJVGACjOFHOXlkAHO9368vNYs3J5MprTBxunPfDftAo9pxrQ091FVYjDbrcpol38jVJ6gqGIAky4Lwri6w+iakoBHvq7DXjk+S9RvtyD3vAYVI3jdRoBMMBKA3i8rQvrr7sayxbNQSgUJifpzpKGS36t2QXId3uQ66dO97YhTomJUaIDrCvVNO08Z+VKpMDEdmdWT+Xd7+GgTeklSGkSAAboaSoitjYTm2vzo/6yOljMZsQZy5tMJhgZ68uhkZAEpSCumZFw5yORW40oo/E4OW9kPU0zKSkSSTp/GJXI53rcHKmGbhLvoLegDU1LSYsEyFgs5Jw/QpcXPak4LsQKB4PBQJJZtPeKuRRtegUBxuZwIZGZj3hXI8LBfgJGaZF/SYkRCkUNHHa6RosZeXWlqMiw4w/HOlCcn4H+aByDBEaqj7ukBQAzB9xGK76iNBO3fn8Tunp6SXgQW97ZhoAlE3arFf3hCAGKwCzAUBr62lpw29rlqMjPxNbfHcDBcB48WW4EI1H0BENK7E0U944znVhfdRZWStc965bih5u+jceffQmbt3yIqRUe+AT0CZS0AJBJP96+6yv86KEnUFroxQ8e2Izm5mZEcquwau31Ss/b+0M43ueHm+JrtVhx6GgDjnKOUJabgUPBbFz7t99jAKSRoAj2dfbAZTYRBANyghHs3fYSZrp8ONnarkBac9UCbH7yNdirc//0AIgRCYkVQxatdZHMYXDyVDt6evtQkFeqwuAE43pQvI3Uf2OcekB3lkGrbws5qP9ReDzZYLikgJJ8gRaju6M3McTEsBpgycyEr7cDO/Y1INAfgN0msYCZxlMUZGJRQVokQLdHRkQ4+JxsNwdvRFtbO7TKMtjsDsTIWVuC8/xIHFZy1kwDaaJOR8ltMecR6rLNbic4TJbQ/1ttYVVPZpMMKOHjsx5KT8v+L1QfEd5zninWgrBNrEwYAMnZ2MX6ow/Np8+grKQQRd4sWncNJ/d8hqDBTAOpoYP+vMnfjwzqtYUqsG//AdTWumG22eBrPYI/fLQL3gwn+ugOv+7xwUnQLDSUzZ3dmN3VinBCH6qA3Mt2KEYTNoAC3YQBkEaiKnWVha8OHMGKpXNRU14KBy387YtqcazhMKw0glQGzHcpN6Dc44rZOZhWXa0yPn+zYibrvUNh4JyAPC2nkUyVBXSR1fMq8eLWD9SjCPsS9RIVkLnEREtaAAhShFGbhU/2HuNUII66mgrOA9pw/dqVyMvLG+rW6AKVi6QahHx+9FAyTE4P5s6yMyq0U+TjiNATCGniDUXMJUj6dN9hVFeWI0F788W+o0BxAQLS7wRLWgCIkOgijwOvvnsATz3YhUVz67Ftx0eIclocpEtTWV8SpiJBqwU+ivCevQfxP+9/gI9370UgwHA334mr5s/gRKgGxXkeJd5hujib1YzW9k68tv0zbLxxDd793Qf4+dufoGiqh3HAxFygYJcWAGQYzNqRKw48+osXUV6SixNNrSoUFqJF8G3UdYn19+z9Gv/x69fx3H9ukS8Gyi5eiZibKQWPbtqA5XPqkJ+TifbOCJ5/bbuqt3PPUWzZfRbeEjc9z8S5L40a0rU0JqGpg8aw9ZwfOOGjb9yHI5+8Rz2vQJAcbzjZjFfe/C1++sSzipiqqSXMD0TQ+EdTZo/ThnP+oKpTw0nQ4aY2dZ0p6cSaufB46fupEroDVK8mdEqLBMgIJCSV0LTU44S7yIMD/9eEf3/hJdxw3TXY8fFneHjzL9RASwrzlKs71tii7m+6chnKCwswJT8PpzvP4fEXt/A+B/2BgCLeYWHIbDGiO2pGjjODXoIxhZIp9fmET2mTgMEjiXGArlgYLbt3DjzO9WSpCZGPFlw4uOGKpbhv480ozvXCycDGyNjh6Vdex89+9WvkujPQ6fPBTFdIk0mjGIG7cgYseUU0glS4QXOFgQ4u8SJtEjC4f4nqAkYLCiuqYQ11IcB5/5nOLuX+8rMY1RGA+mlVqC4tUcmPXn8Ab+38QBGfl5mBjh5xc9QiegxSDJPVDktWjqqbTuKlj0mRAGmYpp+T/D50fbWL7t2EGAOYVLEzGgzQ1d127UpUFhfi/c+/xM6v9sHjdFD/JchJFkmnM3zOqp4FUw6nz2nmvvQyeQCwcY2i6mNO33L2OMKaTbm7JGmc3RkRGuTG8jPdaOcsMlUMJF5yB3ZvIVyVdVQFPYhKvU/Xr8Swk1ai9Aw5JVPRE6Iw0NfnZGeqvkSFwyQ+U9Jh1Hc7gyIhPpUHsPJ5aY4bxUyHZ06pREykaZLKpLVsJJVdFPNpmS6889JzmFKcj86uHlTS/ZmpEkJsD0E5Q6MYpJEzcr5goWpM4VwixOdNZ7rQWrEIPSY7Msj/iYc8IyM4KQBIiOKSlukb32cGU/KDW1/+JWbNqEUD3V+YwBTme1FWWoRyHkK0zCJDjAuaWk6jZk49Xn3qETxdY8V0WxyNIQ3ZbG8yQEi7F1DEU8SPR3nyRfDbZdmw0JLX1VbhvS3P483/3s4o8BXsPXh4GEuWLLgcN69bhfXrr0MZZ4bBPa/ghhIrHmv04JetQLkd6GEH6bQGaTOCMihhupOnE5zm3+gx4pHSo6gruxbRO+9l8BPlvgeLmgidYcDT3HIKHWfPcX4fg8vhQH5eDhMoXmTTTdLfcfpLsX/1VRgP/DPaC5fhnu1WfE4RkAllcOKTwAHwJyQBMmnlOoU6xMn1kTsn5CJiwMP1flRag+h1MV9Aa64xBxBlClz8eE52FvK9HnWdGolklWMEQ4Iesf5GTqdjVUXoawTybDF8tzaEm3faUJiXgJMA+HiEeUwUi0uSAEeS6DMkuDvMG0nskPNTbQmUcFa0OjeGe2cxmDEQolgXNM8C2FbeCc1bwFEzjicIai9Qinr55TODpLj4y5QQolxcDW7lapCJQIkRJKWvHHbhvsN0DWIMrAmU8VKY0Mtx8P8llYsGQJBOEX6Mbg0kvMKRwIbcOGblRFHujsLriMNp5hTWlJqq8CuDBYngcRjsNbD/1T9By84jYGxgJNcmS+nkaeTQHoS2P0D8skkhv5ccAt8YmSds6jVjd7sV206ZsKWTT9lFIcchY+u+BBQuCgAh3sO+jgmnQwbcUxTD2tIIpueEkUPxtBhl/YZc4Ek/OJqBwodGOxKBVkrC5bDd8ENoGSRMEqVDzBmTolxVDn36G8QOPQWDY54OUkKvJ+1LsUiylM37IxqaCcaOUxb84wkCR7UrJxARVvTzEMAupowJgHQsLqjBb8At3jg21QVJeIh5wDiiCQMzOLJYqXclA5MymHz9iYyImdwwF03NebDd9BCMEtpKeKwq88RMceCtxxFvfROGrGUESKbEyYb1RtRZsmDylFsIOFki8Lxp6TPj3RM23H+MOmFOYBp/OikNw8cxqKHk5ahASUeZSeKfqI3gqaW9mJsfUFPfQJS7QCTFzSJTYTnkTn+iHg868SlHmojz2/x5MBdU0Chm0NBxhujwMCWWA0tRLWyL70qSLK1I78OLgCx9ydsgXW2IqfPijAg20eZ8dKUff+lK4CiZ5eW4pZWxyqheIIuNHA9oeLo2jO9c1qdS1EJ4iuCxGh/yXqMu97fCfuXtsOZVUVfIIllEGFQM05eg303uR5lQYYJ0LNMm45ASIQgCyAxvEM8si2DuQSd+csTMZbQE/OxGNPdCYAwdgbTGIpW5fImzHMRqdxwbpvkV8cLxVKeq4sWe6A0SoTYYSzfCWl6nf5XSF3XH4dPQGTM9sC24m9vq9lDGuWHyIktKKoJkjqjmvfV9+NXlXInyGWAjhdSIC5YRAYhSXL02C3oPdmIV9d1tM1LcddG7YEujvaD+J/qPwFy7ihscnEodlCUb+EYg13lkm3MNPUYJmS+u5kJ8G/hwyIUwR2xShMf6aT7817wgGvuYnKHBGJFQfj3sueTavZyN7d/xGb577zrc/uBmbmuVmdqwqkM6H/1GRkZOlF+WrDaCficlwszNkaZpdxCw3RzdaLwbuceUYIUoDdeW+/Hi3AgafEZkc01yhF6HA5DBJatjp87iltuux6P3/wPy62YhbvUySKEmXRIIJD4ehME1jUmNwuSoL8BZMemkwOidigSX0VQgNTKdoz5VrfMUipmwrqIHz07rwJHmPnjNTLFJH4PKELbKhzItxdEmPPzA/dy55SLxDljqbkTC/xU5opLfgz6/iEuCloj2Qsusg5F7f1W5AP0DrXEMepWxKg58MexCT8Yzn+j7Enc/9gJ+/qO7cOSDbUq6B0MwBIAs6v2JnV/gX5+8H7U1NWrnhmR1rDOWkSPShwSe4y3sguGwwVUMg+wEV2V0wjRnpthEltHr6W2NdCaJJgcS3Z/Atv43sEybjTtv2YAr16zH0V6f2sqT+moAAOlKYnSGEFi9coX+PqlQlik1MBaspT/pHL8aqIZp0DigMe1IUjyNHs4ZBIBk//pgxnFm+i3RtxOmWT+Ba/EalYz1eDz4waa7gT07adRleV0vAwBYmIJuYBbmxr++DZUVFeptKkWluTJhnModX8EDHNQ4DZPIm4ET+XCfmuUl+x35J0mw0VPIT3KSnmDkqmM9FSyt19yhluVSi+gL5s9HxqylOMeMk2SspAwA4GBeDgcOcXV3AZzMzspsTQGQ5IrmzqUu8wuZ4Y2rcJXAnMs4/wjifj3dreLXkdpIDsqUW8iI8TokwmfH3x+5D99HMNQ/BsuUavZCOiS7zFKQn4/v3bAKZ75uYR6SaTk+GwBAFiGALkyfPl3qKgDURerEXRt6GWxCUi9H+RVlNmUifvb3CLc0jN0GAddoeM21K2l4j3GE58V1lF7OvyKITEDBWL8C3Iwq9Ksi1l+24M2beznTSocIgO4WFQByUju8XGUoLS5SH6TEP6WHCdmnq2qPEwBpjaJjIGOCH7/OwVGMRnWnevu26YuS7BlHfxI+h1qQKP0OTKXVQ01oUpKrKisUfRLYDUiAkcg0cXVm3sKZ8Hqpe4NL8kODjWohhum80AyuNfp1nOA5lyOyfzNCh79QdWWRQ9QslRhJ/abAMZdUwlz99wyI9rPLi7Q74qYDJ5GYsQYW5XIJXlKtUgzNy8tF+cKr1Y4VsQMqtDfLjgwawIUza+B2y4ZE+U43EikZMhWUy66UMbinPh35FOcWWOcU+Lc9R2/CPQPsU/pI9ZP6VUAQGAP/TsC28CYCwD+zUWowliRwvLEAEs6ZMFZdzrwBhzHok1T7nuxsXDl7BnrPdqu1R+ZumNMTAJpPoq66Sm1glEGkPtAFhWEsXaEhg7M4dqI/G9T6yCQPfZpgPtBaCsPpF9D43lXwT1+OfZ/vht3p5N4BK1PmM5Cbm8sFVEZrnCmq+KNuLvrLbke880NlSHUrPLTZgTuRkv6Pkah+ABb+0ZXS1gEm6rWELgsTszNrpwHPvQFLSZ5eTzeAPaiqIoEsA+IoN9IIP5QY3TyD83Xfp0mOyMvxFLbDkFhzLmK669t4f+s7yCso4C5QO44cPYafPfEM3nj7XZw7xxwiI0HZPivG0L6c84Le48nZ4Sigi/7TThtrlsLCnWlD2J8cZoounc5TanlOAl/dAJqmoGzqFFX1PPeTXyZlyTabllmcwbhdod6OhKeSRfI4irHp5r/A1Vcsw8L5c3HDurV4ZvOj6OvrxRtvvY3unh7+fZXuumwzFjEG2cgY5BT7JZEjFhH/fkabc2Ci61PWf8R6+sOK8jJe2NUuE03+PqeRS1brbroCxUX6ZGUYAElRMrNxLX/NpUWEqm9ykPoc93HbW1ujenLixEnuIrMolbvrjtuZ/Y3jQ26Zk6KkwO6kFNxJKThK9jKgGqlwk3Ui1AStcAlzCjnJP7AiKH9UUnSVFBfjijVrcJzb8TQVAO1vwIol8+FycfMyxX140RszOt0wFs5jZ/wzuAtyY/jXQ57IjlG6xM4Th9SO0rb2drSeauPuMsl1A7duvAX/y70CZzs7lRTIaGyXLYZWtJ79to8sfZJwYb7RmFuLuImeQHdXqr3BJx2ABLK4+LL6ioXAlwRNQmCgHfX19aruyADozciCBf+OjVyUWd1IQOn1Rj0zBpBm7Blurg/SJZWVobAgD41NzeozF43izOm13GnaoTcjBtGRAdsS2oK+Q+yb6A0rpIEuWnO5VYI2BeawanwQT2Zw586Zw7uT+H80X6vv56/SkgAAAABJRU5ErkJggg==
      spokenLanguages:
        $ref: '#/definitions/SpokenLanguages'
  SpokenLanguages:
    title: Languages
    description: A hashmap of spoken languages
    additionalProperties:
      description: An additional spoken language
      type: string
    properties:
      defaultLanguage:
        description: Default spoken language
        type: string
        default: english
    example:
      defaultLanguage: french
      it: italian
      fr: french
  Persons:
    title: Humans
    description: A list of users or friends
    required:
      - items
    properties:
      items:
        description: Array containg the list
        type: array
        minItems: 10
        maxItems: 100
        uniqueItems: true
        items:
          $ref: '#/definitions/Person'
        example:
          - firstname: Robert
            lastname": Doe
            username": robdo
            dateOfBirth: 1970-01-28
            lastTimeOnline: 2016-04-10T14:36:58.014Z
          - firstname: Jane
            lastname: Doe
            username: jdoe123
            dateOfBirth: 1980-05-12
            lastTimeOnline: 2016-05-12T19:23:59.014Z

  CollectingItem:
    discriminator: itemType
    required:
      - itemType
    properties:
      itemType:
        description: |
          An item can be of different type:
            
          type | definition
          -----|-----------
          Vinyl| #/definitions/Vinyl
          VHS  | #/definitions/VHS
          AudioCassette | #/definitions/AudioCassette
        type: string
        enum:
          - AudioCassette
          - Vinyl
          - VHS
      imageId:
        type: string
      maxPrice:
        type: number
        format: double
        minimum: 0
        maximum: 10000
        exclusiveMinimum: true
        exclusiveMaximum: false
  Vinyl:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  VHS:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - movieTitle
        properties:
          movieTitle:
            type: string
          director:
            type: string
  AudioCassette:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string

  PagedPersons:
    allOf:
      - $ref: '#/definitions/Persons'
      - $ref: 'commons.yaml#/definitions/Paging'
  PagedCollectingItems:
    allOf:
      - properties:
          items:
            type: array
            minItems: 10
            maxItems: 100
            uniqueItems: true
            items:
              $ref: '#/definitions/CollectingItem'
      - $ref: 'commons.yaml#/definitions/Paging'

responses:
  PersonDoesNotExistResponse:
    description: Person does not exist.
    headers:
      $ref: 'commons.yaml#/responses/DefaultHeaders/headers'

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  includeNonVerifiedUsers:
    name: includeNonVerifiedUsers
    in: query
    description: Result will not include non verified user by default if this parameter is not provided
    type: boolean
    default: false
    allowEmptyValue: true
  sortPersons:
    name: sort
    in: query
    description: Result will be sorted by lastTimeOnline descending and username ascending by default if this parameter is not provided
    type: array
    uniqueItems: true
    minItems: 1
    maxItems: 3
    collectionFormat: pipes
    items:
      type: string
      pattern: '[-+](username|lastTimeOnline|firstname|lastname)'
    default:
      - -lastTimeOnline
      - +username
  filterItemTypes:
    name: itemType
    in: query
    description: Filter collected items on their type
    type: array
    collectionFormat: multi
    uniqueItems: true
    items:
      type: string
      enum:
        - AudioCassette
        - Vinyl
        - VHS
swagger: "2.0"

info:
  version: 1.0.0
  title: Common elements
  description: Shared elements in all API


securityDefinitions:
  OauthSecurity:
    description: New Oauth security system. Do not use MediaSecurity or LegacySecurity.
    type: oauth2
    flow: accessCode
    authorizationUrl: 'https://oauth.simple.api/authorization'
    tokenUrl: 'https://oauth.simple.api/token'
    scopes:
      admin: Admin scope
      user: User scope
  MediaSecurity:
    description: Specific media security for backward compatibility. Use OauthSecurity instead.
    type: apiKey
    in: query
    name: media-api-key
  LegacySecurity:
    description: Legacy security system for backward compatibility. Use OauthSecurity instead.
    type: basic

security:
  - OauthSecurity:
    - user
  - LegacySecurity: []

produces:
  - application/json
  - application/x-yaml
consumes:
  $ref: '#/produces'

paths: {}

parameters:
  userAgent:
    name: User-Agent
    description: All API consumers MUST provide a user agent
    type: string
    in: header
    required: true
  pageSize:
    name: pageSize
    in: query
    description: Number of items returned
    type: integer
    format: int32
    minimum: 0
    exclusiveMinimum: true
    maximum: 100
    exclusiveMaximum: false
    multipleOf: 10
    default: 20
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    default: 1

responses:
  DefaultHeaders:
    description: A dummy response to define default header
    headers:
      X-Rate-Limit-Remaining:
        description: How many calls consumer can do
        type: integer
      X-Rate-Limit-Reset:
        description: When rate limit will be reset
        type: string
        format: date-time
  Standard500ErrorResponse:
    description: An unexpected error occured.
    headers:
      $ref: '#/responses/DefaultHeaders/headers'
    schema:
      $ref: '#/definitions/Error'
  TotallyUnexpectedResponse:
    description: A totally unexpected response
    headers:
      $ref: '#/responses/DefaultHeaders/headers'

definitions:
  ErrorMessage:
    title: MultiDeviceErrorMessage
    description: An error message with a long and a short description
    required:
      - longMessage
      - shortMessage
    properties:
      longMessage:
        description: A long error description
        type: string
      shortMessage:
        description: A short error description
        type: string
  MultilingualErrorMessage:
    title: MultiLingualMultiDeviceErrorMessage
    description: An multilingual error message (hashmap) with a long and a short description
    additionalProperties:
      $ref: '#/definitions/ErrorMessage'
    properties:
      defaultLanguage:
        $ref: '#/definitions/ErrorMessage'
    example:
      defaultLanguage:
        longMessage: We're deeply sorry but an error occured
        shortMessage: Error
      fr:
        longMessage: Nous sommes désolé mais une erreur est survenu
        shortMessage: Erreur
        
  Error:
    title: MultiLingualMultiDeviceError
    description: Give full information about the problem
    required:
      - code
      - message
    properties:
      code:
        description: A human readable code (death to numeric error codes!)
        type: string
        enum:
          - DBERR
          - NTERR
          - UNERR
        example: UNERR
      message:
        $ref: '#/definitions/MultilingualErrorMessage'
  Paging:
    required:
      - totalItems
      - totalPages
      - pageSize
      - currentPage
    properties:
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer
swagger: '2.0'

info:
  version: 1.1.0
  title: Simple API
  description: |
    A simple API to learn how to write OpenAPI Specification.
    This file uses almost every single aspect of the [Open API Specification](https://openapis.org/).  
    This API will use JSON.  
    JSON looks like this:  
    
    ```JSON
    {
      "key": "value",
      "anotherKey": "anotherValue"
    }
    ```
  termsOfService: http://simple.api/terms-of-service
  contact:
    name: John Doe
    url: http://simple.api/contact
    email: contact@simple.api
  license:
    name: Apache-2.0
    url: http://www.apache.org/licenses/LICENSE-2.0

externalDocs: 
  description: |
    **Complete** documentation describing how to use this API
  url: http://doc.simple.api/

tags:
  - name: Persons
    description: Everything you need to handle `users` and `friends`
    externalDocs:
      description: People category documentation
      url: http://doc.simple.api/people
  - name: Items
    description: Everything you need to handle items collected by users
    externalDocs:
      description: Items category documentation
      url: http://doc.simple.api/items
  - name: Media
    description: Everything you need to handle images
    externalDocs:
      description: Media category documentation
      url: http://doc.simple.api/media
  - name: JSLess
    description: Specific operations for JS less consumers
    externalDocs:
      description: JS Less Consumers documentation
      url: http://doc.simple.api/jsless
      
schemes:
  - https
host: simple.api
basePath: /openapi101

consumes:
  $ref: 'commons.yaml#/consumes'
produces:
  $ref: 'commons.yaml#/produces'

securityDefinitions:
  $ref: 'commons.yaml#/securityDefinitions'

security:
  $ref: 'commons.yaml#/security'

paths:
  /persons:
    $ref: 'persons.yaml#/paths/~1persons'
  /js-less-consumer-persons:
    $ref: 'legacy.yaml#/paths/~1js-less-consumer-persons'
  '/persons/{username}':
    $ref: 'persons.yaml#/paths/~1persons~1{username}'
  '/persons/{username}/friends':
    $ref: 'persons.yaml#/paths/~1persons~1{username}~1friends'
  '/persons/{username}/collecting-items':
    $ref: 'persons.yaml#/paths/~1persons~1{username}~1collecting-items'
  /images:
    $ref: 'images.yaml#/paths/~1images'
  /images/{imageId}:
    $ref: 'images.yaml#/paths/~1images~1{imageId}'
persons:
  parameters:
    - $ref: 'commons.yaml#/parameters/userAgent'
  get:
    summary: Gets some persons
    description: Returns a list containing all persons. The list supports paging.
    operationId: searchUsers
    tags:
      - Persons
    parameters:
      - $ref: 'commons.yaml#/parameters/pageSize'
      - $ref: 'commons.yaml#/parameters/pageNumber'
      - $ref: '#/parameters/includeNonVerifiedUsers'
      - $ref: '#/parameters/sortPersons'
    responses:
      '200':
        description: A list of Person
        schema:
          $ref: '#/definitions/Persons'
        headers:
          $ref: commons.yaml#/defaultHeaders
      '500':
        $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
      default:
        $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
  post:
    summary: Creates a person
    description: Adds a new person to the persons list.
    operationId: createUser
    tags:
      - Persons
    security:
      - OauthSecurity:
        - admin
      - LegacySecurity: []
    parameters:
      - name: person
        in: body
        required: true
        description: The person to create.
        schema:
          $ref: '#/definitions/Person'
    responses:
      '204':
        description: Person succesfully created.
        headers:
          $ref: commons.yaml#/defaultHeaders
      '400':
        description: Person couldn't have been created.
        headers:
          $ref: commons.yaml#/defaultHeaders
      '500':
        $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
      default:
        $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'

persons-username:
  parameters:
    - $ref: '#/parameters/username'
    - $ref: 'commons.yaml#/parameters/userAgent'
  get:
    summary: Gets a person
    description: Returns a single person for its username.
    operationId: readPerson
    tags:
      - Persons
    responses:
      '200':
        description: A Person
        schema:
          $ref: '#/definitions/Person'
        headers:
          $ref: commons.yaml#/defaultHeaders
      '404':
        $ref: '#/responses/PersonDoesNotExistResponse'
      '500':
        $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
      default:
        $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
  delete:
    summary: Deletes a person
    description: Delete a single person identified via its username
    operationId: deletePerson
    tags:
      - Persons
    responses:
      '204':
        description: Person successfully deleted.
        headers:
          $ref: commons.yaml#/defaultHeaders
      '404':
        $ref: '#/responses/PersonDoesNotExistResponse'
      '500':
        $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
      default:
        $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'

persons-username-friends:
  parameters:
    - $ref: '#/parameters/username'
    - $ref: 'commons.yaml#/parameters/userAgent'
  get:
    summary: Gets a person's friends
    description: Returns a list containing all persons. The list supports paging.
    operationId: readPersonsFriends
    tags:
      - Persons
    parameters:
      - $ref: 'commons.yaml#/parameters/pageSize'
      - $ref: 'commons.yaml#/parameters/pageNumber'
      - $ref: '#/parameters/includeNonVerifiedUsers'
      - $ref: '#/parameters/sortPersons'
    responses:
      '200':
        description: A person's friends list
        schema:
          $ref: '#/definitions/PagedPersons'
        headers:
          $ref: commons.yaml#/defaultHeaders
      '404':
        $ref: '#/responses/PersonDoesNotExistResponse'
      '500':
        $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
      default:
        $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'

persons-username-collecting-items:
  parameters:
    - $ref: '#/parameters/username'
    - $ref: 'commons.yaml#/parameters/userAgent'
  get:
    summary: Gets a person's collecting items list
    description: |
      Returns a list containing all items this person is looking for.  
      The list supports paging.
    operationId: readPersonsCollectingItems
    tags:
      - Items
    parameters:
      - $ref: 'commons.yaml#/parameters/pageSize'
      - $ref: 'commons.yaml#/parameters/pageNumber'
      - $ref: '#/parameters/filterItemTypes'
    responses:
      '200':
        description: A collected items list
        schema:
          $ref: '#/definitions/PagedCollectingItems'
        headers:
          $ref: commons.yaml#/defaultHeaders
        examples:
          application/json:
            {
              "totalItems": 10,
              "totalPage": 4,
              "pageSize": 3,
              "currentPage": 2,
              "items": 
              [
                { 
                  "itemType": "Vinyl",
                  "maxPrice": 20,
                  "imageId": "98096838-04eb-4bac-b32e-cd5b7196de71",
                  "albumName": "Captain Future Original Soundtrack",
                  "artist": "Yuji Ohno"
                },
                { 
                  "itemType": "VHS",
                  "maxPrice": 10,
                  "imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
                  "movieTitle": "Star Crash",
                  "director": "Luigi Cozzi"
                },
                { 
                  "itemType": "AudioCassette",
                  "maxPrice": 10,
                  "imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
                  "albumName": "Star Wars",
                  "artist": "John Williams"
                }
              ]
            }
      '404':
        $ref: '#/responses/PersonDoesNotExistResponse'
      '500':
        $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
      default:
        $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'

definitions:
  Person:
    title: Human
    description: A person which can be the user itself or one of his friend
    required:
      - username
    properties:
      firstName:
        description: first name
        type: string
        example: John
      lastName:
        description: last name
        type: string
        example: Doe
      username:
        description: Username used to connect to the service
        type: string
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
        example: john1doe6
      dateOfBirth:
        description: Date of birth
        type: string
        format: date
        example: 1978-06-21
      lastTimeOnline:
        description: The last time this person was connected to the service as a 
        type: string
        format: date-time
        readOnly: true
        example: 2016-06-10T12:36:58.014Z
      avatarBase64PNG:
        description: An avatar PNG image as a base64 encoded string ready to use as an src in img html tag
        type: string
        format: byte
        default: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAC4jAAAuIwF4pT92AAABy2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBJbWFnZVJlYWR5PC94bXA6Q3JlYXRvclRvb2w+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgqyI37xAAAU3UlEQVR4AeVbeXRc1Xn/zZt90UgajXbJ1mYtNraM95XF2AbbFINLg1sgBCg9JicnpDk9TciBAzQlFDds56T0QE45PTkQTNkhTmnslthhMWAweMObbGuzJdmythnNPtPfd9+MLEWyZFkj8keu/d685b577/f71vvdK0POwmsS+DMu2p8x7Yr0Px0AiUGCJ9fqftCzb4gzpm+oH70bIdJgADQNPCeJ5iPep0hPDAFD1ZrUIX5DAAh5JNpIgYtGEe/3IRrwIxIOKcJNRiM0oxlGqw0aD5gtrG5EIh6fVOKl8UkHQJFOYhCNIHLuHAJtzQj3dV2QMM2gwZpbBJs3H6aMLMRFYpR6XPCTCb2YVAAU8SQo3tsNX+NRhH3d+mD5TKmC8F8qCZFSSGg8EUego0UdjrwSOEorkBCJmCQQJhUA8h3h9hb0nPha0SdiTblOHvojdRYQBhcBiHahn0BE/b1w186eNBAmzQsYyNUQxV0RL4QLl+Oxi+MkQTLEorQZJoQJgL/5OLRJkoD0A8CBilWPnutAb+MRgERcNOFJKTDRWLrsFrgsGj83K3WI+XqUVKRbFdIPAIlHKIi+hv06OcL1QWUkx5Z6ZjUbUZKbCavRgL5AWB1ZDhMyzEB/Z4cuBSl7MajNiVym1wYkuR/q7iTT4yguzIfZRHcmIk29joTD8Pv6EAxHEY2LwaO08J/TakJWhgNNHd1oOUNOs2y8bol69/J7H6r77P4uxCJhGNJsENMLgHAnFkO8+wzcTitaT7erwY90spkMcLFOMBRFL7ktx5y6ctz7rdVYXF8Nb1YGQTPg+7euxYP/tgXbd+1DUTyKEKxs7o+t5kg9XNyztAOgkUv+c2dU70/+9MeYXlOl7F9Pnw+nW09h/6c78NnBRnzZGkCwV+f2t1YvxvoV87F4VjVyszMoMQnGSzGSmcDsmqn4l/tuxbxdP4aBsYRmMyjJoVW9OArHqJVGACjOFHOXlkAHO9368vNYs3J5MprTBxunPfDftAo9pxrQ091FVYjDbrcpol38jVJ6gqGIAky4Lwri6w+iakoBHvq7DXjk+S9RvtyD3vAYVI3jdRoBMMBKA3i8rQvrr7sayxbNQSgUJifpzpKGS36t2QXId3uQ66dO97YhTomJUaIDrCvVNO08Z+VKpMDEdmdWT+Xd7+GgTeklSGkSAAboaSoitjYTm2vzo/6yOljMZsQZy5tMJhgZ68uhkZAEpSCumZFw5yORW40oo/E4OW9kPU0zKSkSSTp/GJXI53rcHKmGbhLvoLegDU1LSYsEyFgs5Jw/QpcXPak4LsQKB4PBQJJZtPeKuRRtegUBxuZwIZGZj3hXI8LBfgJGaZF/SYkRCkUNHHa6RosZeXWlqMiw4w/HOlCcn4H+aByDBEaqj7ukBQAzB9xGK76iNBO3fn8Tunp6SXgQW97ZhoAlE3arFf3hCAGKwCzAUBr62lpw29rlqMjPxNbfHcDBcB48WW4EI1H0BENK7E0U944znVhfdRZWStc965bih5u+jceffQmbt3yIqRUe+AT0CZS0AJBJP96+6yv86KEnUFroxQ8e2Izm5mZEcquwau31Ss/b+0M43ueHm+JrtVhx6GgDjnKOUJabgUPBbFz7t99jAKSRoAj2dfbAZTYRBANyghHs3fYSZrp8ONnarkBac9UCbH7yNdirc//0AIgRCYkVQxatdZHMYXDyVDt6evtQkFeqwuAE43pQvI3Uf2OcekB3lkGrbws5qP9ReDzZYLikgJJ8gRaju6M3McTEsBpgycyEr7cDO/Y1INAfgN0msYCZxlMUZGJRQVokQLdHRkQ4+JxsNwdvRFtbO7TKMtjsDsTIWVuC8/xIHFZy1kwDaaJOR8ltMecR6rLNbic4TJbQ/1ttYVVPZpMMKOHjsx5KT8v+L1QfEd5zninWgrBNrEwYAMnZ2MX6ow/Np8+grKQQRd4sWncNJ/d8hqDBTAOpoYP+vMnfjwzqtYUqsG//AdTWumG22eBrPYI/fLQL3gwn+ugOv+7xwUnQLDSUzZ3dmN3VinBCH6qA3Mt2KEYTNoAC3YQBkEaiKnWVha8OHMGKpXNRU14KBy387YtqcazhMKw0glQGzHcpN6Dc44rZOZhWXa0yPn+zYibrvUNh4JyAPC2nkUyVBXSR1fMq8eLWD9SjCPsS9RIVkLnEREtaAAhShFGbhU/2HuNUII66mgrOA9pw/dqVyMvLG+rW6AKVi6QahHx+9FAyTE4P5s6yMyq0U+TjiNATCGniDUXMJUj6dN9hVFeWI0F788W+o0BxAQLS7wRLWgCIkOgijwOvvnsATz3YhUVz67Ftx0eIclocpEtTWV8SpiJBqwU+ivCevQfxP+9/gI9370UgwHA334mr5s/gRKgGxXkeJd5hujib1YzW9k68tv0zbLxxDd793Qf4+dufoGiqh3HAxFygYJcWAGQYzNqRKw48+osXUV6SixNNrSoUFqJF8G3UdYn19+z9Gv/x69fx3H9ukS8Gyi5eiZibKQWPbtqA5XPqkJ+TifbOCJ5/bbuqt3PPUWzZfRbeEjc9z8S5L40a0rU0JqGpg8aw9ZwfOOGjb9yHI5+8Rz2vQJAcbzjZjFfe/C1++sSzipiqqSXMD0TQ+EdTZo/ThnP+oKpTw0nQ4aY2dZ0p6cSaufB46fupEroDVK8mdEqLBMgIJCSV0LTU44S7yIMD/9eEf3/hJdxw3TXY8fFneHjzL9RASwrzlKs71tii7m+6chnKCwswJT8PpzvP4fEXt/A+B/2BgCLeYWHIbDGiO2pGjjODXoIxhZIp9fmET2mTgMEjiXGArlgYLbt3DjzO9WSpCZGPFlw4uOGKpbhv480ozvXCycDGyNjh6Vdex89+9WvkujPQ6fPBTFdIk0mjGIG7cgYseUU0glS4QXOFgQ4u8SJtEjC4f4nqAkYLCiuqYQ11IcB5/5nOLuX+8rMY1RGA+mlVqC4tUcmPXn8Ab+38QBGfl5mBjh5xc9QiegxSDJPVDktWjqqbTuKlj0mRAGmYpp+T/D50fbWL7t2EGAOYVLEzGgzQ1d127UpUFhfi/c+/xM6v9sHjdFD/JchJFkmnM3zOqp4FUw6nz2nmvvQyeQCwcY2i6mNO33L2OMKaTbm7JGmc3RkRGuTG8jPdaOcsMlUMJF5yB3ZvIVyVdVQFPYhKvU/Xr8Swk1ai9Aw5JVPRE6Iw0NfnZGeqvkSFwyQ+U9Jh1Hc7gyIhPpUHsPJ5aY4bxUyHZ06pREykaZLKpLVsJJVdFPNpmS6889JzmFKcj86uHlTS/ZmpEkJsD0E5Q6MYpJEzcr5goWpM4VwixOdNZ7rQWrEIPSY7Msj/iYc8IyM4KQBIiOKSlukb32cGU/KDW1/+JWbNqEUD3V+YwBTme1FWWoRyHkK0zCJDjAuaWk6jZk49Xn3qETxdY8V0WxyNIQ3ZbG8yQEi7F1DEU8SPR3nyRfDbZdmw0JLX1VbhvS3P483/3s4o8BXsPXh4GEuWLLgcN69bhfXrr0MZZ4bBPa/ghhIrHmv04JetQLkd6GEH6bQGaTOCMihhupOnE5zm3+gx4pHSo6gruxbRO+9l8BPlvgeLmgidYcDT3HIKHWfPcX4fg8vhQH5eDhMoXmTTTdLfcfpLsX/1VRgP/DPaC5fhnu1WfE4RkAllcOKTwAHwJyQBMmnlOoU6xMn1kTsn5CJiwMP1flRag+h1MV9Aa64xBxBlClz8eE52FvK9HnWdGolklWMEQ4Iesf5GTqdjVUXoawTybDF8tzaEm3faUJiXgJMA+HiEeUwUi0uSAEeS6DMkuDvMG0nskPNTbQmUcFa0OjeGe2cxmDEQolgXNM8C2FbeCc1bwFEzjicIai9Qinr55TODpLj4y5QQolxcDW7lapCJQIkRJKWvHHbhvsN0DWIMrAmU8VKY0Mtx8P8llYsGQJBOEX6Mbg0kvMKRwIbcOGblRFHujsLriMNp5hTWlJqq8CuDBYngcRjsNbD/1T9By84jYGxgJNcmS+nkaeTQHoS2P0D8skkhv5ccAt8YmSds6jVjd7sV206ZsKWTT9lFIcchY+u+BBQuCgAh3sO+jgmnQwbcUxTD2tIIpueEkUPxtBhl/YZc4Ek/OJqBwodGOxKBVkrC5bDd8ENoGSRMEqVDzBmTolxVDn36G8QOPQWDY54OUkKvJ+1LsUiylM37IxqaCcaOUxb84wkCR7UrJxARVvTzEMAupowJgHQsLqjBb8At3jg21QVJeIh5wDiiCQMzOLJYqXclA5MymHz9iYyImdwwF03NebDd9BCMEtpKeKwq88RMceCtxxFvfROGrGUESKbEyYb1RtRZsmDylFsIOFki8Lxp6TPj3RM23H+MOmFOYBp/OikNw8cxqKHk5ahASUeZSeKfqI3gqaW9mJsfUFPfQJS7QCTFzSJTYTnkTn+iHg868SlHmojz2/x5MBdU0Chm0NBxhujwMCWWA0tRLWyL70qSLK1I78OLgCx9ydsgXW2IqfPijAg20eZ8dKUff+lK4CiZ5eW4pZWxyqheIIuNHA9oeLo2jO9c1qdS1EJ4iuCxGh/yXqMu97fCfuXtsOZVUVfIIllEGFQM05eg303uR5lQYYJ0LNMm45ASIQgCyAxvEM8si2DuQSd+csTMZbQE/OxGNPdCYAwdgbTGIpW5fImzHMRqdxwbpvkV8cLxVKeq4sWe6A0SoTYYSzfCWl6nf5XSF3XH4dPQGTM9sC24m9vq9lDGuWHyIktKKoJkjqjmvfV9+NXlXInyGWAjhdSIC5YRAYhSXL02C3oPdmIV9d1tM1LcddG7YEujvaD+J/qPwFy7ihscnEodlCUb+EYg13lkm3MNPUYJmS+u5kJ8G/hwyIUwR2xShMf6aT7817wgGvuYnKHBGJFQfj3sueTavZyN7d/xGb577zrc/uBmbmuVmdqwqkM6H/1GRkZOlF+WrDaCficlwszNkaZpdxCw3RzdaLwbuceUYIUoDdeW+/Hi3AgafEZkc01yhF6HA5DBJatjp87iltuux6P3/wPy62YhbvUySKEmXRIIJD4ehME1jUmNwuSoL8BZMemkwOidigSX0VQgNTKdoz5VrfMUipmwrqIHz07rwJHmPnjNTLFJH4PKELbKhzItxdEmPPzA/dy55SLxDljqbkTC/xU5opLfgz6/iEuCloj2Qsusg5F7f1W5AP0DrXEMepWxKg58MexCT8Yzn+j7Enc/9gJ+/qO7cOSDbUq6B0MwBIAs6v2JnV/gX5+8H7U1NWrnhmR1rDOWkSPShwSe4y3sguGwwVUMg+wEV2V0wjRnpthEltHr6W2NdCaJJgcS3Z/Atv43sEybjTtv2YAr16zH0V6f2sqT+moAAOlKYnSGEFi9coX+PqlQlik1MBaspT/pHL8aqIZp0DigMe1IUjyNHs4ZBIBk//pgxnFm+i3RtxOmWT+Ba/EalYz1eDz4waa7gT07adRleV0vAwBYmIJuYBbmxr++DZUVFeptKkWluTJhnModX8EDHNQ4DZPIm4ET+XCfmuUl+x35J0mw0VPIT3KSnmDkqmM9FSyt19yhluVSi+gL5s9HxqylOMeMk2SspAwA4GBeDgcOcXV3AZzMzspsTQGQ5IrmzqUu8wuZ4Y2rcJXAnMs4/wjifj3dreLXkdpIDsqUW8iI8TokwmfH3x+5D99HMNQ/BsuUavZCOiS7zFKQn4/v3bAKZ75uYR6SaTk+GwBAFiGALkyfPl3qKgDURerEXRt6GWxCUi9H+RVlNmUifvb3CLc0jN0GAddoeM21K2l4j3GE58V1lF7OvyKITEDBWL8C3Iwq9Ksi1l+24M2beznTSocIgO4WFQByUju8XGUoLS5SH6TEP6WHCdmnq2qPEwBpjaJjIGOCH7/OwVGMRnWnevu26YuS7BlHfxI+h1qQKP0OTKXVQ01oUpKrKisUfRLYDUiAkcg0cXVm3sKZ8Hqpe4NL8kODjWohhum80AyuNfp1nOA5lyOyfzNCh79QdWWRQ9QslRhJ/abAMZdUwlz99wyI9rPLi7Q74qYDJ5GYsQYW5XIJXlKtUgzNy8tF+cKr1Y4VsQMqtDfLjgwawIUza+B2y4ZE+U43EikZMhWUy66UMbinPh35FOcWWOcU+Lc9R2/CPQPsU/pI9ZP6VUAQGAP/TsC28CYCwD+zUWowliRwvLEAEs6ZMFZdzrwBhzHok1T7nuxsXDl7BnrPdqu1R+ZumNMTAJpPoq66Sm1glEGkPtAFhWEsXaEhg7M4dqI/G9T6yCQPfZpgPtBaCsPpF9D43lXwT1+OfZ/vht3p5N4BK1PmM5Cbm8sFVEZrnCmq+KNuLvrLbke880NlSHUrPLTZgTuRkv6Pkah+ABb+0ZXS1gEm6rWELgsTszNrpwHPvQFLSZ5eTzeAPaiqIoEsA+IoN9IIP5QY3TyD83Xfp0mOyMvxFLbDkFhzLmK669t4f+s7yCso4C5QO44cPYafPfEM3nj7XZw7xxwiI0HZPivG0L6c84Le48nZ4Sigi/7TThtrlsLCnWlD2J8cZoounc5TanlOAl/dAJqmoGzqFFX1PPeTXyZlyTabllmcwbhdod6OhKeSRfI4irHp5r/A1Vcsw8L5c3HDurV4ZvOj6OvrxRtvvY3unh7+fZXuumwzFjEG2cgY5BT7JZEjFhH/fkabc2Ci61PWf8R6+sOK8jJe2NUuE03+PqeRS1brbroCxUX6ZGUYAElRMrNxLX/NpUWEqm9ykPoc93HbW1ujenLixEnuIrMolbvrjtuZ/Y3jQ26Zk6KkwO6kFNxJKThK9jKgGqlwk3Ui1AStcAlzCjnJP7AiKH9UUnSVFBfjijVrcJzb8TQVAO1vwIol8+FycfMyxX140RszOt0wFs5jZ/wzuAtyY/jXQ57IjlG6xM4Th9SO0rb2drSeauPuMsl1A7duvAX/y70CZzs7lRTIaGyXLYZWtJ79to8sfZJwYb7RmFuLuImeQHdXqr3BJx2ABLK4+LL6ioXAlwRNQmCgHfX19aruyADozciCBf+OjVyUWd1IQOn1Rj0zBpBm7Blurg/SJZWVobAgD41NzeozF43izOm13GnaoTcjBtGRAdsS2oK+Q+yb6A0rpIEuWnO5VYI2BeawanwQT2Zw586Zw7uT+H80X6vv56/SkgAAAABJRU5ErkJggg==
      spokenLanguages:
        $ref: '#/definitions/SpokenLanguages'
  SpokenLanguages:
    title: Languages
    description: A hashmap of spoken languages
    additionalProperties:
      description: An additional spoken language
      type: string
    properties:
      defaultLanguage:
        description: Default spoken language
        type: string
        default: english
    example:
      defaultLanguage: french
      it: italian
      fr: french
  Persons:
    title: Humans
    description: A list of users or friends
    required:
      - items
    properties:
      items:
        description: Array containg the list
        type: array
        minItems: 10
        maxItems: 100
        uniqueItems: true
        items:
          $ref: '#/definitions/Person'
        example:
          - firstname: Robert
            lastname": Doe
            username": robdo
            dateOfBirth: 1970-01-28
            lastTimeOnline: 2016-04-10T14:36:58.014Z
          - firstname: Jane
            lastname: Doe
            username: jdoe123
            dateOfBirth: 1980-05-12
            lastTimeOnline: 2016-05-12T19:23:59.014Z

  CollectingItem:
    discriminator: itemType
    required:
      - itemType
    properties:
      itemType:
        description: |
          An item can be of different type:
            
          type | definition
          -----|-----------
          Vinyl| #/definitions/Vinyl
          VHS  | #/definitions/VHS
          AudioCassette | #/definitions/AudioCassette
        type: string
        enum:
          - AudioCassette
          - Vinyl
          - VHS
      imageId:
        type: string
      maxPrice:
        type: number
        format: double
        minimum: 0
        maximum: 10000
        exclusiveMinimum: true
        exclusiveMaximum: false
  Vinyl:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  VHS:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - movieTitle
        properties:
          movieTitle:
            type: string
          director:
            type: string
  AudioCassette:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string

  PagedPersons:
    allOf:
      - $ref: '#/definitions/Persons'
      - $ref: 'commons.yaml#/definitions/Paging'
  PagedCollectingItems:
    allOf:
      - properties:
          items:
            type: array
            minItems: 10
            maxItems: 100
            uniqueItems: true
            items:
              $ref: '#/definitions/CollectingItem'
      - $ref: 'commons.yaml#/definitions/Paging'

responses:
  PersonDoesNotExistResponse:
    description: Person does not exist.
    headers:
      $ref: commons.yaml#/defaultHeaders

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  includeNonVerifiedUsers:
    name: includeNonVerifiedUsers
    in: query
    description: Result will not include non verified user by default if this parameter is not provided
    type: boolean
    default: false
    allowEmptyValue: true
  sortPersons:
    name: sort
    in: query
    description: Result will be sorted by lastTimeOnline descending and username ascending by default if this parameter is not provided
    type: array
    uniqueItems: true
    minItems: 1
    maxItems: 3
    collectionFormat: pipes
    items:
      type: string
      pattern: '[-+](username|lastTimeOnline|firstname|lastname)'
    default:
      - -lastTimeOnline
      - +username
  filterItemTypes:
    name: itemType
    in: query
    description: Filter collected items on their type
    type: array
    collectionFormat: multi
    uniqueItems: true
    items:
      type: string
      enum:
        - AudioCassette
        - Vinyl
        - VHS
js-less-consumer-persons:
  parameters:
    - $ref: 'commons.yaml#/parameters/userAgent'
  post:
    summary: Creates a person
    description: For JS-less partners
    operationId: createUserJS
    deprecated: true
    tags:
      - JSLess
      - Persons
    security:
      - OauthSecurity:
        - admin
      - LegacySecurity: []
    consumes:
      - application/x-www-form-urlencoded
    produces:
      - text/html
    parameters:
      - name: username
        in: formData
        required: true
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
        type: string
      - name: firstname
        in: formData
        type: string
      - name: lastname
        in: formData
        type: string
      - name: dateOfBirth
        in: formData
        type: string
        format: date
    responses:
      '204':
        description: Person succesfully created.
        headers:
          $ref: 'commons.yaml#/defaultHeaders'
      '400':
        description: Person couldn't have been created.
        headers:
          $ref: 'commons.yaml#/defaultHeaders'
      '500':
        description: An error occured.
        headers:
          $ref: 'commons.yaml#/defaultHeaders'
      default:
        $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
  images:
    parameters:
      - $ref: 'commons.yaml#/parameters/userAgent'
    post:
      summary: Uploads an image
      description: Upload an image, will return an image id. 
      operationId: storeImage
      externalDocs:
        description: How to upload media
        url: http://doc.simple.api/media/upload
      tags:
        - Media
      security:
        - MediaSecurity: []
      consumes:
        - multipart/form-data
      parameters:
        - name: image
          in: formData
          type: file
      responses:
        '200':
          description: Image's ID
          schema:
            properties:
              imageId:
                type: string
          headers:
            $ref: commons.yaml#/defaultHeaders
        '500':
          $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
        default:
          $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
  images-imageId:
    parameters:
      - $ref: 'commons.yaml#/parameters/userAgent'
    get:
      summary: Gets an image
      description: Return an image 
      operationId: readImage
      tags:
        - Media
      parameters:
        - name: imageId
          in: path
          required: true
          type: string
      produces:
        - image/png
        - image/gif
        - image/jpeg
        - application/json
        - application/x-yaml
      responses:
        '200':
          description: The image
          headers:
            $ref: commons.yaml#/defaultHeaders
        '404':
          description: Image do not exists
          headers:
            $ref: commons.yaml#/defaultHeaders
        '500':
          $ref: 'commons.yaml#/responses/Standard500ErrorResponse'
        default:
          $ref: 'commons.yaml#/responses/TotallyUnexpectedResponse'
securityDefinitions:
  OauthSecurity:
    description: New Oauth security system. Do not use MediaSecurity or LegacySecurity.
    type: oauth2
    flow: accessCode
    authorizationUrl: 'https://oauth.simple.api/authorization'
    tokenUrl: 'https://oauth.simple.api/token'
    scopes:
      admin: Admin scope
      user: User scope
  MediaSecurity:
    description: Specific media security for backward compatibility. Use OauthSecurity instead.
    type: apiKey
    in: query
    name: media-api-key
  LegacySecurity:
    description: Legacy security system for backward compatibility. Use OauthSecurity instead.
    type: basic

defaultSecurity:
  - OauthSecurity:
    - user
  - LegacySecurity: []

defaultMediatypes:
  - application/json
  - application/x-yaml

defaultHeaders:
  X-Rate-Limit-Remaining:
    description: How many calls consumer can do
    type: integer
  X-Rate-Limit-Reset:
    description: When rate limit will be reset
    type: string
    format: date-time

parameters:
  userAgent:
    name: User-Agent
    description: All API consumers MUST provide a user agent
    type: string
    in: header
    required: true
  pageSize:
    name: pageSize
    in: query
    description: Number of items returned
    type: integer
    format: int32
    minimum: 0
    exclusiveMinimum: true
    maximum: 100
    exclusiveMaximum: false
    multipleOf: 10
    default: 20
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    default: 1

responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    headers:
      $ref: '#/defaultHeaders'
    schema:
      $ref: '#/definitions/Error'
  TotallyUnexpectedResponse:
    description: A totally unexpected response
    headers:
      $ref: '#/defaultHeaders'

definitions:
  ErrorMessage:
    title: MultiDeviceErrorMessage
    description: An error message with a long and a short description
    required:
      - longMessage
      - shortMessage
    properties:
      longMessage:
        description: A long error description
        type: string
      shortMessage:
        description: A short error description
        type: string
  MultilingualErrorMessage:
    title: MultiLingualMultiDeviceErrorMessage
    description: An multilingual error message (hashmap) with a long and a short description
    additionalProperties:
      $ref: '#/definitions/ErrorMessage'
    properties:
      defaultLanguage:
        $ref: '#/definitions/ErrorMessage'
    example:
      defaultLanguage:
        longMessage: We're deeply sorry but an error occured
        shortMessage: Error
      fr:
        longMessage: Nous sommes désolé mais une erreur est survenu
        shortMessage: Erreur
        
  Error:
    title: MultiLingualMultiDeviceError
    description: Give full information about the problem
    required:
      - code
      - message
    properties:
      code:
        description: A human readable code (death to numeric error codes!)
        type: string
        enum:
          - DBERR
          - NTERR
          - UNERR
        example: UNERR
      message:
        $ref: '#/definitions/MultilingualErrorMessage'
  Paging:
    required:
      - totalItems
      - totalPages
      - pageSize
      - currentPage
    properties:
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer
swagger: '2.0'

info:
  version: 1.1.0
  title: Simple API
  description: |
    A simple API to learn how to write OpenAPI Specification.
    This file uses almost every single aspect of the [Open API Specification](https://openapis.org/).  
    This API will use JSON.  
    JSON looks like this:  
    
    ```JSON
    {
      "key": "value",
      "anotherKey": "anotherValue"
    }
    ```
  termsOfService: http://simple.api/terms-of-service
  contact:
    name: John Doe
    url: http://simple.api/contact
    email: contact@simple.api
  license:
    name: Apache-2.0
    url: http://www.apache.org/licenses/LICENSE-2.0

externalDocs: 
  description: |
    **Complete** documentation describing how to use this API
  url: http://doc.simple.api/

tags:
  - name: Persons
    description: Everything you need to handle `users` and `friends`
    externalDocs:
      description: People category documentation
      url: http://doc.simple.api/people
  - name: Items
    description: Everything you need to handle items collected by users
    externalDocs:
      description: Items category documentation
      url: http://doc.simple.api/items
  - name: Media
    description: Everything you need to handle images
    externalDocs:
      description: Media category documentation
      url: http://doc.simple.api/media
  - name: JSLess
    description: Specific operations for JS less consumers
    externalDocs:
      description: JS Less Consumers documentation
      url: http://doc.simple.api/jsless
      
schemes:
  - https
host: simple.api
basePath: /openapi101

consumes:
  $ref: commons.yaml#/defaultMediatypes
produces:
  $ref: commons.yaml#/defaultMediatypes

securityDefinitions:
  $ref: commons.yaml#/securityDefinitions

security:
  $ref: commons.yaml#/defaultSecurity

paths:
  /persons:
    $ref: 'persons.yaml#/persons'
  /js-less-consumer-persons:
    $ref: 'legacy.yaml#/js-less-consumer-persons'
  '/persons/{username}':
    $ref: 'persons.yaml#/persons-username'
  '/persons/{username}/friends':
    $ref: 'persons.yaml#/persons-username-friends'
  '/persons/{username}/collecting-items':
    $ref: 'persons.yaml#/persons-username-collecting-items'
  /images:
    $ref: 'images.yaml#/images'
  /images/{imageId}:
    $ref: 'images.yaml#/images-imageId'
securityDefinitions:
  OauthSecurity:
    description: New Oauth security system. Do not use MediaSecurity or LegacySecurity.
    type: oauth2
    flow: accessCode
    authorizationUrl: 'https://oauth.simple.api/authorization'
    tokenUrl: 'https://oauth.simple.api/token'
    scopes:
      admin: Admin scope
      user: User scope
  MediaSecurity:
    description: Specific media security for backward compatibility. Use OauthSecurity instead.
    type: apiKey
    in: query
    name: media-api-key
  LegacySecurity:
    description: Legacy security system for backward compatibility. Use OauthSecurity instead.
    type: basic

defaultSecurity:
  - OauthSecurity:
    - user
  - LegacySecurity: []
schemes:
  - https
server_and_port: simple.api
path: /openapi102
external:
  description: |
    **Complete** documentation describing how to use this API
  url: http://doc.simple.api/

categories:
  - name: Persons
    description: Everything you need to handle `users` and `friends`
    externalDocs:
      description: People category documentation
      url: http://doc.simple.api/people
  - name: Items
    description: Everything you need to handle items collected by users
    externalDocs:
      description: Items category documentation
      url: http://doc.simple.api/items
  - name: Media
    description: Everything you need to handle images
    externalDocs:
      description: Media category documentation
      url: http://doc.simple.api/media
  - name: JSLess
    description: Specific operations for JS less consumers
    externalDocs:
      description: JS Less Consumers documentation
      url: http://doc.simple.api/jsless
username:
  name: username
  in: path
  required: true
  description: The person's username
  type: string
pageSize:
  name: pageSize
  in: query
  description: Number of persons returned
  type: integer
  format: int32
  minimum: 0
  exclusiveMinimum: true
  maximum: 100
  exclusiveMaximum: false
  multipleOf: 10
  default: 20
pageNumber:
  name: pageNumber
  in: query
  description: Page number
  type: integer
  default: 1
includeNonVerifiedUsers:
  name: includeNonVerifiedUsers
  in: query
  description: Result will not include non verified user by default if this parameter is not provided
  type: boolean
  default: false
  allowEmptyValue: true
sortPersons:
  name: sort
  in: query
  description: Result will be sorted by lastTimeOnline descending and username ascending by default if this parameter is not provided
  type: array
  uniqueItems: true
  minItems: 1
  maxItems: 3
  collectionFormat: pipes
  items:
    type: string
    pattern: '[-+](username|lastTimeOnline|firstname|lastname)'
  default:
    - -lastTimeOnline
    - +username
filterItemTypes:
  name: itemType
  in: query
  description: Filter collected items on their type
  type: array
  collectionFormat: multi
  uniqueItems: true
  items:
    type: string
    enum:
      - AudioCassette
      - Vinyl
      - VHS
userAgent:
  name: User-Agent
  description: All API consumers MUST provide a user agent
  type: string
  in: header
  required: true
Standard500ErrorResponse:
  description: An unexpected error occured.
  headers:
    X-Rate-Limit-Remaining:
      description: How many calls consumer can do
      type: integer
    X-Rate-Limit-Reset:
      description: When rate limit will be reset
      type: string
      format: date-time
  schema:
    $ref: '#/definitions/Error'
PersonDoesNotExistResponse:
  description: Person does not exist.
  headers:
    X-Rate-Limit-Remaining:
      description: How many calls consumer can do
      type: integer
    X-Rate-Limit-Reset:
      description: When rate limit will be reset
      type: string
      format: date-time
TotallyUnexpectedResponse:
  description: A totally unexpected response
  headers:
    X-Rate-Limit-Remaining:
      description: How many calls consumer can do
      type: integer
    X-Rate-Limit-Reset:
      description: When rate limit will be reset
      type: string
      format: date-time
Person:
  title: Human
  description: A person which can be the user itself or one of his friend
  required:
    - username
  properties:
    firstName:
      description: first name
      type: string
      example: John
    lastName:
      description: last name
      type: string
      example: Doe
    username:
      description: Username used to connect to the service
      type: string
      pattern: '[a-z0-9]{8,64}'
      minLength: 8
      maxLength: 64
      example: john1doe6
    dateOfBirth:
      description: Date of birth
      type: string
      format: date
      example: 1978-06-21
    lastTimeOnline:
      description: The last time this person was connected to the service as a 
      type: string
      format: date-time
      readOnly: true
      example: 2016-06-10T12:36:58.014Z
    avatarBase64PNG:
      description: An avatar PNG image as a base64 encoded string ready to use as an src in img html tag
      type: string
      format: byte
      default: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAC4jAAAuIwF4pT92AAABy2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBJbWFnZVJlYWR5PC94bXA6Q3JlYXRvclRvb2w+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgqyI37xAAAU3UlEQVR4AeVbeXRc1Xn/zZt90UgajXbJ1mYtNraM95XF2AbbFINLg1sgBCg9JicnpDk9TciBAzQlFDds56T0QE45PTkQTNkhTmnslthhMWAweMObbGuzJdmythnNPtPfd9+MLEWyZFkj8keu/d685b577/f71vvdK0POwmsS+DMu2p8x7Yr0Px0AiUGCJ9fqftCzb4gzpm+oH70bIdJgADQNPCeJ5iPep0hPDAFD1ZrUIX5DAAh5JNpIgYtGEe/3IRrwIxIOKcJNRiM0oxlGqw0aD5gtrG5EIh6fVOKl8UkHQJFOYhCNIHLuHAJtzQj3dV2QMM2gwZpbBJs3H6aMLMRFYpR6XPCTCb2YVAAU8SQo3tsNX+NRhH3d+mD5TKmC8F8qCZFSSGg8EUego0UdjrwSOEorkBCJmCQQJhUA8h3h9hb0nPha0SdiTblOHvojdRYQBhcBiHahn0BE/b1w186eNBAmzQsYyNUQxV0RL4QLl+Oxi+MkQTLEorQZJoQJgL/5OLRJkoD0A8CBilWPnutAb+MRgERcNOFJKTDRWLrsFrgsGj83K3WI+XqUVKRbFdIPAIlHKIi+hv06OcL1QWUkx5Z6ZjUbUZKbCavRgL5AWB1ZDhMyzEB/Z4cuBSl7MajNiVym1wYkuR/q7iTT4yguzIfZRHcmIk29joTD8Pv6EAxHEY2LwaO08J/TakJWhgNNHd1oOUNOs2y8bol69/J7H6r77P4uxCJhGNJsENMLgHAnFkO8+wzcTitaT7erwY90spkMcLFOMBRFL7ktx5y6ctz7rdVYXF8Nb1YGQTPg+7euxYP/tgXbd+1DUTyKEKxs7o+t5kg9XNyztAOgkUv+c2dU70/+9MeYXlOl7F9Pnw+nW09h/6c78NnBRnzZGkCwV+f2t1YvxvoV87F4VjVyszMoMQnGSzGSmcDsmqn4l/tuxbxdP4aBsYRmMyjJoVW9OArHqJVGACjOFHOXlkAHO9368vNYs3J5MprTBxunPfDftAo9pxrQ091FVYjDbrcpol38jVJ6gqGIAky4Lwri6w+iakoBHvq7DXjk+S9RvtyD3vAYVI3jdRoBMMBKA3i8rQvrr7sayxbNQSgUJifpzpKGS36t2QXId3uQ66dO97YhTomJUaIDrCvVNO08Z+VKpMDEdmdWT+Xd7+GgTeklSGkSAAboaSoitjYTm2vzo/6yOljMZsQZy5tMJhgZ68uhkZAEpSCumZFw5yORW40oo/E4OW9kPU0zKSkSSTp/GJXI53rcHKmGbhLvoLegDU1LSYsEyFgs5Jw/QpcXPak4LsQKB4PBQJJZtPeKuRRtegUBxuZwIZGZj3hXI8LBfgJGaZF/SYkRCkUNHHa6RosZeXWlqMiw4w/HOlCcn4H+aByDBEaqj7ukBQAzB9xGK76iNBO3fn8Tunp6SXgQW97ZhoAlE3arFf3hCAGKwCzAUBr62lpw29rlqMjPxNbfHcDBcB48WW4EI1H0BENK7E0U944znVhfdRZWStc965bih5u+jceffQmbt3yIqRUe+AT0CZS0AJBJP96+6yv86KEnUFroxQ8e2Izm5mZEcquwau31Ss/b+0M43ueHm+JrtVhx6GgDjnKOUJabgUPBbFz7t99jAKSRoAj2dfbAZTYRBANyghHs3fYSZrp8ONnarkBac9UCbH7yNdirc//0AIgRCYkVQxatdZHMYXDyVDt6evtQkFeqwuAE43pQvI3Uf2OcekB3lkGrbws5qP9ReDzZYLikgJJ8gRaju6M3McTEsBpgycyEr7cDO/Y1INAfgN0msYCZxlMUZGJRQVokQLdHRkQ4+JxsNwdvRFtbO7TKMtjsDsTIWVuC8/xIHFZy1kwDaaJOR8ltMecR6rLNbic4TJbQ/1ttYVVPZpMMKOHjsx5KT8v+L1QfEd5zninWgrBNrEwYAMnZ2MX6ow/Np8+grKQQRd4sWncNJ/d8hqDBTAOpoYP+vMnfjwzqtYUqsG//AdTWumG22eBrPYI/fLQL3gwn+ugOv+7xwUnQLDSUzZ3dmN3VinBCH6qA3Mt2KEYTNoAC3YQBkEaiKnWVha8OHMGKpXNRU14KBy387YtqcazhMKw0glQGzHcpN6Dc44rZOZhWXa0yPn+zYibrvUNh4JyAPC2nkUyVBXSR1fMq8eLWD9SjCPsS9RIVkLnEREtaAAhShFGbhU/2HuNUII66mgrOA9pw/dqVyMvLG+rW6AKVi6QahHx+9FAyTE4P5s6yMyq0U+TjiNATCGniDUXMJUj6dN9hVFeWI0F788W+o0BxAQLS7wRLWgCIkOgijwOvvnsATz3YhUVz67Ftx0eIclocpEtTWV8SpiJBqwU+ivCevQfxP+9/gI9370UgwHA334mr5s/gRKgGxXkeJd5hujib1YzW9k68tv0zbLxxDd793Qf4+dufoGiqh3HAxFygYJcWAGQYzNqRKw48+osXUV6SixNNrSoUFqJF8G3UdYn19+z9Gv/x69fx3H9ukS8Gyi5eiZibKQWPbtqA5XPqkJ+TifbOCJ5/bbuqt3PPUWzZfRbeEjc9z8S5L40a0rU0JqGpg8aw9ZwfOOGjb9yHI5+8Rz2vQJAcbzjZjFfe/C1++sSzipiqqSXMD0TQ+EdTZo/ThnP+oKpTw0nQ4aY2dZ0p6cSaufB46fupEroDVK8mdEqLBMgIJCSV0LTU44S7yIMD/9eEf3/hJdxw3TXY8fFneHjzL9RASwrzlKs71tii7m+6chnKCwswJT8PpzvP4fEXt/A+B/2BgCLeYWHIbDGiO2pGjjODXoIxhZIp9fmET2mTgMEjiXGArlgYLbt3DjzO9WSpCZGPFlw4uOGKpbhv480ozvXCycDGyNjh6Vdex89+9WvkujPQ6fPBTFdIk0mjGIG7cgYseUU0glS4QXOFgQ4u8SJtEjC4f4nqAkYLCiuqYQ11IcB5/5nOLuX+8rMY1RGA+mlVqC4tUcmPXn8Ab+38QBGfl5mBjh5xc9QiegxSDJPVDktWjqqbTuKlj0mRAGmYpp+T/D50fbWL7t2EGAOYVLEzGgzQ1d127UpUFhfi/c+/xM6v9sHjdFD/JchJFkmnM3zOqp4FUw6nz2nmvvQyeQCwcY2i6mNO33L2OMKaTbm7JGmc3RkRGuTG8jPdaOcsMlUMJF5yB3ZvIVyVdVQFPYhKvU/Xr8Swk1ai9Aw5JVPRE6Iw0NfnZGeqvkSFwyQ+U9Jh1Hc7gyIhPpUHsPJ5aY4bxUyHZ06pREykaZLKpLVsJJVdFPNpmS6889JzmFKcj86uHlTS/ZmpEkJsD0E5Q6MYpJEzcr5goWpM4VwixOdNZ7rQWrEIPSY7Msj/iYc8IyM4KQBIiOKSlukb32cGU/KDW1/+JWbNqEUD3V+YwBTme1FWWoRyHkK0zCJDjAuaWk6jZk49Xn3qETxdY8V0WxyNIQ3ZbG8yQEi7F1DEU8SPR3nyRfDbZdmw0JLX1VbhvS3P483/3s4o8BXsPXh4GEuWLLgcN69bhfXrr0MZZ4bBPa/ghhIrHmv04JetQLkd6GEH6bQGaTOCMihhupOnE5zm3+gx4pHSo6gruxbRO+9l8BPlvgeLmgidYcDT3HIKHWfPcX4fg8vhQH5eDhMoXmTTTdLfcfpLsX/1VRgP/DPaC5fhnu1WfE4RkAllcOKTwAHwJyQBMmnlOoU6xMn1kTsn5CJiwMP1flRag+h1MV9Aa64xBxBlClz8eE52FvK9HnWdGolklWMEQ4Iesf5GTqdjVUXoawTybDF8tzaEm3faUJiXgJMA+HiEeUwUi0uSAEeS6DMkuDvMG0nskPNTbQmUcFa0OjeGe2cxmDEQolgXNM8C2FbeCc1bwFEzjicIai9Qinr55TODpLj4y5QQolxcDW7lapCJQIkRJKWvHHbhvsN0DWIMrAmU8VKY0Mtx8P8llYsGQJBOEX6Mbg0kvMKRwIbcOGblRFHujsLriMNp5hTWlJqq8CuDBYngcRjsNbD/1T9By84jYGxgJNcmS+nkaeTQHoS2P0D8skkhv5ccAt8YmSds6jVjd7sV206ZsKWTT9lFIcchY+u+BBQuCgAh3sO+jgmnQwbcUxTD2tIIpueEkUPxtBhl/YZc4Ek/OJqBwodGOxKBVkrC5bDd8ENoGSRMEqVDzBmTolxVDn36G8QOPQWDY54OUkKvJ+1LsUiylM37IxqaCcaOUxb84wkCR7UrJxARVvTzEMAupowJgHQsLqjBb8At3jg21QVJeIh5wDiiCQMzOLJYqXclA5MymHz9iYyImdwwF03NebDd9BCMEtpKeKwq88RMceCtxxFvfROGrGUESKbEyYb1RtRZsmDylFsIOFki8Lxp6TPj3RM23H+MOmFOYBp/OikNw8cxqKHk5ahASUeZSeKfqI3gqaW9mJsfUFPfQJS7QCTFzSJTYTnkTn+iHg868SlHmojz2/x5MBdU0Chm0NBxhujwMCWWA0tRLWyL70qSLK1I78OLgCx9ydsgXW2IqfPijAg20eZ8dKUff+lK4CiZ5eW4pZWxyqheIIuNHA9oeLo2jO9c1qdS1EJ4iuCxGh/yXqMu97fCfuXtsOZVUVfIIllEGFQM05eg303uR5lQYYJ0LNMm45ASIQgCyAxvEM8si2DuQSd+csTMZbQE/OxGNPdCYAwdgbTGIpW5fImzHMRqdxwbpvkV8cLxVKeq4sWe6A0SoTYYSzfCWl6nf5XSF3XH4dPQGTM9sC24m9vq9lDGuWHyIktKKoJkjqjmvfV9+NXlXInyGWAjhdSIC5YRAYhSXL02C3oPdmIV9d1tM1LcddG7YEujvaD+J/qPwFy7ihscnEodlCUb+EYg13lkm3MNPUYJmS+u5kJ8G/hwyIUwR2xShMf6aT7817wgGvuYnKHBGJFQfj3sueTavZyN7d/xGb577zrc/uBmbmuVmdqwqkM6H/1GRkZOlF+WrDaCficlwszNkaZpdxCw3RzdaLwbuceUYIUoDdeW+/Hi3AgafEZkc01yhF6HA5DBJatjp87iltuux6P3/wPy62YhbvUySKEmXRIIJD4ehME1jUmNwuSoL8BZMemkwOidigSX0VQgNTKdoz5VrfMUipmwrqIHz07rwJHmPnjNTLFJH4PKELbKhzItxdEmPPzA/dy55SLxDljqbkTC/xU5opLfgz6/iEuCloj2Qsusg5F7f1W5AP0DrXEMepWxKg58MexCT8Yzn+j7Enc/9gJ+/qO7cOSDbUq6B0MwBIAs6v2JnV/gX5+8H7U1NWrnhmR1rDOWkSPShwSe4y3sguGwwVUMg+wEV2V0wjRnpthEltHr6W2NdCaJJgcS3Z/Atv43sEybjTtv2YAr16zH0V6f2sqT+moAAOlKYnSGEFi9coX+PqlQlik1MBaspT/pHL8aqIZp0DigMe1IUjyNHs4ZBIBk//pgxnFm+i3RtxOmWT+Ba/EalYz1eDz4waa7gT07adRleV0vAwBYmIJuYBbmxr++DZUVFeptKkWluTJhnModX8EDHNQ4DZPIm4ET+XCfmuUl+x35J0mw0VPIT3KSnmDkqmM9FSyt19yhluVSi+gL5s9HxqylOMeMk2SspAwA4GBeDgcOcXV3AZzMzspsTQGQ5IrmzqUu8wuZ4Y2rcJXAnMs4/wjifj3dreLXkdpIDsqUW8iI8TokwmfH3x+5D99HMNQ/BsuUavZCOiS7zFKQn4/v3bAKZ75uYR6SaTk+GwBAFiGALkyfPl3qKgDURerEXRt6GWxCUi9H+RVlNmUifvb3CLc0jN0GAddoeM21K2l4j3GE58V1lF7OvyKITEDBWL8C3Iwq9Ksi1l+24M2beznTSocIgO4WFQByUju8XGUoLS5SH6TEP6WHCdmnq2qPEwBpjaJjIGOCH7/OwVGMRnWnevu26YuS7BlHfxI+h1qQKP0OTKXVQ01oUpKrKisUfRLYDUiAkcg0cXVm3sKZ8Hqpe4NL8kODjWohhum80AyuNfp1nOA5lyOyfzNCh79QdWWRQ9QslRhJ/abAMZdUwlz99wyI9rPLi7Q74qYDJ5GYsQYW5XIJXlKtUgzNy8tF+cKr1Y4VsQMqtDfLjgwawIUza+B2y4ZE+U43EikZMhWUy66UMbinPh35FOcWWOcU+Lc9R2/CPQPsU/pI9ZP6VUAQGAP/TsC28CYCwD+zUWowliRwvLEAEs6ZMFZdzrwBhzHok1T7nuxsXDl7BnrPdqu1R+ZumNMTAJpPoq66Sm1glEGkPtAFhWEsXaEhg7M4dqI/G9T6yCQPfZpgPtBaCsPpF9D43lXwT1+OfZ/vht3p5N4BK1PmM5Cbm8sFVEZrnCmq+KNuLvrLbke880NlSHUrPLTZgTuRkv6Pkah+ABb+0ZXS1gEm6rWELgsTszNrpwHPvQFLSZ5eTzeAPaiqIoEsA+IoN9IIP5QY3TyD83Xfp0mOyMvxFLbDkFhzLmK669t4f+s7yCso4C5QO44cPYafPfEM3nj7XZw7xxwiI0HZPivG0L6c84Le48nZ4Sigi/7TThtrlsLCnWlD2J8cZoounc5TanlOAl/dAJqmoGzqFFX1PPeTXyZlyTabllmcwbhdod6OhKeSRfI4irHp5r/A1Vcsw8L5c3HDurV4ZvOj6OvrxRtvvY3unh7+fZXuumwzFjEG2cgY5BT7JZEjFhH/fkabc2Ci61PWf8R6+sOK8jJe2NUuE03+PqeRS1brbroCxUX6ZGUYAElRMrNxLX/NpUWEqm9ykPoc93HbW1ujenLixEnuIrMolbvrjtuZ/Y3jQ26Zk6KkwO6kFNxJKThK9jKgGqlwk3Ui1AStcAlzCjnJP7AiKH9UUnSVFBfjijVrcJzb8TQVAO1vwIol8+FycfMyxX140RszOt0wFs5jZ/wzuAtyY/jXQ57IjlG6xM4Th9SO0rb2drSeauPuMsl1A7duvAX/y70CZzs7lRTIaGyXLYZWtJ79to8sfZJwYb7RmFuLuImeQHdXqr3BJx2ABLK4+LL6ioXAlwRNQmCgHfX19aruyADozciCBf+OjVyUWd1IQOn1Rj0zBpBm7Blurg/SJZWVobAgD41NzeozF43izOm13GnaoTcjBtGRAdsS2oK+Q+yb6A0rpIEuWnO5VYI2BeawanwQT2Zw586Zw7uT+H80X6vv56/SkgAAAABJRU5ErkJggg==
    spokenLanguages:
      $ref: '#/definitions/SpokenLanguages'
SpokenLanguages:
  title: Languages
  description: A hashmap of spoken languages
  additionalProperties:
    description: An additional spoken language
    type: string
  properties:
    defaultLanguage:
      description: Default spoken language
      type: string
      default: english
  example:
    defaultLanguage: french
    it: italian
    fr: french
Persons:
  title: Humans
  description: A list of users or friends
  required:
    - items
  properties:
    items:
      description: Array containg the list
      type: array
      minItems: 10
      maxItems: 100
      uniqueItems: true
      items:
        $ref: '#/definitions/Person'
      example:
        - firstname: Robert
          lastname": Doe
          username": robdo
          dateOfBirth: 1970-01-28
          lastTimeOnline: 2016-04-10T14:36:58.014Z
        - firstname: Jane
          lastname: Doe
          username: jdoe123
          dateOfBirth: 1980-05-12
          lastTimeOnline: 2016-05-12T19:23:59.014Z
ErrorMessage:
  title: MultiDeviceErrorMessage
  description: An error message with a long and a short description
  required:
    - longMessage
    - shortMessage
  properties:
    longMessage:
      description: A long error description
      type: string
    shortMessage:
      description: A short error description
      type: string
MultilingualErrorMessage:
  title: MultiLingualMultiDeviceErrorMessage
  description: An multilingual error message (hashmap) with a long and a short description
  additionalProperties:
    $ref: '#/definitions/ErrorMessage'
  properties:
    defaultLanguage:
      $ref: '#/definitions/ErrorMessage'
  example:
    defaultLanguage:
      longMessage: We're deeply sorry but an error occured
      shortMessage: Error
    fr:
      longMessage: Nous sommes désolé mais une erreur est survenu
      shortMessage: Erreur
      
Error:
  title: MultiLingualMultiDeviceError
  description: Give full information about the problem
  required:
    - code
    - message
  properties:
    code:
      description: A human readable code (death to numeric error codes!)
      type: string
      enum:
        - DBERR
        - NTERR
        - UNERR
      example: UNERR
    message:
      $ref: '#/definitions/MultilingualErrorMessage'
CollectingItem:
  discriminator: itemType
  required:
    - itemType
  properties:
    itemType:
      description: |
        An item can be of different type:
          
        type | definition
        -----|-----------
        Vinyl| #/definitions/Vinyl
        VHS  | #/definitions/VHS
        AudioCassette | #/definitions/AudioCassette
      type: string
      enum:
        - AudioCassette
        - Vinyl
        - VHS
    imageId:
      type: string
    maxPrice:
      type: number
      format: double
      minimum: 0
      maximum: 10000
      exclusiveMinimum: true
      exclusiveMaximum: false
Vinyl:
  allOf:
    - $ref: '#/definitions/CollectingItem'
    - required:
        - albumName
        - artist
      properties:
        albumName:
          type: string
        artist:
          type: string
VHS:
  allOf:
    - $ref: '#/definitions/CollectingItem'
    - required:
        - movieTitle
      properties:
        movieTitle:
          type: string
        director:
          type: string
AudioCassette:
  allOf:
    - $ref: '#/definitions/CollectingItem'
    - required:
        - albumName
        - artist
      properties:
        albumName:
          type: string
        artist:
          type: string
Paging:
  required:
    - totalItems
    - totalPages
    - pageSize
    - currentPage
  properties:
    totalItems:
      type: integer
    totalPages:
      type: integer
    pageSize:
      type: integer
    currentPage:
      type: integer
PagedPersons:
  allOf:
    - $ref: '#/definitions/Persons'
    - $ref: '#/definitions/Paging'
PagedCollectingItems:
  allOf:
    - properties:
        items:
          type: array
          minItems: 10
          maxItems: 100
          uniqueItems: true
          items:
            $ref: '#/definitions/CollectingItem'
    - $ref: '#/definitions/Paging'
/js-less-consumer-persons:
  parameters:
    - $ref: '#/parameters/userAgent'
  post:
    summary: Creates a person
    description: For JS-less partners
    operationId: createUserJS
    deprecated: true
    tags:
      - JSLess
      - Persons
    security:
      - OauthSecurity:
        - admin
      - LegacySecurity: []
    consumes:
      - application/x-www-form-urlencoded
    produces:
      - text/html
    parameters:
      - name: username
        in: formData
        required: true
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
        type: string
      - name: firstname
        in: formData
        type: string
      - name: lastname
        in: formData
        type: string
      - name: dateOfBirth
        in: formData
        type: string
        format: date
    responses:
      '204':
        description: Person succesfully created.
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '400':
        description: Person couldn't have been created.
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '500':
        description: An error occured.
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      default:
        $ref: '#/responses/TotallyUnexpectedResponse'
/persons:
  parameters:
    - $ref: '#/parameters/userAgent'
  get:
    summary: Gets some persons
    description: Returns a list containing all persons. The list supports paging.
    operationId: searchUsers
    tags:
      - Persons
    parameters:
      - $ref: '#/parameters/pageSize'
      - $ref: '#/parameters/pageNumber'
      - $ref: '#/parameters/includeNonVerifiedUsers'
      - $ref: '#/parameters/sortPersons'
    responses:
      '200':
        description: A list of Person
        schema:
          $ref: '#/definitions/Persons'
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '500':
        $ref: '#/responses/Standard500ErrorResponse'
      default:
        $ref: '#/responses/TotallyUnexpectedResponse'
  post:
    summary: Creates a person
    description: Adds a new person to the persons list.
    operationId: createUser
    tags:
      - Persons
    security:
      - OauthSecurity:
        - admin
      - LegacySecurity: []
    parameters:
      - name: person
        in: body
        required: true
        description: The person to create.
        schema:
          $ref: '#/definitions/Person'
    responses:
      '204':
        description: Person succesfully created.
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '400':
        description: Person couldn't have been created.
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '500':
        $ref: '#/responses/Standard500ErrorResponse'
      default:
        $ref: '#/responses/TotallyUnexpectedResponse'
'/persons/{username}':
  parameters:
    - $ref: '#/parameters/username'
    - $ref: '#/parameters/userAgent'
  get:
    summary: Gets a person
    description: Returns a single person for its username.
    operationId: readPerson
    tags:
      - Persons
    responses:
      '200':
        description: A Person
        schema:
          $ref: '#/definitions/Person'
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '404':
        $ref: '#/responses/PersonDoesNotExistResponse'
      '500':
        $ref: '#/responses/Standard500ErrorResponse'
      default:
        $ref: '#/responses/TotallyUnexpectedResponse'
  delete:
    summary: Deletes a person
    description: Delete a single person identified via its username
    operationId: deletePerson
    tags:
      - Persons
    responses:
      '204':
        description: Person successfully deleted.
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '404':
        $ref: '#/responses/PersonDoesNotExistResponse'
      '500':
        $ref: '#/responses/Standard500ErrorResponse'
      default:
        $ref: '#/responses/TotallyUnexpectedResponse'
'/persons/{username}/friends':
  parameters:
    - $ref: '#/parameters/username'
    - $ref: '#/parameters/userAgent'
  get:
    summary: Gets a person's friends
    description: Returns a list containing all persons. The list supports paging.
    operationId: readPersonsFriends
    tags:
      - Persons
    parameters:
      - $ref: '#/parameters/pageSize'
      - $ref: '#/parameters/pageNumber'
      - $ref: '#/parameters/includeNonVerifiedUsers'
      - $ref: '#/parameters/sortPersons'
    responses:
      '200':
        description: A person's friends list
        schema:
          $ref: '#/definitions/PagedPersons'
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '404':
        $ref: '#/responses/PersonDoesNotExistResponse'
      '500':
        $ref: '#/responses/Standard500ErrorResponse'
      default:
        $ref: '#/responses/TotallyUnexpectedResponse'
'/persons/{username}/collecting-items':
  parameters:
    - $ref: '#/parameters/username'
    - $ref: '#/parameters/userAgent'
  get:
    summary: Gets a person's collecting items list
    description: |
      Returns a list containing all items this person is looking for.  
      The list supports paging.
    operationId: readPersonsCollectingItems
    tags:
      - Items
    parameters:
      - $ref: '#/parameters/pageSize'
      - $ref: '#/parameters/pageNumber'
      - $ref: '#/parameters/filterItemTypes'
    responses:
      '200':
        description: A collected items list
        schema:
          $ref: '#/definitions/PagedCollectingItems'
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
        examples:
          application/json:
            {
              "totalItems": 10,
              "totalPage": 4,
              "pageSize": 3,
              "currentPage": 2,
              "items": 
              [
                { 
                  "itemType": "Vinyl",
                  "maxPrice": 20,
                  "imageId": "98096838-04eb-4bac-b32e-cd5b7196de71",
                  "albumName": "Captain Future Original Soundtrack",
                  "artist": "Yuji Ohno"
                },
                { 
                  "itemType": "VHS",
                  "maxPrice": 10,
                  "imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
                  "movieTitle": "Star Crash",
                  "director": "Luigi Cozzi"
                },
                { 
                  "itemType": "AudioCassette",
                  "maxPrice": 10,
                  "imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
                  "albumName": "Star Wars",
                  "artist": "John Williams"
                }
              ]
            }
      '404':
        $ref: '#/responses/PersonDoesNotExistResponse'
      '500':
        $ref: '#/responses/Standard500ErrorResponse'
      default:
        $ref: '#/responses/TotallyUnexpectedResponse'
/images:
  parameters:
    - $ref: '#/parameters/userAgent'
  post:
    summary: Uploads an image
    description: Upload an image, will return an image id. 
    operationId: storeImage
    externalDocs:
      description: How to upload media
      url: http://doc.simple.api/media/upload
    tags:
      - Media
    security:
      - MediaSecurity: []
    consumes:
      - multipart/form-data
    parameters:
      - name: image
        in: formData
        type: file
    responses:
      '200':
        description: Image's ID
        schema:
          properties:
            imageId:
              type: string
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '500':
        $ref: '#/responses/Standard500ErrorResponse'
      default:
        $ref: '#/responses/TotallyUnexpectedResponse'
/images/{imageId}:
  parameters:
    - $ref: '#/parameters/userAgent'
  get:
    summary: Gets an image
    description: Return an image 
    operationId: readImage
    tags:
      - Media
    parameters:
      - name: imageId
        in: path
        required: true
        type: string
    produces:
      - image/png
      - image/gif
      - image/jpeg
      - application/json
      - application/x-yaml
    responses:
      '200':
        description: The image
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '404':
        description: Image do not exists
        headers:
          X-Rate-Limit-Remaining:
            description: How many calls consumer can do
            type: integer
          X-Rate-Limit-Reset:
            description: When rate limit will be reset
            type: string
            format: date-time
      '500':
        $ref: '#/responses/Standard500ErrorResponse'
      default:
        $ref: '#/responses/TotallyUnexpectedResponse'
version: 1.1.0
title: Simple API
description: |
  A simple API to learn how to write OpenAPI Specification.
  This file uses almost every single aspect of the [Open API Specification](https://openapis.org/).  
  This API will use JSON.  
  JSON looks like this:  
  
  ```JSON
  {
    "key": "value",
    "anotherKey": "anotherValue"
  }
  ```
termsOfService: http://simple.api/terms-of-service
contact:
  name: John Doe
  url: http://simple.api/contact
  email: contact@simple.api
license:
  name: Apache-2.0
  url: http://www.apache.org/licenses/LICENSE-2.0
swagger: '2.0'

info:
  $ref: info.yaml

externalDocs: 
  $ref: documentation.yaml#/external

tags:
  $ref: documentation.yaml#/categories
      
schemes:
  $ref: endpoint.yaml#/schemes
host:
  $ref: endpoint.yaml#/server_and_port
basePath:
  $ref: endpoint.yaml#/path

consumes:
  $ref: mediatypes.yaml#/default
produces:
  $ref: mediatypes.yaml#/default

securityDefinitions:
  $ref: security.yaml#/securityDefinitions
security:
  $ref: security.yaml#/defaultSecurity

paths:
  $ref: paths.yaml

definitions:
  $ref: definitions.yaml
  
responses:
  $ref: responses.yaml

parameters:
  $ref: parameters.yaml
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "definitions.yaml#/OtherDefinitions/Persons"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "definitions.yaml#/SomeDefinitions/Person"
      responses:
        204:
          description: Persons succesfully created.
        400:
          description: Persons couldn't have been created.
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            $ref: "definitions.yaml#/SomeDefinitions/Person"
        404:
          description: The Person does not exists.
SomeDefinitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string

OtherDefinitions:
  Persons:
    type: array
    items:
      $ref: "#/SomeDefinitions/Person"
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "definitions.yaml#/Persons"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "definitions.yaml#/Person"
      responses:
        204:
          description: Persons succesfully created.
        400:
          description: Persons couldn't have been created.
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            $ref: "definitions.yaml#/Person"
        404:
          description: The Person does not exists.
Person:
  required:
    - username
  properties:
    firstName:
      type: string
    lastName:
      type: string
    username:
      type: string

Persons:
  type: array
  items:
    $ref: "#/Person"
Persons:
  type: array
  items:
    $ref: "http://localhost:8080/folder/person.yaml#/Person"
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "http://localhost:8080/another-folder/persons.yaml#/Persons"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "http://localhost:8080/folder/person.yaml#/Person"
      responses:
        204:
          description: Persons succesfully created.
        400:
          description: Persons couldn't have been created.
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            $ref: "http://localhost:8080/folder/person.yaml#/Person"
        404:
          description: The Person does not exists.
Persons:
  type: array
  items:
    $ref: "../folder/person.yaml#/Person"
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "another-folder/persons.yaml#/Persons"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "folder/person.yaml#/Person"
      responses:
        204:
          description: Persons succesfully created.
        400:
          description: Persons couldn't have been created.
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            $ref: "folder/person.yaml#/Person"
        404:
          description: The Person does not exists.
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "#/definitions/Persons"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "person.yaml#/Person"
      responses:
        204:
          description: Persons succesfully created.
        400:
          description: Persons couldn't have been created.
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            $ref: "person.yaml#/Person"
        404:
          description: The Person does not exists.

definitions:
  Persons:
    type: array
    items:
      $ref: "person.yaml#/Person"
Person:
  required:
    - username
  properties:
    firstName:
      type: string
    lastName:
      type: string
    username:
      type: string
swagger: '2.0'

info:
  version: 1.1.0
  title: Simple API
  description: |
    A simple API to learn how to write OpenAPI Specification.
    This file uses almost every single aspect of the [Open API Specification](https://openapis.org/).  
    This API will use JSON.  
    JSON looks like this:  
    
    ```JSON
    {
      "key": "value",
      "anotherKey": "anotherValue"
    }
    ```
  termsOfService: http://simple.api/terms-of-service
  contact:
    name: John Doe
    url: http://simple.api/contact
    email: contact@simple.api
  license:
    name: Apache-2.0
    url: http://www.apache.org/licenses/LICENSE-2.0

externalDocs: 
  description: |
    **Complete** documentation describing how to use this API
  url: http://doc.simple.api/

tags:
  - name: Persons
    description: Everything you need to handle `users` and `friends`
    externalDocs:
      description: People category documentation
      url: http://doc.simple.api/people
  - name: Items
    description: Everything you need to handle items collected by users
    externalDocs:
      description: Items category documentation
      url: http://doc.simple.api/items
  - name: Media
    description: Everything you need to handle images
    externalDocs:
      description: Media category documentation
      url: http://doc.simple.api/media
  - name: JSLess
    description: Specific operations for JS less consumers
    externalDocs:
      description: JS Less Consumers documentation
      url: http://doc.simple.api/jsless
      
schemes:
  - https
host: simple.api
basePath: /openapi101

consumes:
  - application/json
  - application/x-yaml
produces:
  - application/json
  - application/x-yaml

securityDefinitions:
  OauthSecurity:
    description: New Oauth security system. Do not use MediaSecurity or LegacySecurity.
    type: oauth2
    flow: accessCode
    authorizationUrl: 'https://oauth.simple.api/authorization'
    tokenUrl: 'https://oauth.simple.api/token'
    scopes:
      admin: Admin scope
      user: User scope
  MediaSecurity:
    description: Specific media security for backward compatibility. Use OauthSecurity instead.
    type: apiKey
    in: query
    name: media-api-key
  LegacySecurity:
    description: Legacy security system for backward compatibility. Use OauthSecurity instead.
    type: basic

security:
  - OauthSecurity:
    - user
  - LegacySecurity: []

paths:
  /persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      operationId: searchUsers
      tags:
        - Persons
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A list of Person
          schema:
            $ref: '#/definitions/Persons'
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      operationId: createUser
      tags:
        - Persons
      security:
        - OauthSecurity:
          - admin
        - LegacySecurity: []
      parameters:
        - name: person
          in: body
          required: true
          description: The person to create.
          schema:
            $ref: '#/definitions/Person'
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /js-less-consumer-persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Creates a person
      description: For JS-less partners
      operationId: createUserJS
      deprecated: true
      tags:
        - JSLess
        - Persons
      security:
        - OauthSecurity:
          - admin
        - LegacySecurity: []
      consumes:
        - application/x-www-form-urlencoded
      produces:
        - text/html
      parameters:
        - name: username
          in: formData
          required: true
          pattern: '[a-z0-9]{8,64}'
          minLength: 8
          maxLength: 64
          type: string
        - name: firstname
          in: formData
          type: string
        - name: lastname
          in: formData
          type: string
        - name: dateOfBirth
          in: formData
          type: string
          format: date
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '500':
          description: An error occured.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      operationId: readPerson
      tags:
        - Persons
      responses:
        '200':
          description: A Person
          schema:
            $ref: '#/definitions/Person'
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      operationId: deletePerson
      tags:
        - Persons
      responses:
        '204':
          description: Person successfully deleted.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/friends':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      operationId: readPersonsFriends
      tags:
        - Persons
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A person's friends list
          schema:
            $ref: '#/definitions/PagedPersons'
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/collecting-items':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's collecting items list
      description: |
        Returns a list containing all items this person is looking for.  
        The list supports paging.
      operationId: readPersonsCollectingItems
      tags:
        - Items
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/filterItemTypes'
      responses:
        '200':
          description: A collected items list
          schema:
            $ref: '#/definitions/PagedCollectingItems'
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
          examples:
            application/json:
              {
                "totalItems": 10,
                "totalPage": 4,
                "pageSize": 3,
                "currentPage": 2,
                "items": 
                [
                  { 
                    "itemType": "Vinyl",
                    "maxPrice": 20,
                    "imageId": "98096838-04eb-4bac-b32e-cd5b7196de71",
                    "albumName": "Captain Future Original Soundtrack",
                    "artist": "Yuji Ohno"
                  },
                  { 
                    "itemType": "VHS",
                    "maxPrice": 10,
                    "imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
                    "movieTitle": "Star Crash",
                    "director": "Luigi Cozzi"
                  },
                  { 
                    "itemType": "AudioCassette",
                    "maxPrice": 10,
                    "imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
                    "albumName": "Star Wars",
                    "artist": "John Williams"
                  }
                ]
              }
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Uploads an image
      description: Upload an image, will return an image id. 
      operationId: storeImage
      externalDocs:
        description: How to upload media
        url: http://doc.simple.api/media/upload
      tags:
        - Media
      security:
        - MediaSecurity: []
      consumes:
        - multipart/form-data
      parameters:
        - name: image
          in: formData
          type: file
      responses:
        '200':
          description: Image's ID
          schema:
            properties:
              imageId:
                type: string
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images/{imageId}:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets an image
      description: Return an image 
      operationId: readImage
      tags:
        - Media
      parameters:
        - name: imageId
          in: path
          required: true
          type: string
      produces:
        - image/png
        - image/gif
        - image/jpeg
        - application/json
        - application/x-yaml
      responses:
        '200':
          description: The image
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '404':
          description: Image do not exists
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
      
definitions:
  Person:
    title: Human
    description: A person which can be the user itself or one of his friend
    required:
      - username
    properties:
      firstName:
        description: first name
        type: string
        example: John
      lastName:
        description: last name
        type: string
        example: Doe
      username:
        description: Username used to connect to the service
        type: string
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
        example: john1doe6
      dateOfBirth:
        description: Date of birth
        type: string
        format: date
        example: 1978-06-21
      lastTimeOnline:
        description: The last time this person was connected to the service as a 
        type: string
        format: date-time
        readOnly: true
        example: 2016-06-10T12:36:58.014Z
      avatarBase64PNG:
        description: An avatar PNG image as a base64 encoded string ready to use as an src in img html tag
        type: string
        format: byte
        default: data:image/png;base64,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
      spokenLanguages:
        $ref: '#/definitions/SpokenLanguages'
  SpokenLanguages:
    title: Languages
    description: A hashmap of spoken languages
    additionalProperties:
      description: An additional spoken language
      type: string
    properties:
      defaultLanguage:
        description: Default spoken language
        type: string
        default: english
    example:
      defaultLanguage: french
      it: italian
      fr: french
  Persons:
    title: Humans
    description: A list of users or friends
    required:
      - items
    properties:
      items:
        description: Array containg the list
        type: array
        minItems: 10
        maxItems: 100
        uniqueItems: true
        items:
          $ref: '#/definitions/Person'
        example:
          - firstname: Robert
            lastname": Doe
            username": robdo
            dateOfBirth: 1970-01-28
            lastTimeOnline: 2016-04-10T14:36:58.014Z
          - firstname: Jane
            lastname: Doe
            username: jdoe123
            dateOfBirth: 1980-05-12
            lastTimeOnline: 2016-05-12T19:23:59.014Z
  ErrorMessage:
    title: MultiDeviceErrorMessage
    description: An error message with a long and a short description
    required:
      - longMessage
      - shortMessage
    properties:
      longMessage:
        description: A long error description
        type: string
      shortMessage:
        description: A short error description
        type: string
  MultilingualErrorMessage:
    title: MultiLingualMultiDeviceErrorMessage
    description: An multilingual error message (hashmap) with a long and a short description
    additionalProperties:
      $ref: '#/definitions/ErrorMessage'
    properties:
      defaultLanguage:
        $ref: '#/definitions/ErrorMessage'
    example:
      defaultLanguage:
        longMessage: We're deeply sorry but an error occured
        shortMessage: Error
      fr:
        longMessage: Nous sommes désolé mais une erreur est survenu
        shortMessage: Erreur
        
  Error:
    title: MultiLingualMultiDeviceError
    description: Give full information about the problem
    required:
      - code
      - message
    properties:
      code:
        description: A human readable code (death to numeric error codes!)
        type: string
        enum:
          - DBERR
          - NTERR
          - UNERR
        example: UNERR
      message:
        $ref: '#/definitions/MultilingualErrorMessage'
  CollectingItem:
    discriminator: itemType
    required:
      - itemType
    properties:
      itemType:
        description: |
          An item can be of different type:
            
          type | definition
          -----|-----------
          Vinyl| #/definitions/Vinyl
          VHS  | #/definitions/VHS
          AudioCassette | #/definitions/AudioCassette
        type: string
        enum:
          - AudioCassette
          - Vinyl
          - VHS
      imageId:
        type: string
      maxPrice:
        type: number
        format: double
        minimum: 0
        maximum: 10000
        exclusiveMinimum: true
        exclusiveMaximum: false
  Vinyl:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  VHS:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - movieTitle
        properties:
          movieTitle:
            type: string
          director:
            type: string
  AudioCassette:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  Paging:
    required:
      - totalItems
      - totalPages
      - pageSize
      - currentPage
    properties:
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer
  PagedPersons:
    allOf:
      - $ref: '#/definitions/Persons'
      - $ref: '#/definitions/Paging'
  PagedCollectingItems:
    allOf:
      - properties:
          items:
            type: array
            minItems: 10
            maxItems: 100
            uniqueItems: true
            items:
              $ref: '#/definitions/CollectingItem'
      - $ref: '#/definitions/Paging'
responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    headers:
      X-Rate-Limit-Remaining:
        description: How many calls consumer can do
        type: integer
      X-Rate-Limit-Reset:
        description: When rate limit will be reset
        type: string
        format: date-time
    schema:
      $ref: '#/definitions/Error'
  PersonDoesNotExistResponse:
    description: Person does not exist.
    headers:
      X-Rate-Limit-Remaining:
        description: How many calls consumer can do
        type: integer
      X-Rate-Limit-Reset:
        description: When rate limit will be reset
        type: string
        format: date-time
  TotallyUnexpectedResponse:
    description: A totally unexpected response
    headers:
      X-Rate-Limit-Remaining:
        description: How many calls consumer can do
        type: integer
      X-Rate-Limit-Reset:
        description: When rate limit will be reset
        type: string
        format: date-time

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  pageSize:
    name: pageSize
    in: query
    description: Number of persons returned
    type: integer
    format: int32
    minimum: 0
    exclusiveMinimum: true
    maximum: 100
    exclusiveMaximum: false
    multipleOf: 10
    default: 20
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    default: 1
  includeNonVerifiedUsers:
    name: includeNonVerifiedUsers
    in: query
    description: Result will not include non verified user by default if this parameter is not provided
    type: boolean
    default: false
    allowEmptyValue: true
  sortPersons:
    name: sort
    in: query
    description: Result will be sorted by lastTimeOnline descending and username ascending by default if this parameter is not provided
    type: array
    uniqueItems: true
    minItems: 1
    maxItems: 3
    collectionFormat: pipes
    items:
      type: string
      pattern: '[-+](username|lastTimeOnline|firstname|lastname)'
    default:
      - -lastTimeOnline
      - +username
  filterItemTypes:
    name: itemType
    in: query
    description: Filter collected items on their type
    type: array
    collectionFormat: multi
    uniqueItems: true
    items:
      type: string
      enum:
        - AudioCassette
        - Vinyl
        - VHS
  userAgent:
    name: User-Agent
    description: All API consumers MUST provide a user agent
    type: string
    in: header
    required: true
swagger: '2.0'

info:
  version: 1.1.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification
  termsOfService: http://simple.api/terms-of-service
  contact:
    name: John Doe
    url: http://simple.api/contact
    email: contact@simple.api
  license:
    name: Apache-2.0
    url: http://www.apache.org/licenses/LICENSE-2.0

externalDocs: 
  description: Complete documentation describing how to use this API
  url: http://doc.simple.api/

tags:
  - name: Persons
    description: Everything you need to handle users and friends
    externalDocs:
      description: Peopls category documentation
      url: http://doc.simple.api/people
  - name: Items
    description: Everything you need to handle items collected by users
    externalDocs:
      description: Items category documentation
      url: http://doc.simple.api/items
  - name: Media
    description: Everything you need to handle images
    externalDocs:
      description: Media category documentation
      url: http://doc.simple.api/media
  - name: JSLess
    description: Specific operations for JS less consumers
    externalDocs:
      description: JS Less Consumers documentation
      url: http://doc.simple.api/jsless
      
schemes:
  - https
host: simple.api
basePath: /openapi101

consumes:
  - application/json
  - application/x-yaml
produces:
  - application/json
  - application/x-yaml

securityDefinitions:
  OauthSecurity:
    description: New Oauth security system. Do not use MediaSecurity or LegacySecurity.
    type: oauth2
    flow: accessCode
    authorizationUrl: 'https://oauth.simple.api/authorization'
    tokenUrl: 'https://oauth.simple.api/token'
    scopes:
      admin: Admin scope
      user: User scope
  MediaSecurity:
    description: Specific media security for backward compatibility. Use OauthSecurity instead.
    type: apiKey
    in: query
    name: media-api-key
  LegacySecurity:
    description: Legacy security system for backward compatibility. Use OauthSecurity instead.
    type: basic

security:
  - OauthSecurity:
    - user
  - LegacySecurity: []

paths:
  /persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      operationId: searchUsers
      tags:
        - Persons
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A list of Person
          schema:
            $ref: '#/definitions/Persons'
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      operationId: createUser
      tags:
        - Persons
      security:
        - OauthSecurity:
          - admin
        - LegacySecurity: []
      parameters:
        - name: person
          in: body
          required: true
          description: The person to create.
          schema:
            $ref: '#/definitions/Person'
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /js-less-consumer-persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Creates a person
      description: For JS-less partners
      operationId: createUserJS
      deprecated: true
      tags:
        - JSLess
        - Persons
      security:
        - OauthSecurity:
          - admin
        - LegacySecurity: []
      consumes:
        - application/x-www-form-urlencoded
      produces:
        - text/html
      parameters:
        - name: username
          in: formData
          required: true
          pattern: '[a-z0-9]{8,64}'
          minLength: 8
          maxLength: 64
          type: string
        - name: firstname
          in: formData
          type: string
        - name: lastname
          in: formData
          type: string
        - name: dateOfBirth
          in: formData
          type: string
          format: date
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '500':
          description: An error occured.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      operationId: readPerson
      tags:
        - Persons
      responses:
        '200':
          description: A Person
          schema:
            $ref: '#/definitions/Person'
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      operationId: deletePerson
      tags:
        - Persons
      responses:
        '204':
          description: Person successfully deleted.
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/friends':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      operationId: readPersonsFriends
      tags:
        - Persons
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A person's friends list
          schema:
            $ref: '#/definitions/PagedPersons'
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/collecting-items':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's collecting items list
      description: >-
        Returns a list containing all items this person is looking for. The list
        supports paging.
      operationId: readPersonsCollectingItems
      tags:
        - Items
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/filterItemTypes'
      responses:
        '200':
          description: A collected items list
          schema:
            $ref: '#/definitions/PagedCollectingItems'
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
          examples:
            application/json:
              {
                "totalItems": 10,
                "totalPage": 4,
                "pageSize": 3,
                "currentPage": 2,
                "items": 
                [
                  { 
                    "itemType": "Vinyl",
                    "maxPrice": 20,
                    "imageId": "98096838-04eb-4bac-b32e-cd5b7196de71",
                    "albumName": "Captain Future Original Soundtrack",
                    "artist": "Yuji Ohno"
                  },
                  { 
                    "itemType": "VHS",
                    "maxPrice": 10,
                    "imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
                    "movieTitle": "Star Crash",
                    "director": "Luigi Cozzi"
                  },
                  { 
                    "itemType": "AudioCassette",
                    "maxPrice": 10,
                    "imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
                    "albumName": "Star Wars",
                    "artist": "John Williams"
                  }
                ]
              }
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Uploads an image
      description: Upload an image, will return an image id. 
      operationId: storeImage
      externalDocs:
        description: How to upload media
        url: http://doc.simple.api/media/upload
      tags:
        - Media
      security:
        - MediaSecurity: []
      consumes:
        - multipart/form-data
      parameters:
        - name: image
          in: formData
          type: file
      responses:
        '200':
          description: Image's ID
          schema:
            properties:
              imageId:
                type: string
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images/{imageId}:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets an image
      description: Return an image 
      operationId: readImage
      tags:
        - Media
      parameters:
        - name: imageId
          in: path
          required: true
          type: string
      produces:
        - image/png
        - image/gif
        - image/jpeg
        - application/json
        - application/x-yaml
      responses:
        '200':
          description: The image
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '404':
          description: Image do not exists
          headers:
            X-Rate-Limit-Remaining:
              description: How many calls consumer can do
              type: integer
            X-Rate-Limit-Reset:
              description: When rate limit will be reset
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
      
definitions:
  Person:
    title: Human
    description: A person which can be the user itself or one of his friend
    required:
      - username
    properties:
      firstName:
        description: first name
        type: string
        example: John
      lastName:
        description: last name
        type: string
        example: Doe
      username:
        description: Username used to connect to the service
        type: string
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
        example: john1doe6
      dateOfBirth:
        description: Date of birth
        type: string
        format: date
        example: 1978-06-21
      lastTimeOnline:
        description: The last time this person was connected to the service as a 
        type: string
        format: date-time
        readOnly: true
        example: 2016-06-10T12:36:58.014Z
      avatarBase64PNG:
        description: An avatar PNG image as a base64 encoded string ready to use as an src in img html tag
        type: string
        format: byte
        default: data:image/png;base64,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
      spokenLanguages:
        $ref: '#/definitions/SpokenLanguages'
  SpokenLanguages:
    title: Languages
    description: A hashmap of spoken languages
    additionalProperties:
      description: An additional spoken language
      type: string
    properties:
      defaultLanguage:
        description: Default spoken language
        type: string
        default: english
    example:
      defaultLanguage: french
      it: italian
      fr: french
  Persons:
    title: Humans
    description: A list of users or friends
    required:
      - items
    properties:
      items:
        description: Array containg the list
        type: array
        minItems: 10
        maxItems: 100
        uniqueItems: true
        items:
          $ref: '#/definitions/Person'
        example:
          - firstname: Robert
            lastname": Doe
            username": robdo
            dateOfBirth: 1970-01-28
            lastTimeOnline: 2016-04-10T14:36:58.014Z
          - firstname: Jane
            lastname: Doe
            username: jdoe123
            dateOfBirth: 1980-05-12
            lastTimeOnline: 2016-05-12T19:23:59.014Z
  ErrorMessage:
    title: MultiDeviceErrorMessage
    description: An error message with a long and a short description
    required:
      - longMessage
      - shortMessage
    properties:
      longMessage:
        description: A long error description
        type: string
      shortMessage:
        description: A short error description
        type: string
  MultilingualErrorMessage:
    title: MultiLingualMultiDeviceErrorMessage
    description: An multilingual error message (hashmap) with a long and a short description
    additionalProperties:
      $ref: '#/definitions/ErrorMessage'
    properties:
      defaultLanguage:
        $ref: '#/definitions/ErrorMessage'
    example:
      defaultLanguage:
        longMessage: We're deeply sorry but an error occured
        shortMessage: Error
      fr:
        longMessage: Nous sommes désolé mais une erreur est survenu
        shortMessage: Erreur
        
  Error:
    title: MultiLingualMultiDeviceError
    description: Give full information about the problem
    required:
      - code
      - message
    properties:
      code:
        description: A human readable code (death to numeric error codes!)
        type: string
        enum:
          - DBERR
          - NTERR
          - UNERR
        example: UNERR
      message:
        $ref: '#/definitions/MultilingualErrorMessage'
  CollectingItem:
    discriminator: itemType
    required:
      - itemType
    properties:
      itemType:
        type: string
        enum:
          - AudioCassette
          - Vinyl
          - VHS
      imageId:
        type: string
      maxPrice:
        type: number
        format: double
        minimum: 0
        maximum: 10000
        exclusiveMinimum: true
        exclusiveMaximum: false
  Vinyl:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  VHS:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - movieTitle
        properties:
          movieTitle:
            type: string
          director:
            type: string
  AudioCassette:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  Paging:
    required:
      - totalItems
      - totalPages
      - pageSize
      - currentPage
    properties:
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer
  PagedPersons:
    allOf:
      - $ref: '#/definitions/Persons'
      - $ref: '#/definitions/Paging'
  PagedCollectingItems:
    allOf:
      - properties:
          items:
            type: array
            minItems: 10
            maxItems: 100
            uniqueItems: true
            items:
              $ref: '#/definitions/CollectingItem'
      - $ref: '#/definitions/Paging'
responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    headers:
      X-Rate-Limit-Remaining:
        description: How many calls consumer can do
        type: integer
      X-Rate-Limit-Reset:
        description: When rate limit will be reset
        type: string
        format: date-time
    schema:
      $ref: '#/definitions/Error'
  PersonDoesNotExistResponse:
    description: Person does not exist.
    headers:
      X-Rate-Limit-Remaining:
        description: How many calls consumer can do
        type: integer
      X-Rate-Limit-Reset:
        description: When rate limit will be reset
        type: string
        format: date-time
  TotallyUnexpectedResponse:
    description: A totally unexpected response
    headers:
      X-Rate-Limit-Remaining:
        description: How many calls consumer can do
        type: integer
      X-Rate-Limit-Reset:
        description: When rate limit will be reset
        type: string
        format: date-time

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  pageSize:
    name: pageSize
    in: query
    description: Number of persons returned
    type: integer
    format: int32
    minimum: 0
    exclusiveMinimum: true
    maximum: 100
    exclusiveMaximum: false
    multipleOf: 10
    default: 20
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    default: 1
  includeNonVerifiedUsers:
    name: includeNonVerifiedUsers
    in: query
    description: Result will not include non verified user by default if this parameter is not provided
    type: boolean
    default: false
    allowEmptyValue: true
  sortPersons:
    name: sort
    in: query
    description: Result will be sorted by lastTimeOnline descending and username ascending by default if this parameter is not provided
    type: array
    uniqueItems: true
    minItems: 1
    maxItems: 3
    collectionFormat: pipes
    items:
      type: string
      pattern: '[-+](username|lastTimeOnline|firstname|lastname)'
    default:
      - -lastTimeOnline
      - +username
  filterItemTypes:
    name: itemType
    in: query
    description: Filter collected items on their type
    type: array
    collectionFormat: multi
    uniqueItems: true
    items:
      type: string
      enum:
        - AudioCassette
        - Vinyl
        - VHS
  userAgent:
    name: User-Agent
    description: All API consumers MUST provide a user agent
    type: string
    in: header
    required: true
swagger: '2.0'
info:
  version: 1.1.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification
schemes:
  - https
host: simple.api
basePath: /openapi101
consumes:
  - application/json
  - application/x-yaml
produces:
  - application/json
  - application/x-yaml

securityDefinitions:
  OauthSecurity:
    type: oauth2
    flow: accessCode
    authorizationUrl: 'https://oauth.simple.api/authorization'
    tokenUrl: 'https://oauth.simple.api/token'
    scopes:
      admin: Admin scope
      user: User scope
  MediaSecurity:
    type: apiKey
    in: query
    name: media-api-key
  LegacySecurity:
    type: basic

security:
  - OauthSecurity:
    - user
  - LegacySecurity: []

paths:
  /persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A list of Person
          schema:
            $ref: '#/definitions/Persons'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      security:
        - OauthSecurity:
          - admin
        - LegacySecurity: []
      parameters:
        - name: person
          in: body
          required: true
          description: The person to create.
          schema:
            $ref: '#/definitions/Person'
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /js-less-consumer-persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Creates a person
      description: For JS-less partners
      security:
        - OauthSecurity:
          - admin
        - LegacySecurity: []
      consumes:
        - application/x-www-form-urlencoded
      produces:
        - text/html
      parameters:
        - name: username
          in: formData
          required: true
          pattern: '[a-z0-9]{8,64}'
          minLength: 8
          maxLength: 64
          type: string
        - name: firstname
          in: formData
          type: string
        - name: lastname
          in: formData
          type: string
        - name: dateOfBirth
          in: formData
          type: string
          format: date
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          description: An error occured.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      responses:
        '200':
          description: A Person
          schema:
            $ref: '#/definitions/Person'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      responses:
        '204':
          description: Person successfully deleted.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/friends':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A person's friends list
          schema:
            $ref: '#/definitions/PagedPersons'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/collecting-items':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's collecting items list
      description: >-
        Returns a list containing all items this person is looking for. The list
        supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/filterItemTypes'
      responses:
        '200':
          description: A collected items list
          schema:
            $ref: '#/definitions/PagedCollectingItems'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Uploads an image
      security:
        - MediaSecurity: []
      consumes:
        - multipart/form-data
      parameters:
        - name: image
          in: formData
          type: file
      responses:
        '200':
          description: Image's ID
          schema:
            properties:
              imageId:
                type: string
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images/{imageId}:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets an image
      parameters:
        - name: imageId
          in: path
          required: true
          type: string
      produces:
        - image/png
        - image/gif
        - image/jpeg
        - application/json
        - application/x-yaml
      responses:
        '200':
          description: The image
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          description: Image do not exists
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
      
definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
      dateOfBirth:
        type: string
        format: date
      lastTimeOnline:
        type: string
        format: date-time
        readOnly: true
      avatarBase64PNG:
        type: string
        format: byte
        default: data:image/png;base64,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
      spokenLanguages:
        $ref: '#/definitions/SpokenLanguages'
  SpokenLanguages:
    additionalProperties:
      type: string
    properties:
      defaultLanguage:
        type: string
        default: english
  Persons:
    required:
      - items
    properties:
      items:
        type: array
        minItems: 10
        maxItems: 100
        uniqueItems: true
        items:
          $ref: '#/definitions/Person'
  ErrorMessage:
    required:
      - longMessage
      - shortMessage
    properties:
      longMessage:
        type: string
      shortMessage:
        type: string
  MultilingualErrorMessage:
    additionalProperties:
      $ref: '#/definitions/ErrorMessage'
    properties:
      defaultLanguage:
        $ref: '#/definitions/ErrorMessage'
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: string
        enum:
          - DBERR
          - NTERR
          - UNERR
      message:
        $ref: '#/definitions/MultilingualErrorMessage'
  CollectingItem:
    discriminator: itemType
    required:
      - itemType
    properties:
      itemType:
        type: string
        enum:
          - AudioCassette
          - Vinyl
          - VHS
      imageId:
        type: string
      maxPrice:
        type: number
        format: double
        minimum: 0
        maximum: 10000
        exclusiveMinimum: true
        exclusiveMaximum: false
  Vinyl:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  VHS:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - movieTitle
        properties:
          movieTitle:
            type: string
          director:
            type: string
  AudioCassette:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  Paging:
    required:
      - totalItems
      - totalPages
      - pageSize
      - currentPage
    properties:
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer
  PagedPersons:
    allOf:
      - $ref: '#/definitions/Persons'
      - $ref: '#/definitions/Paging'
  PagedCollectingItems:
    allOf:
      - properties:
          items:
            type: array
            minItems: 10
            maxItems: 100
            uniqueItems: true
            items:
              $ref: '#/definitions/CollectingItem'
      - $ref: '#/definitions/Paging'
responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time
    schema:
      $ref: '#/definitions/Error'
  PersonDoesNotExistResponse:
    description: Person does not exist.
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time
  TotallyUnexpectedResponse:
    description: A totally unexpected response
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  pageSize:
    name: pageSize
    in: query
    description: Number of persons returned
    type: integer
    format: int32
    minimum: 0
    exclusiveMinimum: true
    maximum: 100
    exclusiveMaximum: false
    multipleOf: 10
    default: 20
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    default: 1
  includeNonVerifiedUsers:
    name: includeNonVerifiedUsers
    in: query
    type: boolean
    default: false
    allowEmptyValue: true
  sortPersons:
    name: sort
    in: query
    type: array
    uniqueItems: true
    minItems: 1
    maxItems: 3
    collectionFormat: pipes
    items:
      type: string
      pattern: '[-+](username|lastTimeOnline|firstname|lastname)'
    default:
      - -lastTimeOnline
      - +username
  filterItemTypes:
    name: itemType
    in: query
    type: array
    collectionFormat: multi
    uniqueItems: true
    items:
      type: string
      enum:
        - AudioCassette
        - Vinyl
        - VHS
  userAgent:
    name: User-Agent
    type: string
    in: header
    required: true
swagger: '2.0'
info:
  version: 1.1.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification
schemes:
  - https
host: simple.api
basePath: /openapi101
consumes:
  - application/json
  - application/x-yaml
produces:
  - application/json
  - application/x-yaml

securityDefinitions:
  OauthSecurity:
    type: oauth2
    flow: accessCode
    authorizationUrl: 'https://oauth.simple.api/authorization'
    tokenUrl: 'https://oauth.simple.api/token'
    scopes:
      admin: Admin scope
      user: User scope
      media: Media scope

security:
  - OauthSecurity:
    - user

paths:
  /persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A list of Person
          schema:
            $ref: '#/definitions/Persons'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      security:
        - OauthSecurity:
          - admin
      parameters:
        - name: person
          in: body
          required: true
          description: The person to create.
          schema:
            $ref: '#/definitions/Person'
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /js-less-consumer-persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Creates a person
      description: For JS-less partners
      security:
        - OauthSecurity:
          - admin
      consumes:
        - application/x-www-form-urlencoded
      produces:
        - text/html
      parameters:
        - name: username
          in: formData
          required: true
          pattern: '[a-z0-9]{8,64}'
          minLength: 8
          maxLength: 64
          type: string
        - name: firstname
          in: formData
          type: string
        - name: lastname
          in: formData
          type: string
        - name: dateOfBirth
          in: formData
          type: string
          format: date
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          description: An error occured.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      responses:
        '200':
          description: A Person
          schema:
            $ref: '#/definitions/Person'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      responses:
        '204':
          description: Person successfully deleted.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/friends':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A person's friends list
          schema:
            $ref: '#/definitions/PagedPersons'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/collecting-items':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's collecting items list
      description: >-
        Returns a list containing all items this person is looking for. The list
        supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/filterItemTypes'
      responses:
        '200':
          description: A collected items list
          schema:
            $ref: '#/definitions/PagedCollectingItems'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Uploads an image
      security:
        - OauthSecurity:
          - media
      consumes:
        - multipart/form-data
      parameters:
        - name: image
          in: formData
          type: file
      responses:
        '200':
          description: Image's ID
          schema:
            properties:
              imageId:
                type: string
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images/{imageId}:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets an image
      parameters:
        - name: imageId
          in: path
          required: true
          type: string
      produces:
        - image/png
        - image/gif
        - image/jpeg
        - application/json
        - application/x-yaml
      responses:
        '200':
          description: The image
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          description: Image do not exists
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
      
definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
      dateOfBirth:
        type: string
        format: date
      lastTimeOnline:
        type: string
        format: date-time
        readOnly: true
      avatarBase64PNG:
        type: string
        format: byte
        default: data:image/png;base64,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
      spokenLanguages:
        $ref: '#/definitions/SpokenLanguages'
  SpokenLanguages:
    additionalProperties:
      type: string
    properties:
      defaultLanguage:
        type: string
        default: english
  Persons:
    required:
      - items
    properties:
      items:
        type: array
        minItems: 10
        maxItems: 100
        uniqueItems: true
        items:
          $ref: '#/definitions/Person'
  ErrorMessage:
    required:
      - longMessage
      - shortMessage
    properties:
      longMessage:
        type: string
      shortMessage:
        type: string
  MultilingualErrorMessage:
    additionalProperties:
      $ref: '#/definitions/ErrorMessage'
    properties:
      defaultLanguage:
        $ref: '#/definitions/ErrorMessage'
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: string
        enum:
          - DBERR
          - NTERR
          - UNERR
      message:
        $ref: '#/definitions/MultilingualErrorMessage'
  CollectingItem:
    discriminator: itemType
    required:
      - itemType
    properties:
      itemType:
        type: string
        enum:
          - AudioCassette
          - Vinyl
          - VHS
      imageId:
        type: string
      maxPrice:
        type: number
        format: double
        minimum: 0
        maximum: 10000
        exclusiveMinimum: true
        exclusiveMaximum: false
  Vinyl:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  VHS:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - movieTitle
        properties:
          movieTitle:
            type: string
          director:
            type: string
  AudioCassette:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  Paging:
    required:
      - totalItems
      - totalPages
      - pageSize
      - currentPage
    properties:
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer
  PagedPersons:
    allOf:
      - $ref: '#/definitions/Persons'
      - $ref: '#/definitions/Paging'
  PagedCollectingItems:
    allOf:
      - properties:
          items:
            type: array
            minItems: 10
            maxItems: 100
            uniqueItems: true
            items:
              $ref: '#/definitions/CollectingItem'
      - $ref: '#/definitions/Paging'
responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time
    schema:
      $ref: '#/definitions/Error'
  PersonDoesNotExistResponse:
    description: Person does not exist.
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time
  TotallyUnexpectedResponse:
    description: A totally unexpected response
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  pageSize:
    name: pageSize
    in: query
    description: Number of persons returned
    type: integer
    format: int32
    minimum: 0
    exclusiveMinimum: true
    maximum: 100
    exclusiveMaximum: false
    multipleOf: 10
    default: 20
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    default: 1
  includeNonVerifiedUsers:
    name: includeNonVerifiedUsers
    in: query
    type: boolean
    default: false
    allowEmptyValue: true
  sortPersons:
    name: sort
    in: query
    type: array
    uniqueItems: true
    minItems: 1
    maxItems: 3
    collectionFormat: pipes
    items:
      type: string
      pattern: '[-+](username|lastTimeOnline|firstname|lastname)'
    default:
      - -lastTimeOnline
      - +username
  filterItemTypes:
    name: itemType
    in: query
    type: array
    collectionFormat: multi
    uniqueItems: true
    items:
      type: string
      enum:
        - AudioCassette
        - Vinyl
        - VHS
  userAgent:
    name: User-Agent
    type: string
    in: header
    required: true
swagger: '2.0'
info:
  version: 1.1.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification
schemes:
  - https
host: simple.api
basePath: /openapi101
consumes:
  - application/json
  - application/x-yaml
produces:
  - application/json
  - application/x-yaml

securityDefinitions:
  UserSecurity:
    type: apiKey
    in: header
    name: SIMPLE-API-KEY
  AdminSecurity:
    type: apiKey
    in: header
    name: ADMIN-API-KEY
  MediaSecurity:
    type: apiKey
    in: query
    name: media-api-key

security:
  - UserSecurity: [] 

paths:
  /persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A list of Person
          schema:
            $ref: '#/definitions/Persons'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      security:
        - AdminSecurity: []
      parameters:
        - name: person
          in: body
          required: true
          description: The person to create.
          schema:
            $ref: '#/definitions/Person'
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /js-less-consumer-persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Creates a person
      description: For JS-less partners
      security:
        - AdminSecurity: []
      consumes:
        - application/x-www-form-urlencoded
      produces:
        - text/html
      parameters:
        - name: username
          in: formData
          required: true
          pattern: '[a-z0-9]{8,64}'
          minLength: 8
          maxLength: 64
          type: string
        - name: firstname
          in: formData
          type: string
        - name: lastname
          in: formData
          type: string
        - name: dateOfBirth
          in: formData
          type: string
          format: date
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          description: An error occured.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      responses:
        '200':
          description: A Person
          schema:
            $ref: '#/definitions/Person'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      responses:
        '204':
          description: Person successfully deleted.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/friends':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A person's friends list
          schema:
            $ref: '#/definitions/PagedPersons'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/collecting-items':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's collecting items list
      description: >-
        Returns a list containing all items this person is looking for. The list
        supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/filterItemTypes'
      responses:
        '200':
          description: A collected items list
          schema:
            $ref: '#/definitions/PagedCollectingItems'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Uploads an image
      security:
        - MediaSecurity: []
      consumes:
        - multipart/form-data
      parameters:
        - name: image
          in: formData
          type: file
      responses:
        '200':
          description: Image's ID
          schema:
            properties:
              imageId:
                type: string
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images/{imageId}:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets an image
      parameters:
        - name: imageId
          in: path
          required: true
          type: string
      produces:
        - image/png
        - image/gif
        - image/jpeg
        - application/json
        - application/x-yaml
      responses:
        '200':
          description: The image
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          description: Image do not exists
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
      
definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
      dateOfBirth:
        type: string
        format: date
      lastTimeOnline:
        type: string
        format: date-time
        readOnly: true
      avatarBase64PNG:
        type: string
        format: byte
        default: data:image/png;base64,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
      spokenLanguages:
        $ref: '#/definitions/SpokenLanguages'
  SpokenLanguages:
    additionalProperties:
      type: string
    properties:
      defaultLanguage:
        type: string
        default: english
  Persons:
    required:
      - items
    properties:
      items:
        type: array
        minItems: 10
        maxItems: 100
        uniqueItems: true
        items:
          $ref: '#/definitions/Person'
  ErrorMessage:
    required:
      - longMessage
      - shortMessage
    properties:
      longMessage:
        type: string
      shortMessage:
        type: string
  MultilingualErrorMessage:
    additionalProperties:
      $ref: '#/definitions/ErrorMessage'
    properties:
      defaultLanguage:
        $ref: '#/definitions/ErrorMessage'
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: string
        enum:
          - DBERR
          - NTERR
          - UNERR
      message:
        $ref: '#/definitions/MultilingualErrorMessage'
  CollectingItem:
    discriminator: itemType
    required:
      - itemType
    properties:
      itemType:
        type: string
        enum:
          - AudioCassette
          - Vinyl
          - VHS
      imageId:
        type: string
      maxPrice:
        type: number
        format: double
        minimum: 0
        maximum: 10000
        exclusiveMinimum: true
        exclusiveMaximum: false
  Vinyl:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  VHS:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - movieTitle
        properties:
          movieTitle:
            type: string
          director:
            type: string
  AudioCassette:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  Paging:
    required:
      - totalItems
      - totalPages
      - pageSize
      - currentPage
    properties:
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer
  PagedPersons:
    allOf:
      - $ref: '#/definitions/Persons'
      - $ref: '#/definitions/Paging'
  PagedCollectingItems:
    allOf:
      - properties:
          items:
            type: array
            minItems: 10
            maxItems: 100
            uniqueItems: true
            items:
              $ref: '#/definitions/CollectingItem'
      - $ref: '#/definitions/Paging'
responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time
    schema:
      $ref: '#/definitions/Error'
  PersonDoesNotExistResponse:
    description: Person does not exist.
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time
  TotallyUnexpectedResponse:
    description: A totally unexpected response
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  pageSize:
    name: pageSize
    in: query
    description: Number of persons returned
    type: integer
    format: int32
    minimum: 0
    exclusiveMinimum: true
    maximum: 100
    exclusiveMaximum: false
    multipleOf: 10
    default: 20
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    default: 1
  includeNonVerifiedUsers:
    name: includeNonVerifiedUsers
    in: query
    type: boolean
    default: false
    allowEmptyValue: true
  sortPersons:
    name: sort
    in: query
    type: array
    uniqueItems: true
    minItems: 1
    maxItems: 3
    collectionFormat: pipes
    items:
      type: string
      pattern: '[-+](username|lastTimeOnline|firstname|lastname)'
    default:
      - -lastTimeOnline
      - +username
  filterItemTypes:
    name: itemType
    in: query
    type: array
    collectionFormat: multi
    uniqueItems: true
    items:
      type: string
      enum:
        - AudioCassette
        - Vinyl
        - VHS
  userAgent:
    name: User-Agent
    type: string
    in: header
    required: true
swagger: '2.0'
info:
  version: 1.1.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification
schemes:
  - https
host: simple.api
basePath: /openapi101
consumes:
  - application/json
  - application/x-yaml
produces:
  - application/json
  - application/x-yaml

securityDefinitions:
  UserSecurity:
    type: basic
  AdminSecurity:
    type: basic
  MediaSecurity:
    type: basic

security:
  - UserSecurity: [] 

paths:
  /persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A list of Person
          schema:
            $ref: '#/definitions/Persons'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      security:
        - AdminSecurity: []
      parameters:
        - name: person
          in: body
          required: true
          description: The person to create.
          schema:
            $ref: '#/definitions/Person'
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /js-less-consumer-persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Creates a person
      description: For JS-less partners
      security:
        - AdminSecurity: []
      consumes:
        - application/x-www-form-urlencoded
      produces:
        - text/html
      parameters:
        - name: username
          in: formData
          required: true
          pattern: '[a-z0-9]{8,64}'
          minLength: 8
          maxLength: 64
          type: string
        - name: firstname
          in: formData
          type: string
        - name: lastname
          in: formData
          type: string
        - name: dateOfBirth
          in: formData
          type: string
          format: date
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          description: An error occured.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      responses:
        '200':
          description: A Person
          schema:
            $ref: '#/definitions/Person'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      responses:
        '204':
          description: Person successfully deleted.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/friends':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A person's friends list
          schema:
            $ref: '#/definitions/PagedPersons'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/collecting-items':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's collecting items list
      description: >-
        Returns a list containing all items this person is looking for. The list
        supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/filterItemTypes'
      responses:
        '200':
          description: A collected items list
          schema:
            $ref: '#/definitions/PagedCollectingItems'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Uploads an image
      security:
        - MediaSecurity: []
      consumes:
        - multipart/form-data
      parameters:
        - name: image
          in: formData
          type: file
      responses:
        '200':
          description: Image's ID
          schema:
            properties:
              imageId:
                type: string
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images/{imageId}:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets an image
      parameters:
        - name: imageId
          in: path
          required: true
          type: string
      produces:
        - image/png
        - image/gif
        - image/jpeg
        - application/json
        - application/x-yaml
      responses:
        '200':
          description: The image
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          description: Image do not exists
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
      
definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
      dateOfBirth:
        type: string
        format: date
      lastTimeOnline:
        type: string
        format: date-time
        readOnly: true
      avatarBase64PNG:
        type: string
        format: byte
        default: data:image/png;base64,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
      spokenLanguages:
        $ref: '#/definitions/SpokenLanguages'
  SpokenLanguages:
    additionalProperties:
      type: string
    properties:
      defaultLanguage:
        type: string
        default: english
  Persons:
    required:
      - items
    properties:
      items:
        type: array
        minItems: 10
        maxItems: 100
        uniqueItems: true
        items:
          $ref: '#/definitions/Person'
  ErrorMessage:
    required:
      - longMessage
      - shortMessage
    properties:
      longMessage:
        type: string
      shortMessage:
        type: string
  MultilingualErrorMessage:
    additionalProperties:
      $ref: '#/definitions/ErrorMessage'
    properties:
      defaultLanguage:
        $ref: '#/definitions/ErrorMessage'
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: string
        enum:
          - DBERR
          - NTERR
          - UNERR
      message:
        $ref: '#/definitions/MultilingualErrorMessage'
  CollectingItem:
    discriminator: itemType
    required:
      - itemType
    properties:
      itemType:
        type: string
        enum:
          - AudioCassette
          - Vinyl
          - VHS
      imageId:
        type: string
      maxPrice:
        type: number
        format: double
        minimum: 0
        maximum: 10000
        exclusiveMinimum: true
        exclusiveMaximum: false
  Vinyl:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  VHS:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - movieTitle
        properties:
          movieTitle:
            type: string
          director:
            type: string
  AudioCassette:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  Paging:
    required:
      - totalItems
      - totalPages
      - pageSize
      - currentPage
    properties:
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer
  PagedPersons:
    allOf:
      - $ref: '#/definitions/Persons'
      - $ref: '#/definitions/Paging'
  PagedCollectingItems:
    allOf:
      - properties:
          items:
            type: array
            minItems: 10
            maxItems: 100
            uniqueItems: true
            items:
              $ref: '#/definitions/CollectingItem'
      - $ref: '#/definitions/Paging'
responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time
    schema:
      $ref: '#/definitions/Error'
  PersonDoesNotExistResponse:
    description: Person does not exist.
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time
  TotallyUnexpectedResponse:
    description: A totally unexpected response
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  pageSize:
    name: pageSize
    in: query
    description: Number of persons returned
    type: integer
    format: int32
    minimum: 0
    exclusiveMinimum: true
    maximum: 100
    exclusiveMaximum: false
    multipleOf: 10
    default: 20
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    default: 1
  includeNonVerifiedUsers:
    name: includeNonVerifiedUsers
    in: query
    type: boolean
    default: false
    allowEmptyValue: true
  sortPersons:
    name: sort
    in: query
    type: array
    uniqueItems: true
    minItems: 1
    maxItems: 3
    collectionFormat: pipes
    items:
      type: string
      pattern: '[-+](username|lastTimeOnline|firstname|lastname)'
    default:
      - -lastTimeOnline
      - +username
  filterItemTypes:
    name: itemType
    in: query
    type: array
    collectionFormat: multi
    uniqueItems: true
    items:
      type: string
      enum:
        - AudioCassette
        - Vinyl
        - VHS
  userAgent:
    name: User-Agent
    type: string
    in: header
    required: true
POST /js-less-persons

username=apihandyman&firstname=API&lastname=Handyman
swagger: '2.0'
info:
  version: 1.1.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification
schemes:
  - https
host: simple.api
basePath: /openapi101
consumes:
  - application/json
  - application/x-yaml
produces:
  - application/json
  - application/x-yaml
paths:
  /persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A list of Person
          schema:
            $ref: '#/definitions/Persons'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          required: true
          description: The person to create.
          schema:
            $ref: '#/definitions/Person'
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /js-less-consumer-persons:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Creates a person
      description: For JS-less partners
      consumes:
        - application/x-www-form-urlencoded
      produces:
        - text/html
      parameters:
        - name: username
          in: formData
          required: true
          pattern: '[a-z0-9]{8,64}'
          minLength: 8
          maxLength: 64
          type: string
        - name: firstname
          in: formData
          type: string
        - name: lastname
          in: formData
          type: string
        - name: dateOfBirth
          in: formData
          type: string
          format: date
      responses:
        '204':
          description: Person succesfully created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '400':
          description: Person couldn't have been created.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          description: An error occured.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      responses:
        '200':
          description: A Person
          schema:
            $ref: '#/definitions/Person'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      responses:
        '204':
          description: Person successfully deleted.
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/friends':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/includeNonVerifiedUsers'
        - $ref: '#/parameters/sortPersons'
      responses:
        '200':
          description: A person's friends list
          schema:
            $ref: '#/definitions/PagedPersons'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  '/persons/{username}/collecting-items':
    parameters:
      - $ref: '#/parameters/username'
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets a person's collecting items list
      description: >-
        Returns a list containing all items this person is looking for. The list
        supports paging.
      parameters:
        - $ref: '#/parameters/pageSize'
        - $ref: '#/parameters/pageNumber'
        - $ref: '#/parameters/filterItemTypes'
      responses:
        '200':
          description: A collected items list
          schema:
            $ref: '#/definitions/PagedCollectingItems'
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          $ref: '#/responses/PersonDoesNotExistResponse'
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Uploads an image
      consumes:
        - multipart/form-data
      parameters:
        - name: image
          in: formData
          type: file
      responses:
        '200':
          description: Image's ID
          schema:
            properties:
              imageId:
                type: string
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
  /images/{imageId}:
    parameters:
      - $ref: '#/parameters/userAgent'
    get:
      summary: Gets an image
      parameters:
        - name: imageId
          in: path
          required: true
          type: string
      produces:
        - image/png
        - image/gif
        - image/jpeg
        - application/json
        - application/x-yaml
      responses:
        '200':
          description: The image
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '404':
          description: Image do not exists
          headers:
            X-Rate-Limit-Remaining:
              type: integer
            X-Rate-Limit-Reset:
              type: string
              format: date-time
        '500':
          $ref: '#/responses/Standard500ErrorResponse'
        default:
          $ref: '#/responses/TotallyUnexpectedResponse'
      
definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
        pattern: '[a-z0-9]{8,64}'
        minLength: 8
        maxLength: 64
      dateOfBirth:
        type: string
        format: date
      lastTimeOnline:
        type: string
        format: date-time
        readOnly: true
      avatarBase64PNG:
        type: string
        format: byte
        default: data:image/png;base64,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
      spokenLanguages:
        $ref: '#/definitions/SpokenLanguages'
  SpokenLanguages:
    additionalProperties:
      type: string
    properties:
      defaultLanguage:
        type: string
        default: english
  Persons:
    required:
      - items
    properties:
      items:
        type: array
        minItems: 10
        maxItems: 100
        uniqueItems: true
        items:
          $ref: '#/definitions/Person'
  ErrorMessage:
    required:
      - longMessage
      - shortMessage
    properties:
      longMessage:
        type: string
      shortMessage:
        type: string
  MultilingualErrorMessage:
    additionalProperties:
      $ref: '#/definitions/ErrorMessage'
    properties:
      defaultLanguage:
        $ref: '#/definitions/ErrorMessage'
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: string
        enum:
          - DBERR
          - NTERR
          - UNERR
      message:
        $ref: '#/definitions/MultilingualErrorMessage'
  CollectingItem:
    discriminator: itemType
    required:
      - itemType
    properties:
      itemType:
        type: string
        enum:
          - AudioCassette
          - Vinyl
          - VHS
      imageId:
        type: string
      maxPrice:
        type: number
        format: double
        minimum: 0
        maximum: 10000
        exclusiveMinimum: true
        exclusiveMaximum: false
  Vinyl:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  VHS:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - movieTitle
        properties:
          movieTitle:
            type: string
          director:
            type: string
  AudioCassette:
    allOf:
      - $ref: '#/definitions/CollectingItem'
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string
  Paging:
    required:
      - totalItems
      - totalPages
      - pageSize
      - currentPage
    properties:
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer
  PagedPersons:
    allOf:
      - $ref: '#/definitions/Persons'
      - $ref: '#/definitions/Paging'
  PagedCollectingItems:
    allOf:
      - properties:
          items:
            type: array
            minItems: 10
            maxItems: 100
            uniqueItems: true
            items:
              $ref: '#/definitions/CollectingItem'
      - $ref: '#/definitions/Paging'
responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time
    schema:
      $ref: '#/definitions/Error'
  PersonDoesNotExistResponse:
    description: Person does not exist.
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time
  TotallyUnexpectedResponse:
    description: A totally unexpected response
    headers:
      X-Rate-Limit-Remaining:
        type: integer
      X-Rate-Limit-Reset:
        type: string
        format: date-time

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  pageSize:
    name: pageSize
    in: query
    description: Number of persons returned
    type: integer
    format: int32
    minimum: 0
    exclusiveMinimum: true
    maximum: 100
    exclusiveMaximum: false
    multipleOf: 10
    default: 20
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    default: 1
  includeNonVerifiedUsers:
    name: includeNonVerifiedUsers
    in: query
    type: boolean
    default: false
    allowEmptyValue: true
  sortPersons:
    name: sort
    in: query
    type: array
    uniqueItems: true
    minItems: 1
    maxItems: 3
    collectionFormat: pipes
    items:
      type: string
      pattern: '[-+](username|lastTimeOnline|firstname|lastname)'
    default:
      - -lastTimeOnline
      - +username
  filterItemTypes:
    name: itemType
    in: query
    type: array
    collectionFormat: multi
    uniqueItems: true
    items:
      type: string
      enum:
        - AudioCassette
        - Vinyl
        - VHS
  userAgent:
    name: User-Agent
    type: string
    in: header
    required: true
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - $ref: "#/parameters/pageSize"
       - $ref: "#/parameters/pageNumber"
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "#/definitions/Persons"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "#/definitions/Person"
      responses:
        204:
          description: Person succesfully created.
        400:
          description: Person couldn't have been created.
        500:
          $ref: "#/responses/Standard500ErrorResponse"
          
  /persons/{username}:
    parameters:
      - $ref: "#/parameters/username"
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      responses:
        200:
          description: A Person
          schema:
            $ref: "#/definitions/Person"
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      responses:
        204:
          description: Person successfully deleted.
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
          
  /persons/{username}/friends:
    parameters:
      - $ref: "#/parameters/username"
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - $ref: "#/parameters/pageSize"
       - $ref: "#/parameters/pageNumber"
      responses:
        200:
          description: A person's friends list 
          schema:
            $ref: "#/definitions/PagedPersons"
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"

  /persons/{username}/collectingItems:
    parameters:
      - $ref: "#/parameters/username"
    get:
      summary: Gets a person's collecting items list
      description: Returns a list containing all items this person is looking for. The list supports paging.
      parameters:
       - $ref: "#/parameters/pageSize"
       - $ref: "#/parameters/pageNumber"
      responses:
        200:
          description: A collected items list 
          schema:
            $ref: "#/definitions/PagedCollectingItems"
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"

definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
        pattern: "[a-z0-9]{8,64}"
        minLength: 8
        maxLength: 64
      dateOfBirth:
        type: string
        format: date
      lastTimeOnline:
        type: string
        format: date-time
        readOnly: true
      avatarBase64PNG:
        type: string
        format: byte
      spokenLanguages:
        $ref: "#/definitions/SpokenLanguages"
  
  SpokenLanguages:
    additionalProperties:
      type: string
      
  Persons:
    properties:
      items:
        type: array
        minItems: 10
        maxItems: 100
        uniqueItems: true
        items:
          $ref: "#/definitions/Person"
  
  ErrorMessage:
    properties:
      longMessage:
        type: string
      shortMessage:
        type: string
  
  MultilingualErrorMessage:
    additionalProperties:
      $ref: "#/definitions/ErrorMessage"
    properties:
      defaultLanguage:
        $ref: "#/definitions/ErrorMessage"
  
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: string
        enum:
          - DBERR
          - NTERR
          - UNERR
      message:
        $ref: "#/definitions/MultilingualErrorMessage"

  CollectingItem:
    discriminator: itemType
    required:
      - itemType
    properties:
      itemType:
        type: string
        enum:
          - Vinyl
          - VHS
      imageId:
        type: string
      maxPrice:
        type: number
        format: double
        minimum: 0
        maximum: 10000
        exclusiveMinimum: true
        exclusiveMaximum: false

  Vinyl:
    allOf:
      - $ref: "#/definitions/CollectingItem"
      - required:
          - albumName
          - artist
        properties:
          albumName:
            type: string
          artist:
            type: string

  VHS:
    allOf:
      - $ref: "#/definitions/CollectingItem"
      - required:
          - movieTitle
        properties:
          movieTitle:
            type: string
          director:
            type: string

  PagedPersonsV1:
    properties:
      items:
        type: array
        items:
          $ref: "#/definitions/Person"
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer
        
  PagedPersonsV2:
    properties:
      items:
        type: array
        items:
          $ref: "#/definitions/Person"
      paging:
        $ref: "#/definitions/Paging"

  Paging:
    properties:
      totalItems:
        type: integer
      totalPages:
        type: integer
      pageSize:
        type: integer
      currentPage:
        type: integer

  PagedPersons:
    allOf:
      - $ref: "#/definitions/Persons"
      - $ref: "#/definitions/Paging"
      
  PagedCollectingItems:
    allOf:
      - properties:
          items:
            type: array
            minItems: 10
            maxItems: 100
            uniqueItems: true
            items:
              $ref: "#/definitions/CollectingItem"
      - $ref: "#/definitions/Paging"

responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    schema:
      $ref: "#/definitions/Error"
  PersonDoesNotExistResponse:
    description: Person does not exist.

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  pageSize:
    name: pageSize
    in: query
    description: Number of persons returned
    type: integer
    format: int32
    minimum: 0
    exclusiveMinimum: true
    maximum: 100
    exclusiveMaximum: false
    multipleOf: 10
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - $ref: "#/parameters/pageSize"
       - $ref: "#/parameters/pageNumber"
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "#/definitions/Persons"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "#/definitions/Person"
      responses:
        204:
          description: Person succesfully created.
        400:
          description: Person couldn't have been created.
        500:
          $ref: "#/responses/Standard500ErrorResponse"
          
  /persons/{username}:
    parameters:
      - $ref: "#/parameters/username"
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      responses:
        200:
          description: A Person
          schema:
            $ref: "#/definitions/Person"
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      responses:
        204:
          description: Person successfully deleted.
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
          
  /persons/{username}/friends:
    parameters:
      - $ref: "#/parameters/username"
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - $ref: "#/parameters/pageSize"
       - $ref: "#/parameters/pageNumber"
      responses:
        200:
          description: A person's friends list 
          schema:
            $ref: "#/definitions/Persons"
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"

definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
  Persons:
    type: array
    items:
      $ref: "#/definitions/Person"
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: string
      message:
        type: string

responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    schema:
      $ref: "#/definitions/Error"
  PersonDoesNotExistResponse:
    description: Person does not exist.

parameters:
  username:
    name: username
    in: path
    required: true
    description: The person's username
    type: string
  pageSize:
    name: pageSize
    in: query
    description: Number of persons returned
    type: integer
  pageNumber:
    name: pageNumber
    in: query
    description: Page number
    type: integer
    
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "#/definitions/Persons"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "#/definitions/Person"
      responses:
        204:
          description: Person succesfully created.
        400:
          description: Person couldn't have been created.
        500:
          $ref: "#/responses/Standard500ErrorResponse"
          
  /persons/{username}:
    parameters:
      - name: username
        in: path
        required: true
        description: The person's username
        type: string
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      responses:
        200:
          description: A Person
          schema:
            $ref: "#/definitions/Person"
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      responses:
        204:
          description: Person successfully deleted.
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
          
  /persons/{username}/friends:
    parameters:
      - name: username
        in: path
        required: true
        description: The person's username
        type: string
    get:
      summary: Gets a person's friends
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A person's friends list 
          schema:
            $ref: "#/definitions/Persons"
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"

definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
  Persons:
    type: array
    items:
      $ref: "#/definitions/Person"
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: string
      message:
        type: string

responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    schema:
      $ref: "#/definitions/Error"
  PersonDoesNotExistResponse:
    description: Person does not exist.
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "#/definitions/Persons"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "#/definitions/Person"
      responses:
        204:
          description: Person succesfully created.
        400:
          description: Person couldn't have been created.
        500:
          $ref: "#/responses/Standard500ErrorResponse"
          
  /persons/{username}:
    parameters:
      - name: username
        in: path
        required: true
        description: The person's username
        type: string
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      responses:
        200:
          description: A Person
          schema:
            $ref: "#/definitions/Person"
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      responses:
        204:
          description: Person successfully deleted.
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
      
definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
  Persons:
    type: array
    items:
      $ref: "#/definitions/Person"
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: string
      message:
        type: string

responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    schema:
      $ref: "#/definitions/Error"
  PersonDoesNotExistResponse:
    description: Person does not exist.
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "#/definitions/Persons"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "#/definitions/Person"
      responses:
        204:
          description: Person succesfully created.
        400:
          description: Person couldn't have been created.
        500:
          $ref: "#/responses/Standard500ErrorResponse"
          
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            $ref: "#/definitions/Person"
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    delete:
      summary: Deletes a person
      description: Delete a single person identified via its username
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        204:
          description: Person successfully deleted.
        404:
          $ref: "#/responses/PersonDoesNotExistResponse"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
      
definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
  Persons:
    type: array
    items:
      $ref: "#/definitions/Person"
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: string
      message:
        type: string

responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    schema:
      $ref: "#/definitions/Error"
  PersonDoesNotExistResponse:
    description: Person does not exist.
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "#/definitions/Persons"
        500:
          $ref: "#/responses/Standard500ErrorResponse"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "#/definitions/Person"
      responses:
        204:
          description: Persons succesfully created.
        400:
          description: Persons couldn't have been created.
        500:
          $ref: "#/responses/Standard500ErrorResponse"
          
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            $ref: "#/definitions/Person"
        404:
          description: The Person does not exists.
        500:
          $ref: "#/responses/Standard500ErrorResponse"

definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
  Persons:
    type: array
    items:
      $ref: "#/definitions/Person"
  Error:
    properties:
      code:
        type: string
      message:
        type: string

responses:
  Standard500ErrorResponse:
    description: An unexpected error occured.
    schema:
      $ref: "#/definitions/Error"
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "#/definitions/Persons"
        500:
          description: An unexpected error occured.
          schema:
            $ref: "#/definitions/Error"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "#/definitions/Person"
      responses:
        204:
          description: Persons succesfully created.
        400:
          description: Persons couldn't have been created.
        500:
          description: An unexpected error occured.
          schema:
            $ref: "#/definitions/Error"          
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            $ref: "#/definitions/Person"
        404:
          description: The Person does not exists.
        500:
          description: An unexpected error occured.
          schema:
            $ref: "#/definitions/Error"
definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
  Persons:
    type: array
    items:
      $ref: "#/definitions/Person"
  Error:
    properties:
      code:
        type: string
      message:
        type: string
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "#/definitions/Persons"
        500:
          description: An unexpected error occured.
          schema:
            properties:
              code:
                type: string
              message:
                type: string
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "#/definitions/Person"
      responses:
        204:
          description: Persons succesfully created.
        400:
          description: Persons couldn't have been created.
        500:
          description: An unexpected error occured.
          schema:
            properties:
              code:
                type: string
              message:
                type: string

          
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            $ref: "#/definitions/Person"
        404:
          description: The Person does not exists.
        500:
          description: An unexpected error occured.
          schema:
            properties:
              code:
                type: string
              message:
                type: string

definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
  Persons:
    type: array
    items:
      $ref: "#/definitions/Person"
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            $ref: "#/definitions/Persons"
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            $ref: "#/definitions/Person"
      responses:
        204:
          description: Persons succesfully created.
        400:
          description: Persons couldn't have been created.
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            $ref: "#/definitions/Person"
        404:
          description: The Person does not exists.

definitions:
  Person:
    required:
      - username
    properties:
      firstName:
        type: string
      lastName:
        type: string
      username:
        type: string
  Persons:
    type: array
    items:
      $ref: "#/definitions/Person"
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            type: array
            items:
              required:
                - username
              properties:
                firstName:
                  type: string
                lastName:
                  type: string
                username:
                  type: string
    post:
      summary: Creates a person
      description: Adds a new person to the persons list.
      parameters:
        - name: person
          in: body
          description: The person to create.
          schema:
            required:
              - username
            properties:
              firstName:
                type: string
              lastName:
                type: string
              username:
                type: string
      responses:
        204:
          description: Persons succesfully created.
        400:
          description: Persons couldn't have been created.
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username.
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            required:
              - username
            properties:
              firstName:
                type: string
              lastName:
                type: string
              username:
                type: string
        404:
          description: The Person does not exists.
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            type: array
            items:
              required:
                - username
              properties:
                firstName:
                  type: string
                lastName:
                  type: string
                username:
                  type: string
  /persons/{username}:
    get:
      summary: Gets a person
      description: Returns a single person for its username
      parameters:
        - name: username
          in: path
          required: true
          description: The person's username
          type: string
      responses:
        200:
          description: A Person
          schema:
            required:
              - username
            properties:
              firstName:
                type: string
              lastName:
                type: string
              username:
                type: string
        404:
          description: The Person does not exists.
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons. The list supports paging.
      parameters:
       - name: pageSize
         in: query
         description: Number of persons returned
         type: integer
       - name: pageNumber
         in: query
         description: Page number
         type: integer
      responses:
        200:
          description: A list of Person
          schema:
            type: array
            items:
              required:
                - username
              properties:
                firstName:
                  type: string
                lastName:
                  type: string
                username:
                  type: string
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons.
      responses:
        200:
          description: A list of Person
          schema:
            type: array
            items:
              required:
                - username
              properties:
                firstName:
                  type: string
                lastName:
                  type: string
                username:
                  type: string
swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths: {}
{
    "swagger": "2.0",
    "info": {
        "version": "1.0.0",
        "title": "Simple API",
        "description": "A simple API to learn how to write OpenAPI Specification"
    },
    "schemes": [
        "https"
    ],
    "host": "simple.api",
    "basePath": "/openapi101",
    "paths": {
        "/persons": {
            "get": {
                "summary": "Gets some persons",
                "description": "Returns a list containing all persons.",
                "responses": {
                    "200": {
                        "description": "A list of Person",
                        "schema": {
                            "type": "array",
                            "items": {
                                "properties": {
                                    "firstName": {
                                        "type": "string"
                                    },
                                    "lastName": {
                                        "type": "string"
                                    },
                                    "username": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Open API Specification (fka Swagger Specification) tutorial

All these Gist files are explained on my Open API Specification (fka Swagger Specification) tutorial on API Handyman blog.

The tutorial

This tutorial is composed of several posts, here are the posts links and files used for each one:

The OpenAPI Specification

If you're a bit lost in the specification, take a look at my visual documentation: