# This file was automatically generated by documentation-and-generation.fish - all changes will be lost\n
openapi: 3.1.0
info:
  title: Booking service
  description: >-
    This API represents the booking service, which each participating institution hosting one instance of the booking service (e.g. each institution has one *device-reservation* service). All of the booking services connected through **CrossLab** will communicate with each other in order to allow cross-institution bookings.


    In this document, two words are used: *reservation* for the management of low-level devices and *bookings* for the experiment booking inkluding one or multiple devices.
    The booking service itself is build on 4 different microservices, as shown by the different tags used in this documentation. By using different micro service, scaling is easier to realise (especially when using a language like TypeScript which does not support parallel execution). The booking service as a whole should have different data bases:
     * **Device reservation database**: This database contains the low-level reservation for individual devices. The *schedule-service* will access it read-only and the *device-reservation* will access it read-write.
     * **Booking database**: This contains the database with all experiment bookings including experiments. It can be accessed read-write by *booking-frontend* and *booking-backend*.
     * **Callback-Database**: This contains all known callbacks (both registered from other services and one callbacks registered at the booking service). It should only be accessed by booking-backend.

    To facillitate communication between the different services, a message broker will be used.
  version: 1.0.0
  x-service-name: Booking Service
servers:
  - url: /v1
tags:
  - name: schedule-service
    description: The schedule service is responsible for showing the schedule of devices. It shares a database with device-reservation, but accesses it read-only. It can be scaled horizontally
  - name: booking-frontend
    description: The booking-frontend is tasked with accepting and showing experiment bookings. It itself only does minimal management, most intensive tasks (like the actual reservation of devices) are handled by the booking backend. It communicates with the backend through a message protocol. It should not be scaled horizontally.
  - name: booking-backend
    description: The booking backend handles the computation heavy tasks of the booking, like the device selection & reservation and the response to callbacks. It communicates with the frontend through a message protocol. It should be scaled horizontally.
  - name: device-reservation
    description: The device reservation service handles the actual low-level reservation of devices. Since all requests must be serialised, it must not be scaled horizontally. It exposes no public API, all communication runs through an internal message protocol.

paths:
  /schedule:
    post:
      operationId: 'schedule'
      security:
        - JWT:
          - booking
          - booking:use
      tags:
        - schedule-service
      summary: Returns the free / booked times for given experiment.
      x-optional-url: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
               - Experiment
               - Time
              properties:
                Experiment:
                  $ref: '#/components/schemas/Experiment'
                Time:
                  $ref: '#/components/schemas/Timeslot'
                Combined:
                  type: boolean
                  description: If true, show only one timetable per device instead of one for all available physical devices.
                onlyOwn:
                  type: boolean
                  description: (private) Show only devices of this institution. Give an error if a device of an other institution is requested.
      responses:
        '200':
          description: Timetable of free/booked time. If 'Combined' is set to true, an array with only one entry is returned containing the combined timetable.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  required:
                   - Device
                   - Booked
                   - Free
                  properties:
                    Device:
                      type: string
                      description: ID of the device (or * if combined).
                    Booked:
                      type: array
                      description: Array of booked times.
                      items:
                        $ref: '#/components/schemas/Timeslot'
                    Free:
                      type: array
                      description: Array of free times.
                      items:
                        $ref: '#/components/schemas/Timeslot'
        '400':
          description: onlyOwn was set, but devices not belonging to that institution were requested.
        '401':
          description: No authorisation header found.
        '403':
          description: >-
            Caller is not allowed to call this method. Usually, caller is missing required scopes.
        '404':
          description: Request contains unknown type IDs. The first unknown ID will be returned.
          content:
            application/json:
              schema:
                type: string
                description: First unknown device ID.
        '422':
          description: Request contains virtual devices and can thus not be processed.
          content:
            application/json:
              schema:
                type: string
                description: First virtual device ID.
        '500':
          description: >-
            Request could not be answered. An error string containing the reason
            will be returned.
          content:
            application/json:
              schema:
                type: string
                description: Error description.
        '503':
          description: >-
            Service is unable to respond in time, possibly overloaded. Try again in a few minutes.
  /booking:
    post:
      operationId: 'newBooking'
      security:
        - JWT:
          - booking
          - booking:use
      tags:
        - booking-frontend
      summary: Books an experiment.
      x-optional-url: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
               - Devices
               - Time
              properties:
                Devices:
                  type: array
                  description: List of devices which should be added.
                  items:
                    $ref: '#/components/schemas/Device'
                Time:
                  $ref: '#/components/schemas/Timeslot'
                Type:
                  description: Type of booking. Currently, only one type is defined, but others might follow (e.g. priority booking). If empty, 'normal' is assumed.
                  type: string
                  enum:
                   - normal
      responses:
        '200':
          description: The booking was accepted. The booking status will display whether the booking of all devices was successful.
          content:
            application/json:
              schema:
                type: object
                required:
                 - BookingID
                properties:
                  BookingID:
                    type: string
                    format: uri
                    description: ID at which the booking can be managed.
        '401':
          description: No authorisation header found.
        '403':
          description: >-
            Caller is not allowed to call this method. Usually, caller is missing required scopes.
        '500':
          description: >-
            Request could not be answered. An error string containing the reason
            will be returned.
          content:
            application/json:
              schema:
                description: Error description
                type: string
        '503':
          description: >-
            Service is unable to respond in time, possibly overloaded. Try again in a few minutes.
  /booking/{ID}:
    patch:
      operationId: 'updateBooking'
      security:
        - JWT: []
      parameters:
        - $ref: '#/components/parameters/ID'
          name: ID
          schema:
            type: string
          required: true
          description: ID of Booking
      tags:
        - booking-frontend
      summary: Allows the addition of devices to a booking (removing of devices is not supportet) or the registration of callbacks. For adding devices, the scope 'booking:use' is required.
      requestBody:
        content:
          application/json:
            schema:
              anyOf:
              -  type: object
                 description: Use this request for adding devices.
                 properties:
                    Locked:
                      type: boolean
                      description: Expresses whether the devices should be locked. Must match current status of booking.
                    Devices:
                     type: array
                     description: List of devices which should be added.
                     items:
                      $ref: '#/components/schemas/Device'
              - type: object
                description: Use this request for adding callbacks.
                properties:
                  Callback:
                    type: string
                    format: uri
                    description: Callback which should be called at changes.
        required: true
      responses:
        '200':
          description: The booking change was accepted. The booking status will display whether the booking of all devices was successful.
          content:
            application/json:
              schema:
                type: object
                required:
                  - BookingID
                properties:
                  BookingID:
                    type: string
                    format: uri
        '401':
          description: No authorisation header found.
        '403':
          description: >-
            Caller is not allowed to call this method. Usually, caller is missing required scopes.
        '404':
          description: Request contains unknown booking ID.
        '423':
          description: >-
            The booking 'locked' status and the requested locked status do not match.
        '500':
          description: >-
            Request could not be answered. An error string containing the reason
            will be returned.
          content:
            application/json:
              schema:
                type: string
                description: Error description
        '503':
          description: >-
            Service is unable to respond in time, possibly overloaded. Try again in a few minutes.
    delete:
      operationId: 'deleteBooking'
      security:
        - JWT:
          - booking
          - booking:use
      parameters:
        - $ref: '#/components/parameters/ID'
          name: ID
          schema:
            type: string
          required: true
          description: ID of Booking
      tags:
        - booking-frontend
      summary: Cancels a booking, as long as the booking was originally done by you.
      responses:
        '200':
          description: >-
            The booking was cancelled. All associated devices were released.
        '401':
          description: No authorisation header found.
        '403':
          description: >-
            Caller is not allowed to call this method. Usually, caller is missing required scopes.
        '404':
          description: Request contains unknown booking ID.
        '423':
          description: >-
            The booking is currently locked, deletion not possible.
        '500':
          description: >-
            Request could not be answered. An error string containing the reason
            will be returned.
          content:
            application/json:
              schema:
                type: string
                description: Error description
        '503':
          description: >-
            Service is unable to respond in time, possibly overloaded. Try again in a few minutes.
    get:
      operationId: 'getBooking'
      security:
        - JWT:
          - booking
          - booking:use
      parameters:
        - $ref: '#/components/parameters/ID'
          name: ID
          schema:
            type: string
          required: true
          description: ID of Booking
      tags:
      - booking-frontend
      summary: >-
        Returns whether a list of devices is currently booked for a user.
      responses:
        '200':
          description: Returns the current booking.
          content:
            application/json:
              schema:
                type: object
                required:
                 - Booking
                 - Locked
                properties:
                  Booking:
                    $ref: '#/components/schemas/Booking'
                  Locked:
                    type: boolean
                    description: Shows if the booking is in a locked status.
        '401':
          description: No authorisation header found.
        '403':
          description: >-
            Caller is not allowed to call this method. Usually, caller is missing required scopes.
        '404':
          description: Request contains unknown ID
        '500':
          description: >-
            Request could not be answered. An error string containing the reason
            will be returned.
          content:
            application/json:
              schema:
                type: string
                description: Error code
        '503':
          description: >-
            Service is unable to respond in time, possibly overloaded. Try again in a few minutes.
  /booking/{ID}/destroy:
    delete:
      operationId: 'destroyBooking'
      security:
        - JWT:
          - booking
          - booking:destroy
      parameters:
        - $ref: '#/components/parameters/ID'
          name: ID
          schema:
            type: string
          required: true
          description: ID of Booking
      tags:
        - booking-frontend
      summary: Allows selected persons (like lab manager) to remove a user booking. To avoid mistakes, this is a different path than normal delete.
      responses:
        '200':
          description: >-
            The booking was cancelled. All associated devices were released.
        '401':
          description: No authorisation header found.
        '403':
          description: >-
            Caller is not allowed to call this method. Usually, caller is missing required scopes.
        '404':
          description: Request contains unknown booking ID.
        '423':
          description: >-
            The booking is currently locked, deletion not possible.
        '500':
          description: >-
            Request could not be answered. An error string containing the reason
            will be returned.
          content:
            application/json:
              schema:
                type: string
                description: Error description
        '503':
          description: >-
            Service is unable to respond in time, possibly overloaded. Try again in a few minutes.
  /booking/{ID}/lock:
    put:
      operationId: 'lockBooking'
      security:
        - JWT:
          - booking
          - booking:use
      parameters:
        - $ref: '#/components/parameters/ID'
          name: ID
          schema:
            type: string
          required: true
          description: ID of Booking
      tags:
      - booking-backend
      summary: >-
        Locks the current booking so the devices can be used. This sets the status to "active" This means that the booking can not be cancelled or (currently not implemented) the end time can not be set to a prior time. If called multiple times, the booking will be locked only once.
      responses:
        '200':
          description: All devices were booked by user.
          content:
            application/json:
              schema:
                type: array
                description: The list of booked devices and selected real devices. Order is guaranteed to be the same as in the booking.
                items:
                  type: object
                  required:
                    - Requested
                    - Selected
                  properties:
                    Requested:
                      type: string
                      format: uri
                    Selected:
                      type: string
                      format: uri
        '401':
          description: No authorisation header found.
        '403':
          description: >-
            Caller is not allowed to call this method. Usually, caller is missing required scopes.
        '404':
          description: Request contains unknown ID
        '412':
          description: The current booking status is not correct.
        '500':
          description: >-
            Request could not be answered. An error string containing the reason
            will be returned.
          content:
            application/json:
              schema:
                type: string
                description: Error string
        '503':
          description: >-
            Service is unable to respond in time, possibly overloaded. Try again in a few minutes.
    delete:
      operationId: 'unlockBooking'
      security:
        - JWT:
          - booking
          - booking:use
      parameters:
        - $ref: '#/components/parameters/ID'
          name: ID
          schema:
            type: string
          required: true
          description: ID of Booking
      tags:
      - booking-backend
      summary: >-
        Unlocks all devices belonging to a booking, status will be set to 'booked'.
      responses:
        '200':
          description: Unlocking was successful.
        '401':
          description: No authorisation header found.
        '403':
          description: >-
            Caller is not allowed to call this method. Usually, caller is missing required scopes.
        '404':
          description: Request contains unknown ID
        '412':
          description: The current booking status is not correct.      
        '500':
          description: >-
            Request could not be answered. An error string containing the reason
            will be returned.
          content:
            application/json:
              schema:
                type: string
                description: Error description.
        '503':
          description: >-
            Service is unable to respond in time, possibly overloaded. Try again in a few minutes.
  /booking_callback/{ID}:
    post:
      operationId: 'bookingCallback'
      security:
        - JWT: []
      parameters:
        - $ref: '#/components/parameters/ID'
          name: ID
          schema:
            type: string
          required: true
          description: ID of Booking
      tags:
      - booking-backend
      summary: >-
        Callback used for updating device info / booking info.
      responses:
        '200':
          description: Update was processed.
        '404':
          description: Callback is no longer needed.
        '500':
          description: >-
            Request could not be answered. An error string containing the reason
            will be returned.
          content:
            application/json:
              schema:
                type: string
                description: Error description.
        '503':
          description: >-
            Service is unable to respond in time, possibly overloaded. Try again in a few minutes.
components:
  parameters:
    ID:
      in: path
      name: ID
      description: String ID without any specified strcture. Only needed because the validator at the time of writing can not handle inline validation (e.g. ensure that a string extracted from a path is a string).
      schema:
        type: string
      required: true
  schemas:
    Booking:
      title: Booking
      description: A booking in the booking system.
      type: object
      required:
        - ID
        - Time
        - Devices
        - Status
        - You
        - External
      properties:
        ID:
          type: string
          format: uri
          description: Unique ID of the booking.
        Time:
          $ref: '#/components/schemas/Timeslot'
        Devices:
          type: array
          items:
            type: string
            format: uri
        Type:
          description: Type of booking. Currently, only one type is defined, but others might follow (e.g. priority booking). If empty, 'normal' is assumed.
          type: string
          enum:
            - normal
        Status:
          description: Current status of the booking. While the booking is pending, it can not be used. Will change automatically and can not be set by user. 'rejected' is set when the initial booking failed, 'cancelled' when the booking was deleted / cancelled after it was once active. The 'active-*' will be used when a device was added after the booking was locked.
          type: string
          enum:
            - pending
            - booked
            - rejected
            - cancelled
            - active
            - active-pending
            - active-rejected
        You:
          type: boolean
          description: If true, this booking was done by you.
        External:
          type: boolean
          description: Shows whether the booking was done by an external institution.
        Message:
          type: string
          description: User readable notes about the status of the booking (e.g. if devices are unknown).
    Device:
      title: Device
      description: A device might either be a physical/virtual device or a group of device.
      type: object
      required:
        - ID
      properties:
        ID:
          type: string
          description: Unique ID of the device. Contains the institution (by having an end point at that institution)
          format: uri
    Experiment:
      title: Experiment
      description: An experiment describes a set of devices and how they should be connected (potentially among other metadata).
      type: object
      required:
        - Devices
      properties:
        Devices:
          type: array
          description: List of devices used in experiment.
          items:
            $ref: '#/components/schemas/Device'
        Description:
          type: string
          description: User provided description, for example might be a reason for the booking (e.g. maintenance) or a link to the experiment. Might be empty or missing.
    Timeslot:
      title: Timeslot
      description: A time slot represents a slice of time used for bookings.
      type: object
      required:
        - Start
        - End
      properties:
        Start:
          type: string
          description: Start time of the booking.
          format: date-time
        End:
          type: string
          description: End time of the booking.
          format: date-time
  securitySchemes:
    JWT:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |-
        As this is the API description of the internal Device API, the only supported security schema is the JWT bearer token.
        This token will be populated by the API Gateway.
        To learn about the general Authentification scheme, please refer to the [Authentication section](https://cross-lab-project.github.io/crosslab/backend.html#authentification) in the CrossLab architecture description.
