openapi: 3.0.2
info:
  title: adaptor:ex RESTful API
  version: 0.0.2
  description: |
    RESTful API for adaptor:ex. Access, create and modify adaptor games.

    Take a look at [this tutorial](https://docs.adaptorex.org/tutorials/server-setup) to find out how to setup an adaptor.ex server.

    On **Security**: You can protect API endpoints with [basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication). 
    This is by no means the safest authentication procedure but it is all there is for now. 

    We recommend to view it rather as a way of user administration then actual security.

    For basic auth to be effective make sure to only allow https access to your server.

    adaptor:ex provides user roles which are defined in the security `basicAuth` schema. See the [Server Readme]( https://gitlab.com/machina_ex/adaptor_ex/adaptor_ex_server/-/blob/main/README.md?ref_type=heads#secure-with-user-authentication) for details. 

    Endpoints that don't define security roles are open for all users.
  license:
    name: MIT
    url: "https://mit-license.org/"
  contact:
    name: tech@machinaex.de
    url: "https://docs.adaptorex.org"
servers:
  # basic authentication might be enabled
  - url: "{protocol}://{domain}:{port}/api"
    description: Custom server
    variables:
      protocol:
        enum: ["http", "https"]
        default: "http"
      domain:
        default: "localhost"
      port:
        default: "8081"
  - url: "https://server.test.adaptorex.org/api"
    description: Adaptor Development server
tags:
  - name: root
    description: adaptor:ex main features, relevant to all games
  - name: user
    description: organize users and user sessions
  - name: game
    description: interact with a game
  - name: files
    description: >
      manage game media files and directories. 
      List, upload, download, copy, move/rename files and create directories.
  - name: level
    description: get level data, create and modify levels
  - name: state
    description: get levels state data, create and modify states
  - name: schema
    description: get json schema architecture data
  - name: session
    description: get, launch and cancel sessions
  - name: plugin
    description: add and remove plugins and get information about active plugins
  - name: plugin items
    description: add and remove plugins and get information about active plugins
  - name: collection
    description: >
      add and remove data collections and create, update and remove 
      data collection documents.
  - name: items
    description: combined plugin and data collection items endpoint
  - name: history
    description: archive and restore documents and create and restore revisions.
paths:
  /info:
    get:
      tags:
        - root
      summary: get information about the running server instance
      operationId: getInfo
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  name:
                    type: string
                    description: Name of the npm package.
                  version:
                    type: string
                    description: Current installed version of the package.
                  description:
                    type: string
                    description: Short description of the package.
                  homepage:
                    type: string
                    format: uri
                    description: URL to the package's homepage.
                  repository:
                    type: object
                    properties:
                      type:
                        type: string
                        description: Type of repository (e.g., git).
                      url:
                        type: string
                        format: uri
                        description: URL to the repository.
                    required:
                      - type
                      - url
                  license:
                    type: string
                    description: License of the package.
                  latestVersion:
                    type: string
                    description: Latest version available in the npm registry.
                  updateAvailable:
                    type: boolean
                    description: Indicates if an update is available.
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
  /config:
    get:
      tags:
        - root
      summary: get adaptor config
      operationId: getConfig
      security:
        - basicAuth: [admin]
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                    description: url shows plugins where to find the adaptor in the internet
                  host:
                    type: string
                    default: http://localhost
                  port:
                    type: integer
                    default: 8080
                  database:
                    type: object
                    description: database connection setup. NeDB requires files property, MongoDB requires url property.
                    properties:
                      type:
                        type: string
                        enum: ["nedb", "mongodb"]
                      url:
                        type: string
                        default: "mongodb://localhost:27017?replicaSet=adaptor-repl"
                  level:
                    type: string
                    description: current log level
                    enum: [error, warn, info, debug, trace]
                  users:
                    type: array
                    items:
                      $ref: "#/components/schemas/user"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
  /plugins:
    get:
      tags:
        - root
        - plugin
      summary: get available plugins
      description: |
        get a list of all plugins that may be installed by games.
        Contains information about the plugins module package.

        No security rules since not sensitive information and is required by games.
      operationId: getPlugins
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  name:
                    type: string
                    description: name reference for use in adaptor:ex API calls
                  package_name:
                    type: string
                    description: original NPM package name
                  source:
                    type: string
                    enum: ["local", "npm", "internal"]
                    description: source of plugin.
                  installed:
                    type: boolean
                    description: true if plugin is installed
                  title:
                    type: string
                    description: Plugin display title
                  version:
                    type: string
                  description:
                    type: string
                  main:
                    type: string
                    description: entry file
                  path:
                    type: string
                    description: path of directory in server file system (local and internal plugins only)
                  homepage:
                    type: string
                    description: web address of plugin documentation
                  license:
                    type: string
                  dependencies:
                    type: object
                    additionalProperties:
                      type: string
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
  /user:
    get:
      tags:
        - root
        - user
      summary: get user list (NOT IMPLEMENTED)
      security:
        - basicAuth: [admin]
      operationId: getUser
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/user"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
    post:
      tags:
        - root
        - user
      summary: create a new user (NOT IMPLEMENTED)
      description: creates a new user that can login to this adaptor editor
      security:
        - basicAuth: [admin]
      operationId: createUser
      requestBody:
        description: user properties
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/user"
      responses:
        201:
          $ref: "#/components/responses/201Created"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        400:
          $ref: "#/components/responses/400Invalid"
  /me:
    get:
      tags:
        - root
        - user
      summary: get information about the current user
      operationId: getMe
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/user"
        401:
          $ref: "#/components/responses/401Unauthorized"
    put:
      tags:
        - root
        - user
      summary: change my user data (NOT IMPLEMENTED)
      operationId: updateMe
      requestBody:
        description: modified user data
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/user"
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
  /games:
    get:
      tags:
        - root
        - game
      summary: get list of existing games
      operationId: getGames
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/game_preview"
        401:
          $ref: "#/components/responses/401Unauthorized"
  /game:
    post:
      tags:
        - root
        - game
      summary: create a new game
      description: creates a new game and database or loads game from an existing database
      security:
        - basicAuth: [admin]
      operationId: createGame
      requestBody:
        description: game properties
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                template:
                  type: string
                  enum: ["basic", "multiplayer", "openworld"]
      responses:
        201:
          $ref: "#/components/responses/201Created"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
  /game/{game}:
    parameters:
      - $ref: "#/components/parameters/game"
    get:
      tags:
        - game
      summary: get game data overview
      description: preview data describing the game.
      operationId: getGame
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/game"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
    delete:
      tags:
        - game
      description: delete game with name
      security:
        - basicAuth: [admin, owner]
      operationId: deleteGame
      responses:
        204:
          description: game delete successful
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/setup:
    parameters:
      - $ref: "#/components/parameters/game"
    post:
      tags:
        - game
      summary: edit game setup
      description: >
        change game setup elements.
      deprecated: true
      security:
        - basicAuth: [admin, owner, developer]
      operationId: editGameSetup
      requestBody:
        description: update values
        content:
          application/json:
            schema:
              type: object
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/_event:
    parameters:
      - $ref: "#/components/parameters/game"
    post:
      tags:
        - game
      summary: dispatch global game event
      operationId: gameEvent
      requestBody:
        description: event name and payload.
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: event name
                payload:
                  description: the event payload data. Is optional and may be of any type.
      responses:
        200:
          $ref: "#/components/responses/200Executed"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/media:
    parameters:
      - $ref: "#/components/parameters/game"
    get:
      tags:
        - game
      summary: get list of media files
      operationId: getMedia
      deprecated: true
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/files:
    parameters:
      - $ref: "#/components/parameters/game"
    get:
      tags:
        - files
      summary: list files and directories
      description: >
        Returns the contents of the root file directory for this game.
        Use the `path` query parameter to list the contents of a subdirectory.
        Each entry indicates whether it is a file or a directory.
      operationId: listFiles
      parameters:
        - name: path
          in: query
          required: false
          description: >
            Subdirectory path to list. Omit to list the root directory.
            Example: `audio/voice-messages`
          schema:
            type: string
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/file"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
    post:
      tags:
        - files
      summary: upload one or more files
      description: >
        Upload a file to the game's file storage.
        Use the `path` query parameter to place the file into a subdirectory.
        If the target directory does not exist it will be created automatically.
        Uploading a file with the same name as an existing file will replace it.
      operationId: uploadFiles
      security:
        - basicAuth: [admin, owner, developer, author]
      parameters:
        - name: path
          in: query
          required: false
          description: >
            Target directory path. Omit to upload to the root directory.
            Example: `images/avatars`
          schema:
            type: string
        - name: extract
          in: query
          required: false
          description: >
            Wether to extract .zip archives after upload
            Example: `true`
          schema:
            type: boolean
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - files
              properties:
                files:
                  type: array
                  items:
                    type: string
                    format: binary
                  description: One or more files to upload.
                  minItems: 1
      responses:
        201:
          $ref: "#/components/responses/201UploadDone"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/files/{path}:
    parameters:
      - $ref: "#/components/parameters/game"
      - name: path
        in: path
        required: true
        description: >
          Path to the file, including filename or directory.
        example: "images/characters/ada.png"
        schema:
          type: string
    post:
      tags:
        - files
      summary: create a directory
      description: >
        Creates a new directory at the specified path.
        Intermediate parent directories are created automatically if they do not exist.
        Does nothing if the directory already exists.
      operationId: createDirectory
      security:
        - basicAuth: [admin, owner, developer, author]
      responses:
        201:
          $ref: "#/components/responses/201Created"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
    get:
      tags:
        - files
      summary: download a file
      description: Returns the raw file content with the appropriate MIME type.
      operationId: downloadFile
      responses:
        200:
          description: file content
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
    delete:
      tags:
        - files
      summary: delete a file or directory
      description: Permanently deletes a file or a directory. This action cannot be undone.
      operationId: deleteFile
      security:
        - basicAuth: [admin, owner, developer, author]
      responses:
        204:
          description: file or directory delete successful
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/files/{path}/_copy:
    parameters:
      - $ref: "#/components/parameters/game"
      - name: path
        in: path
        required: true
        description: >
          Full path to the source file or directory. Example: `images/ada.png`
        schema:
          type: string
    post:
      tags:
        - files
      summary: copy a file
      description: >
        Copies a file or all files in a directory to a new location. The source file is kept unchanged.
        If a file already exists at the destination it will be overwritten.
      operationId: copyFile
      security:
        - basicAuth: [admin, owner, developer, author]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - destination
              properties:
                destination:
                  type: string
                  description: >
                    Target path including the desired filename.
                  example: "images/characters/ada_copy.png"
      responses:
        201:
          $ref: "#/components/responses/201Created"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/files/{path}/_move:
    parameters:
      - $ref: "#/components/parameters/game"
      - name: path
        in: path
        required: true
        description: >
          Full path to the source file or directory. Example: `images/ada.png`
        schema:
          type: string
    post:
      tags:
        - files
      summary: move or rename a file or directory
      description: >
        Moves a file or directory to a new path, which also serves as a rename operation
        when the directory part of the path stays the same.
        If a file already exists at the destination it will be overwritten.
      operationId: moveFile
      security:
        - basicAuth: [admin, owner, developer, author]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - destination
              properties:
                destination:
                  type: string
                  description: >
                    Target path including the desired filename if it's a file.
                  example: "images/characters/ada_renamed.png"
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/files/{path}/_publish:
    parameters:
      - $ref: "#/components/parameters/game"
      - name: path
        in: path
        required: true
        description: >
          Full path to the file or directory. Example: `images/ada.png`
        schema:
          type: string
    post:
      tags:
        - files
      summary: make a file or directory publicly available
      description: >
        Creates a symlink in the public file directory to the specified file or directory.
        If path is a directory all files in that directory will be public even if they are added later.
      operationId: publishFile
      security:
        - basicAuth: [admin, owner, developer, author]
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/files/{path}/_unpublish:
    parameters:
      - $ref: "#/components/parameters/game"
      - name: path
        in: path
        required: true
        description: >
          Full path to the file or directory. Example: `images/ada.png`
        schema:
          type: string
    post:
      tags:
        - files
      summary: remove a file or directory from the public files directory.
      description: >
        Removes the symlink in the public file directory to the specified file or directory.
        If path is a directory none of the files in that directory will be public anymore.
      operationId: unpublishFile
      security:
        - basicAuth: [admin, owner, developer, author]
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/level:
    parameters:
      - $ref: "#/components/parameters/game"
    post:
      tags:
        - level
      summary: create new level
      description: If only name (required) is provided, a default level will be created as described in "#/components/schemas/level/default"
      security:
        - basicAuth: [admin, owner, developer, author]
      operationId: createLevel
      requestBody:
        description: level properties
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/level"
      responses:
        201:
          $ref: "#/components/responses/201Created"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
    get:
      tags:
        - level
      summary: find levels by using query parameters
      description: |
        omit parameters to get all the levels or use _sort_by parameter to get a sorted list of levels that match the query

        Use `_archived=true` to get levels that have been archived.
      operationId: findLevel
      parameters:
        - name: name
          in: query
          schema:
            type: string
        - $ref: "#/components/parameters/archived"
        - $ref: "#/components/parameters/sort_by"
        - $ref: "#/components/parameters/sort_direction"
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/skip"
        - $ref: "#/components/parameters/cast_types_false"
        - $ref: "#/components/parameters/params"
      responses:
        200:
          description: level data
          content:
            application/json:
              schema:
                type: array
                items:
                  # sollten hier auch nur die previews zurückgegeben werden?
                  $ref: "#/components/schemas/level"
        401:
          $ref: "#/components/responses/401Unauthorized"
  /game/{game}/level/{level}:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/level"
    get:
      tags:
        - level
      summary: get level data
      operationId: getLevel
      parameters:
        - $ref: "#/components/parameters/archived"
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/level"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
    put:
      tags:
        - level
      summary: update level data
      description: >
        Replace level document. Make sure to include created_at, created_by and created_with properties otherwise they are lost.
        Known Bug: If you use name as identification, updating the name property will lead to missing modification information
      security:
        - basicAuth: [admin, owner, developer, author]
      operationId: updateLevel
      requestBody:
        description: modified level data
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/level"
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
    delete:
      tags:
        - level
      summary: permanently delete level
      description: |
        Will delete active levels and levels that have been moved to archive. Deleted levels can not be restored.

        For active levels this will cancel all it's sessions and delete all level revisions.
      security:
        - basicAuth: [admin, owner, developer]
      operationId: deleteLevel
      responses:
        204:
          description: level delete successful
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/level/{level}/_archive:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/level"
    post:
      tags:
        - level
        - history
      summary: move level to archive
      description: |
        Level will be removed from levels collection and moved to levels_archive collection.

        Archive operation will cancel all Sessions for this level and delete all revisions.
      operationId: archiveLevel
      security:
        - basicAuth: [admin, owner, developer, author]
      responses:
        200:
          description: archive level successful
          $ref: "#/components/responses/200Executed"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/level/{level}/_restore:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/level"
    post:
      tags:
        - level
        - history
      summary: restore archived level
      operationId: restoreLevel
      security:
        - basicAuth: [admin, owner, developer, author]
      responses:
        201:
          description: restore level successful
          $ref: "#/components/responses/201Created"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/level/{level}/{operator}:
    post:
      tags:
        - level
      summary: edit level using update operator
      description: >
        Known Bug: If you use name as identification, updating the name property will lead to missing modification information
      security:
        - basicAuth: [admin, owner, developer, author]
      operationId: editLevel
      parameters:
        - $ref: "#/components/parameters/game"
        - $ref: "#/components/parameters/level"
        - $ref: "#/components/parameters/operator"
      requestBody:
        description: update values
        content:
          application/json:
            schema:
              type: object
              example:
                name: newName
                config.arguments.Player.query: "{name:'Testplayer'}"
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/level/{level}/revision:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/level"
    get:
      tags:
        - level
        - history
      summary: get level revisions
      operationId: findLevelRevisions
      description: |
        omit parameters to get all the level revisions or use additional parameters to get a filtered list. Use _sort_by to get a sorted list of level revisions that match the query.
        To get the latest revision of a level, use 

        `/game/{game}/level/{level}/revision/?_sort_by=id&_sort_direction=-1&_limit=1`
      parameters:
        - name: name
          in: query
          schema:
            type: string
        - name: id
          in: query
          schema:
            type: integer
        - $ref: "#/components/parameters/sort_by"
        - $ref: "#/components/parameters/sort_direction"
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/skip"
        - $ref: "#/components/parameters/cast_types_false"
        - $ref: "#/components/parameters/params"
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/level"
        400:
          $ref: "#/components/responses/400Invalid"
        404:
          $ref: "#/components/responses/404NotFound"
    post:
      tags:
        - level
        - history
      summary: create new level revision
      description: Makes a copy of the current level in the level history database. Add name and or description to identify the revision
      operationId: createLevelRevision
      security:
        - basicAuth: [admin, owner, developer, author]
      requestBody:
        description: Revision infos
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: optional name property to identify revision. Response 400 ,"DuplicateError" if name is not unique
                description:
                  type: string
      responses:
        201:
          $ref: "#/components/responses/201Created"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
  /game/{game}/level/{level}/revision/_delete:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/level"
    post:
      tags:
        - level
        - history
      summary: batch delete level revisions via query
      description: |
        omit parameters to delete all the level revisions or use additional parameters to delete based on a filtered list. Use _sort_by to get a sorted list of level revisions that match the query.
        To delete all but keep the 10 latest revision of a level, use 

        `/game/{game}/level/{level}/revision/_delete?_sort_by=id&_sort_direction=-1&_skip=10`

        Operation will not fail if no revisions match the query.
      operationId: findAndDeleteLevelRevisions
      security:
        - basicAuth: [admin, owner, developer, author]
      parameters:
        - name: name
          in: query
          schema:
            type: string
        - name: id
          in: query
          schema:
            type: integer
        - $ref: "#/components/parameters/sort_by"
        - $ref: "#/components/parameters/sort_direction"
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/skip"
        - $ref: "#/components/parameters/cast_types_false"
        - $ref: "#/components/parameters/params"
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: string
                example: "2 revisions deleted for level MyLevel'"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
  /game/{game}/level/{level}/revision/{level_revision}:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/level"
      - $ref: "#/components/parameters/level_revision"
    get:
      tags:
        - level
        - history
      summary: get level data of a specific revision
      operationId: getLevel
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/level"
        400:
          $ref: "#/components/responses/400Invalid"
        404:
          $ref: "#/components/responses/404NotFound"
    delete:
      tags:
        - level
        - history
      summary: delete level revision
      operationId: deleteLevelRevision
      security:
        - basicAuth: [admin, owner, developer, author]
      responses:
        204:
          description: level revision delete successful
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/level/{level}/revision/{level_revision}/_restore:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/level"
      - $ref: "#/components/parameters/level_revision"
    post:
      tags:
        - level
        - history
      summary: restore level revision
      description: Overwrite the current level with the level revision
      operationId: restoreLevelRevision
      security:
        - basicAuth: [admin, owner, developer, author]
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/level"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/level/{level}/variables:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/level"
    get:
      tags:
        - level
      summary: get variables and functions of level context
      operationId: getLevelVariables
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  level_attributes:
                    type: array
                    example: ["[[name]]", "[[_id]]", "[[custom_attribute]]"]
                    items:
                      type: string
                  level_arguments:
                    type: array
                    example: ["[[Player]]", "[[Player.name]]"]
                    items:
                      type: string
                  plugin_items:
                    type: array
                    example:
                      [
                        "[[devices]]",
                        "[[devices.http]]",
                        "[[devices.http.mydevice.settings]]"
                      ]
                    items:
                      type: string
                  action_data:
                    type: array
                    example:
                      [
                        "[[state]]",
                        "[[state.StateName]]",
                        "[[state.StateName.onEvent]]",
                        "[[state.StateName.onEvent.match]]"
                      ]
                    items:
                      type: string
                  functions:
                    type: array
                    example: ["[[function]]", "[[function.getDate()]]"]
                    items:
                      type: string
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/level/{level}/states:
    # might be obsolete since states are in level GET and are pretty useless without actions and contents
    get:
      tags:
        - level
        - state
      summary: get list of level states (This is not implemented because it probably has no use)
      deprecated: true
      parameters:
        - $ref: "#/components/parameters/game"
        - $ref: "#/components/parameters/level"
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/state"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/level/{level}/state:
    post:
      tags:
        - state
        - level
      summary: create new state
      security:
        - basicAuth: [admin, owner, developer, author]
      operationId: createState
      parameters:
        - $ref: "#/components/parameters/game"
        - $ref: "#/components/parameters/level"
      requestBody:
        description: create new states, actions and contents. Use existing state id to replace existing state.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/states"
      responses:
        200:
          $ref: "#/components/responses/200StateUpdate"
        201:
          $ref: "#/components/responses/201StateCreated"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
  /game/{game}/level/{level}/state/{state}:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/level"
      - $ref: "#/components/parameters/state"
    get:
      tags:
        - level
        - state
      summary: get state data (not implemented yet)
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/state"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
    put:
      tags:
        - level
        - state
      summary: replace state data
      security:
        - basicAuth: [admin, owner, developer, author]
      operationId: updateState
      requestBody:
        description: modified state data
        content:
          application/json:
            schema:
              type: object
              description: state properties, action and content elements of a selected state
              properties:
                state:
                  $ref: "#/components/schemas/state"
                actions:
                  type: object
                  additionalProperties:
                    $ref: "#/components/schemas/action"
                contents:
                  type: object
                  additionalProperties:
                    $ref: "#/components/schemas/content"
      responses:
        200:
          $ref: "#/components/responses/200StateUpdate"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
    delete:
      tags:
        - level
        - state
      summary: delete state with id
      security:
        - basicAuth: [admin, owner, developer, author]
      operationId: deleteState
      responses:
        200:
          $ref: "#/components/responses/200StateUpdate"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/level_schema:
    get:
      tags:
        - level
        - schema
        - game
      summary: get current game level schema
      description: >
        each level has to validate against this schema. All plugin action and 
        listener schemas are merged inside. It may change and you can subscribe 
        to changes. See ./asyncapi.yaml.
      operationId: getLevelSchema
      parameters:
        - $ref: "#/components/parameters/game"
      responses:
        200:
          description: successful. Response content-length might well be > 50000
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/meta_schema"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/actions:
    parameters:
      - $ref: "#/components/parameters/game"
    get:
      tags:
        - schema
        - game
      summary: get schemas of all actions currently available
      description: >
        Omit query parameters to get all actions available. 
        Use query parameters to get a single action or all actions of a plugin.
      operationId: getActions
      parameters:
        - name: action
          in: query
          schema:
            type: string
        - name: plugin
          in: query
          schema:
            type: string
        - $ref: "#/components/parameters/sort_by"
        - $ref: "#/components/parameters/sort_direction"
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/skip"
        - $ref: "#/components/parameters/cast_types_false"
        - $ref: "#/components/parameters/params"
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/action_schema"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/session:
    parameters:
      - $ref: "#/components/parameters/game"
    post:
      tags:
        - session
      summary: launch new session
      operationId: launchSession
      security:
        - basicAuth: [admin, owner, developer, author, operator]
      requestBody:
        description: session properties
        content:
          application/json:
            schema:
              type: object
              required: ["level"]
              properties:
                name:
                  type: string
                  description: optional name property to identify session
                level:
                  type: string
                  description: level name or _id the session is based on
                arguments:
                  $ref: "#/components/schemas/arguments"
      responses:
        201:
          $ref: "#/components/responses/201Created"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
    get:
      tags:
        - session
      summary: find sessions by using query parameters
      description: |
        omit parameters to get all active sessions or use _sort_by parameter to get 
        a sorted list of sessions that match the query

        Use `_archived=true` to get sessions that have been canceled.
      operationId: findSessions
      parameters:
        - name: name
          in: query
          schema:
            type: string
        - name: level
          description: level _id
          in: query
          schema:
            type: string
        - name: level_name
          description: level name property
          in: query
          schema:
            type: string
        - $ref: "#/components/parameters/archived"
        - $ref: "#/components/parameters/sort_by"
        - $ref: "#/components/parameters/sort_direction"
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/skip"
        - $ref: "#/components/parameters/cast_types_false"
        - $ref: "#/components/parameters/params"
      responses:
        200:
          description: session data
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/session"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/session/{session}:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/session"
    get:
      tags:
        - session
      summary: get session data
      operationId: getSession
      parameters:
        - $ref: "#/components/parameters/archived"
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/session"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
    delete:
      tags:
        - session
      summary: delete canceled session
      description: >
        Will cancel and delete active sessions or delete sessions that have been canceled and moved to archive. Deleted sessions can not be restored.
      operationId: deleteSession
      security:
        - basicAuth: [admin, owner, developer]
      responses:
        204:
          description: session delete successful
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/session/{session}/_cancel:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/session"
    post:
      tags:
        - session
        - history
      summary: cancel session
      operationId: cancelSession
      security:
        - basicAuth: [admin, owner, developer, author, operator]
      responses:
        200:
          description: session cancel successful
          $ref: "#/components/responses/200Executed"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/session/{session}/_restore:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/session"
    post:
      tags:
        - session
        - history
      summary: restore canceled session
      operationId: restoreSession
      security:
        - basicAuth: [admin, owner, developer, author, operator]
      responses:
        200:
          description: session restore successful
          $ref: "#/components/responses/200Executed"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/session/{session}/_next:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/session"
    post:
      tags:
        - session
      summary: cue next state
      operationId: next
      security:
        - basicAuth: [admin, owner, developer, author, operator]
      requestBody:
        description: state identification query. Use either name or id.
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                name:
                  type: string
                id:
                  type: string
      responses:
        200:
          $ref: "#/components/responses/200Executed"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin:
    parameters:
      - $ref: "#/components/parameters/game"
    post:
      tags:
        - plugin
      summary: add plugin to palette
      security:
        - basicAuth: [admin, owner, developer]
      operationId: addPlugin
      requestBody:
        description: plugin name
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  # maybe have an enum with all available plugins that can be references here?
                  type: string
      responses:
        201:
          description: plugin added successfully
          content:
            text/plain:
              schema:
                type: boolean
                # maybe return whole path instead, or both?
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
    get:
      tags:
        - plugin
        - schema
      summary: find plugin by using query parameters
      description: >
        omit parameters to get all the plugins or use _sort_by parameter to get 
        a sorted list of plugins that match the query
      security:
        - basicAuth: [admin, owner, developer]
      operationId: findPlugins
      parameters:
        - name: name
          in: query
          schema:
            type: string
        - $ref: "#/components/parameters/sort_by"
        - $ref: "#/components/parameters/sort_direction"
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/skip"
        - $ref: "#/components/parameters/cast_types_false"
        - $ref: "#/components/parameters/params"
      responses:
        200:
          description: plugin data
          content:
            application/json:
              schema:
                type: array
                items:
                  # sollten hier auch nur die previews zurückgegeben werden?
                  $ref: "#/components/schemas/plugin"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
    get:
      tags:
        - plugin
        - schema
      summary: get plugin settings and items
      security:
        - basicAuth: [admin, owner, developer]
      operationId: getPlugin
      description: Plugin contains schemas for settings and collections. Schemas might change. You can subscribe to changes via socket, see ./asyncapi.yaml
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/plugin"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
    delete:
      tags:
        - plugin
      summary: remove plugin from game
      description: This deletes all the items and settings!
      security:
        - basicAuth: [admin, owner, developer]
      operationId: removePlugin
      responses:
        204:
          description: plugin remove successful
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/settings:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
    put:
      tags:
        - plugin
      summary: update plugin settings
      description: >
        Replace plugin settings
      operationId: updatePluginSettings
      security:
        - basicAuth: [admin, owner, developer]
      requestBody:
        description: modified plugin settings data
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/plugin/properties/settings/properties/data"
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/_load:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
    post:
      tags:
        - plugin
      summary: load plugin setup and data
      security:
        - basicAuth: [admin, owner, developer]
      operationId: loadPlugin
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/plugin"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/_connect:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
    post:
      tags:
        - plugin
      summary: connect plugin
      security:
        - basicAuth: [admin, owner, developer]
      operationId: connectPlugin
      requestBody:
        description: plugin item settings. If omitted connects with current settings.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/plugin/properties/settings"
      responses:
        200:
          $ref: "#/components/responses/200Connect"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/_disconnect:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
    post:
      tags:
        - plugin
      summary: disconnect plugin
      security:
        - basicAuth: [admin, owner, developer]
      operationId: disconnectPlugin
      responses:
        200:
          $ref: "#/components/responses/200Connect"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/{plugin_collection}:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
      - $ref: "#/components/parameters/plugin_collection"
    post:
      tags:
        - plugin
        - plugin items
      summary: create a new item in a plugin collection
      security:
        - basicAuth: [admin, owner, developer]
      operationId: createPluginItem
      requestBody:
        description: item to be added to plugin collection
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/plugin_item"
      responses:
        201:
          $ref: "#/components/responses/201Created"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
    get:
      tags:
        - plugin
        - plugin items
      summary: find plugin items by using query parameters
      description: omit parameters to get all the items or use _sort_by parameter to get a sorted list of items that match the query
      security:
        - basicAuth: [admin, owner, developer]
      operationId: findPluginItems
      parameters:
        - name: name
          in: query
          schema:
            type: string
        - $ref: "#/components/parameters/sort_by"
        - $ref: "#/components/parameters/sort_direction"
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/skip"
        - $ref: "#/components/parameters/cast_types_true"
        - $ref: "#/components/parameters/params"
      responses:
        200:
          description: list of items
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/plugin_item"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/{plugin_collection}/{item}:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
      - $ref: "#/components/parameters/plugin_collection"
      - $ref: "#/components/parameters/plugin_item"
    get:
      tags:
        - plugin
        - plugin items
      summary: get plugin item data
      security:
        - basicAuth: [admin, owner, developer]
      operationId: getPluginItem
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: object
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
    delete:
      tags:
        - plugin
        - plugin items
      summary: delete plugin item
      security:
        - basicAuth: [admin, owner, developer]
      operationId: deletePluginItem
      responses:
        204:
          description: plugin item delete successful
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/{plugin_collection}/{item}/_set:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
      - $ref: "#/components/parameters/plugin_collection"
      - $ref: "#/components/parameters/plugin_item"
    post:
      tags:
        - plugin
        - plugin items
      summary: edit plugin item using update set operator
      security:
        - basicAuth: [admin, owner, developer]
      operationId: editPluginItem
      requestBody:
        description: update set values
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/plugin_item"
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/{plugin_collection}/{item}/_connect:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
      - $ref: "#/components/parameters/plugin_collection"
      - $ref: "#/components/parameters/plugin_item"
    post:
      tags:
        - plugin
        - plugin items
      summary: connect plugin item
      security:
        - basicAuth: [admin, owner, developer]
      operationId: connectPluginItem
      requestBody:
        description: plugin item settings. If omitted connects with current settings.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/plugin_item/properties/settings"
      responses:
        200:
          $ref: "#/components/responses/200Connect"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/{plugin_collection}/{item}/_disconnect:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
      - $ref: "#/components/parameters/plugin_collection"
      - $ref: "#/components/parameters/plugin_item"
    post:
      tags:
        - plugin
        - plugin items
      summary: disconnect plugin item
      security:
        - basicAuth: [admin, owner, developer]
      operationId: disconnectPluginItem
      responses:
        200:
          $ref: "#/components/responses/200Connect"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/{plugin_collection}/{item}/_load:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
      - $ref: "#/components/parameters/plugin_collection"
      - $ref: "#/components/parameters/plugin_item"
    post:
      tags:
        - plugin
        - plugin items
      summary: reload plugin item setup
      security:
        - basicAuth: [admin, owner, developer]
      operationId: loadPluginItem
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/plugin"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/plugin/{plugin}/{plugin_collection}/{item}/_{function}:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/plugin"
      - $ref: "#/components/parameters/plugin_collection"
      - $ref: "#/components/parameters/plugin_item"
      - name: function
        in: path
        description: name of plugin item function
        required: true
        schema:
          type: string
    post:
      tags:
        - plugin
        - plugin items
      summary: call plugin item function
      security:
        - basicAuth: [admin, owner, developer]
      operationId: callPluginItemFunction
      requestBody:
        description: plugin item function parameters.
        content:
          application/json:
            schema:
              type: object
      responses:
        200:
          $ref: "#/components/responses/200Executed"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/collections:
    parameters:
      - $ref: "#/components/parameters/game"
    get:
      tags:
        - collection
        - game
      summary: get schemas of all current data collections
      description: >
        Schemas are an estimation from the merge of exiting documents and data collection schema definitions by plugins
      operationId: getCollections
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: object
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/collection:
    post:
      tags:
        - collection
      summary: create a new data collection
      security:
        - basicAuth: [admin, owner, developer]
      operationId: createCollection
      parameters:
        - $ref: "#/components/parameters/game"
      requestBody:
        description: collection name
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/collection"
      responses:
        201:
          description: create successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  created_id:
                    type: string
                  db_collection_created:
                    type: boolean
                    description: true if there wasn't already a collection with that name in the database
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
  /game/{game}/collection/{collection}:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/collection"
    post:
      tags:
        - collection
      summary: create a new document in a collection
      security:
        - basicAuth: [admin, owner, developer, author]
      operationId: createDocument
      requestBody:
        description: document to be added to collection
        content:
          application/json:
            schema:
              type: object
      responses:
        201:
          $ref: "#/components/responses/201Created"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
    get:
      tags:
        - collection
      summary: find documents by using query parameters
      description: |
        omit parameters to get all the documents or use _sort_by parameter to get a sorted list of documents that match the query

        Use `_archived=true` to get levels that have been archived.
      operationId: findDocuments
      parameters:
        - name: name
          in: query
          schema:
            type: string
        - $ref: "#/components/parameters/archived"
        - $ref: "#/components/parameters/sort_by"
        - $ref: "#/components/parameters/sort_direction"
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/skip"
        - $ref: "#/components/parameters/cast_types_true"
        - $ref: "#/components/parameters/params"
      responses:
        200:
          description: list of documents
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
    delete:
      tags:
        - collection
      summary: delete data collection
      description: This deletes all the collections documents!
      security:
        - basicAuth: [admin, owner, developer]
      operationId: deleteCollection
      responses:
        204:
          description: collection delete successful
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/collection/{collection}/{document}:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/collection"
      - $ref: "#/components/parameters/document"
    get:
      tags:
        - collection
      summary: get document data
      operationId: getDocument
      parameters:
        - $ref: "#/components/parameters/archived"
      responses:
        200:
          description: successful
          content:
            application/json:
              schema:
                type: object
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
    put:
      tags:
        - collection
      summary: update collection document
      description: Returns 400 OutdatedError if original on server was updated in the meantime
      operationId: updateDocument
      security:
        - basicAuth: [admin, owner, developer, author, operator]
      requestBody:
        description: modified collection document data
        content:
          application/json:
            schema:
              type: object
              properties:
                _forceUpdate:
                  type: boolean
                  description: Replace even if modified date of original document is newer
                  default: false
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
    delete:
      tags:
        - collection
      summary: delete collection document
      security:
        - basicAuth: [admin, owner, developer]
      operationId: deleteDocument
      responses:
        204:
          description: document delete successful
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/collection/{collection}/{document}/_archive:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/collection"
      - $ref: "#/components/parameters/document"
    post:
      tags:
        - collection
        - history
      summary: move document to archive
      description: |
        Document will be removed from collection and moved to archive collection.
      operationId: archiveDocument
      security:
        - basicAuth: [admin, owner, developer, author, operator]
      responses:
        200:
          description: archive document successful
          $ref: "#/components/responses/200Executed"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/collection/{collection}/{document}/_restore:
    parameters:
      - $ref: "#/components/parameters/game"
      - $ref: "#/components/parameters/collection"
      - $ref: "#/components/parameters/document"
    post:
      tags:
        - collection
        - history
      summary: restore archived document
      operationId: restoreDocument
      security:
        - basicAuth: [admin, owner, developer, author, operator]
      responses:
        201:
          description: restore document successful
          $ref: "#/components/responses/201Created"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        403:
          $ref: "#/components/responses/403AccessDenied"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/collection/{collection}/{document}/{operator}:
    post:
      tags:
        - collection
      summary: edit document using update operator
      description: Returns 400 OutdatedError if original on server was updated in the meantime
      operationId: editDocument
      security:
        - basicAuth: [admin, owner, developer, author, operator]
      parameters:
        - $ref: "#/components/parameters/game"
        - $ref: "#/components/parameters/collection"
        - $ref: "#/components/parameters/document"
        - $ref: "#/components/parameters/operator"
      requestBody:
        description: update values
        content:
          application/json:
            schema:
              type: object
              example:
                someProperty: newValue
                some.nested.property: changedValue
      responses:
        200:
          $ref: "#/components/responses/200Update"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
  /game/{game}/items:
    parameters:
      - $ref: "#/components/parameters/game"
    get:
      tags:
        - items
      summary: get selected documents from plugin and data collections alike
      description: >
        Use query parameter to get specific documents. 'collection' and 'type' can be used to get (specific) plugin or data collections only.
        Use optional _sort_by parameter to get a sorted list of documents that match the query.
        Omit query parameter to get all the documents
      operationId: findItems
      parameters:
        - name: name
          in: query
          schema:
            type: string
        - $ref: "#/components/parameters/sort_by"
        - $ref: "#/components/parameters/sort_direction"
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/skip"
        - $ref: "#/components/parameters/cast_types_true"
        - $ref: "#/components/parameters/params"
      responses:
        200:
          description: list of documents
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/item"
        400:
          $ref: "#/components/responses/400Invalid"
        401:
          $ref: "#/components/responses/401Unauthorized"
        404:
          $ref: "#/components/responses/404NotFound"
components:
  parameters:
    user:
      name: user
      in: path
      description: user _id
      required: true
      schema:
        type: string
    game:
      name: game
      in: path
      description: name of game
      required: true
      schema:
        type: string
    level:
      name: level
      in: path
      description: level _id or name property
      required: true
      schema:
        type: string
    level_revision:
      name: level_revision
      in: path
      description: level revision id
      required: true
      schema:
        type: integer
    state:
      name: state
      in: path
      description: state id
      required: true
      schema:
        type: string
    session:
      name: session
      in: path
      description: session _id or name property
      required: true
      schema:
        type: string
    plugin:
      name: plugin
      in: path
      description: plugin name
      required: true
      schema:
        type: string
    plugin_collection:
      name: plugin_collection
      in: path
      description: name of plugin collection
      required: true
      schema:
        type: string
    plugin_item:
      name: item
      in: path
      description: name or _id of plugin item
      required: true
      schema:
        type: string
    collection:
      name: collection
      in: path
      description: name of collection
      required: true
      schema:
        type: string
    document:
      name: document
      in: path
      description: document _id or name property
      required: true
      schema:
        type: string
    params:
      name: params
      in: query
      schema:
        type: object
        default: {}
        additionalProperties:
          type: string
    operator:
      name: operator
      in: path
      description: |
        make a specific update operation.

        - **set** update the specified fields only.
        - **remove** remove the specified fields.
        - **push** add an element to an array.
        - **add** add an element to an array if it does not exist.

        You can use any [NeDB operator](https://www.npmjs.com/package/nedb#updating-documents) or if you use mongodb any [mongo update operator](https://docs.mongodb.com/manual/reference/operator/update/). Just omit the $ character.
      required: true
      schema:
        type: string
        enum:
          [
            _set,
            _remove,
            _inc,
            _min,
            _max,
            _mul,
            _rename,
            _push,
            _add,
            _pop,
            _pull,
            _pullAll
          ]
    sort_by:
      name: _sort_by
      in: query
      schema:
        type: string
    sort_direction:
      name: _sort_direction
      description: sort order. 1 means A to Z, -1 means Z to A
      in: query
      schema:
        type: integer
        enum: [-1, 1]
    limit:
      name: _limit
      description: Maximum number of entries to return. 0 returns all entries.
      in: query
      schema:
        type: integer
        minimum: 0
    skip:
      name: _skip
      description: Do not return the first n entries
      in: query
      schema:
        type: integer
        minimum: 0
    cast_types_false:
      name: _cast_types
      description: Wether or not to typecast the query parameters in this request. Set to 'true' to make sure values are matching their type.
      in: query
      schema:
        type: boolean
        default: false
    cast_types_true:
      name: _cast_types
      description: Wether or not to typecast the query parameters in this request. Set to 'false' to prevent typecasting.
      in: query
      schema:
        type: boolean
        default: true
    archived:
      name: _archived
      description: Wether or not to return archived documents
      in: query
      schema:
        type: boolean
        default: false
  schemas:
    game_preview:
      type: object
      properties:
        name:
          type: string
        setup:
          $ref: "#/components/schemas/game_setup"
    game_setup:
      type: object
      properties:
        created_at:
          type: string
        created_by:
          type: string
          description: user id
        created_with:
          type: string
          description: adaptor server version the game was created with
    file:
      type: object
      description: Represents a single file or directory entry as returned by the getFiles endpoint.
      required:
        - name
        - type
        - path
      properties:
        name:
          type: string
          description: File or directory name (without path).
          example: "adaptor-logo.png"
        type:
          type: string
          enum: [file, directory]
          description: Whether this entry is a file or a directory.
        path:
          type: string
          description: path relative to the game's files directory.
          example: "examples/adaptor-logo.png"
        absolute_path:
          type: string
          description: Full path of the file or directory.
          example: "/home/user/adaptorex/games/my-game/files/examples/adaptor-logo.png"
        size:
          type: integer
          description: File size in bytes. Only present for files.
          example: 204800
        mime_type:
          type: string
          description: Detected MIME type. Only present for files.
          example: "image/png"
        public:
          type: boolean
          description: Wether or not the file was published using the publishFile endpoint.
          example: false
        publicly_accessible:
          type: boolean
          description: Wether or not the file is in a public directory but not itself published.
          example: false
        public_url:
          type: string
          description: Public URL to the file. Only present for published and publicly accessible files.
          example: "https://my-adaptorex-server.io/my-game/files/examples/adaptor-logo.png"
        modified_at:
          type: string
          format: date-time
          description: Last modification timestamp.
          example: "2026-04-01T10:26:04.784Z"
        created_at:
          type: string
          format: date-time
          description: Creation timestamp.
          example: "2026-03-31T12:43:35.797Z"
    level_preview:
      type: object
      properties:
        _id:
          type: string
        name:
          type: string
        created_at:
          type: string
        created_by:
          type: string
        created_with:
          type: string
          description: adaptor server version the level was created with
        modified_at:
          type: string
        modified_by:
          type: string
        modified_with:
          type: string
          description: adaptor server version the level was last modified with
        config:
          type: object
          properties:
            arguments:
              $ref: "#/components/schemas/arguments"
    action_preview:
      type: object
      properties:
        action:
          type: string
          description: action name as defined by plugin
        title:
          type: string
          description: friendly action name
        description:
          type: string
          description: brief action description
        plugin:
          type: string
          description: the plugin that provides this action
        mode:
          $ref: "#/components/schemas/action_mode"
    session_preview:
      type: object
      properties:
        _id:
          type: string
        name:
          type: string
        level:
          type: string
          description: level _id
        level_name:
          type: string
          description: level name
        game:
          type: string
        created_at:
          type: string
        created_by:
          type: string
        created_with:
          type: string
          description: adaptor server version the session was launched with
    plugin_preview:
      type: object
      required: [name]
      properties:
        name:
          type: string
        settings:
          type: object
        core:
          type: boolean
          description: If true, plugin is included with every game by default.
        description:
          type: string
        created_at:
          type: string
        created_by:
          type: string
        created_with:
          type: string
          description: adaptor server version the plugin was added with
        modified_at:
          type: string
        modified_by:
          type: string
        modified_with:
          type: string
          description: adaptor server version the plugin was modified with
    user:
      type: object
      example:
        login: ada
        password: secret123
        role: author
        games:
          - name: AdasGame
            role: owner
      properties:
        _id:
          type: string
        name:
          type: string
        login:
          type: string
          required: true
        password:
          type: string
        role:
          type: string
          enum: [admin, owner, developer, author, operator, viewer]
        games:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              role:
                type: string
    game:
      type: object
      properties:
        name:
          type: string
        setup:
          $ref: "#/components/schemas/game_setup"
        level:
          type: array
          items:
            $ref: "#/components/schemas/level_preview"
        actions:
          type: array
          items:
            $ref: "#/components/schemas/action_preview"
        sessions:
          type: array
          items:
            $ref: "#/components/schemas/session_preview"
        plugins:
          type: array
          items:
            $ref: "#/components/schemas/plugin_preview"
        collections:
          type: array
          items:
            description: collection name
            type: string
    plugin:
      type: object
      properties:
        name:
          type: string
        core:
          type: boolean
          description: if true, plugin is part of basics, included in each game and can not be removed
        settings:
          type: object
          properties:
            data:
              type: object
            schema:
              $ref: "#/components/schemas/meta_schema"
        items:
          type: object
          additionalProperties:
            type: object
            properties:
              items:
                type: array
                items:
                  $ref: "#/components/schemas/plugin_item"
              schema:
                $ref: "#/components/schemas/meta_schema"
        created_at:
          type: string
        created_by:
          type: string
        created_with:
          type: string
          description: adaptor server version the plugin was added with
        modified_at:
          type: string
        modified_by:
          type: string
        modified_with:
          type: string
          description: adaptor server version the plugin was modified with
    plugin_item:
      type: object
      properties:
        name:
          type: string
        settings:
          type: object
        created_at:
          type: string
        created_by:
          type: string
        created_with:
          type: string
          description: adaptor server version the plugin item was created with
        modified_at:
          type: string
        modified_by:
          type: string
        modified_with:
          type: string
          description: adaptor server version the plugin item was modified with
    item:
      type: object
      description: Data or Plugin item for use in dashboard view (async api)
      properties:
        name:
          type: string
        type:
          type: string
          enum: ["plugin", "data"]
        collection:
          type: string
          description: Plugin or Data collection name
        plugin:
          type: string
          description: Plugin name if item is a plugin item
        dashboard:
          type: object
          properties:
            favorite:
              type: boolean
              description: show or hide item in favorites dashboard
            hidden_properties:
              type: array
              description: item properties that are not shown or not highlighted in items dashboard. Nested properties addressed by dot notation e.g. 'dont.show.thisproperty'
              items:
                type: string
    session:
      type: object
      properties:
        _id:
          type: string
        name:
          type: string
        level:
          type: string
          description: _id property of the level the session is based on
        level_name:
          type: string
          description: name of level the session is based on
        game:
          type: string
          description: name of game the session is located in
        created_at:
          type: string
        created_by:
          type: string
        created_with:
          type: string
          description: adaptor server version the session was launched with
        references:
          type: object
          description: snapshot of currently referenced documents
          additionalProperties:
            type: object
        current_states:
          type: array
          description: list of latest dispatched states in each path.
          items:
            $ref: "#/components/schemas/session/properties/history/items"
        current_listeners:
          type: object
          description: liste of listener actions that are currently listening. Can be "active", "muted" or "stalled".
          additionalProperties:
            type: array
            items:
              $ref: "#/components/schemas/listener"
        history:
          type: array
          description: list off all states that where dispatched since. Contain data that was generated with them
          items:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
              path:
                type: string
              date:
                type: string
        states:
          type: object
          description: storeage of latest occurance of specific state (by name)
          additionalProperties:
            type: object
    arguments:
      description: Each level parameter argument is of type object where the object key is the argument name.
      type: object
      additionalProperties:
        type: object
        properties:
          type:
            description: The optional argument type. Can be "string", "number", "array", "object" or the name of an item collection.
            type: string
          value:
            description: An optional value that is used if the argument is not provided otherwise on session start. Must be of the type provided above and can be a query referring to one or more collection items in the collection above.
            type: string
    collection:
      type: object
      required: ["name"]
      additionalProperties: false
      properties:
        name:
          description: name of collection to be created
          type: string
          not:
            type: string
            enum: ["levels", "sessions", "plugins", "setup"]
    level:
      type: object
      default:
        name: new_level
        config:
          arguments:
            Player:
              type: players
        states:
          _state_0:
            name: "START"
            view:
              position:
                x: 40
                y: 40
            comments: ["When a new session is created, the START state starts."]
            run: [_action_0]
            listen: []
          _state_1:
            name: "QUIT"
            view:
              position:
                x: 800
                y: 500
            comments: []
            run: [_action_1]
            listen: []
        actions:
          _action_0:
            action: next
            name: next_1
            plugin: control
            payload:
              next: ""
            mode: run
          _action_1:
            action: quit
            name: quit_1
            plugin: control
            payload: null
            mode: run
        contents: {}
      example:
        _id: 2ZN32ayOujErm2Hl
        name: my_level
        config:
          arguments: {}
        paths: [["start"]]
        states:
          stateID1:
            name: START
            path:
              - start
            view:
              position:
                x: 0
                y: 0
            comments:
              - Here the journey begins
            run:
              - ActionID1
            listen:
              - ActionID2
        stateID2:
          name: QUIT
          path: []
          view:
            position:
              x: 100
              y: 0
          comments:
            - Here it ends
          run: []
          listen: []
        actions:
          ActionID1:
            name: action-1
            action: send_message
            plugin: telegram
            mode: run
            payload: {}
          ActionID2:
            name: action-2
            action: timeout
            plugin: time
            mode: listen
            payload: {}
        contents:
          ContentID1:
            de: sein oder nicht sein
            en: to be or not to be
      properties:
        _id:
          type: string
        name:
          type: string
        config:
          type: object
          properties:
            arguments:
              $ref: "#/components/schemas/arguments"
        revision:
          description: Only for level history. Details about the history entry.
          type: object
          properties:
            created_at:
              type: string
            created_by:
              type: string
            id:
              type: number
            comment:
              type: string
        paths:
          description: all existing state paths of this level in one list
          type: array
          items:
            type: array
            items:
              type: string
        states:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/state"
        actions:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/action"
        contents:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/content"
    states:
      type: object
      description: state elements of a selected set of states
      properties:
        states:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/state"
        actions:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/action"
        contents:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/content"
    state:
      type: object
      properties:
        name:
          type: string
        path:
          type: array
          items:
            type: string
        view:
          type: object
          description: state appearance in level editor
          properties:
            position:
              type: object
              properties:
                x:
                  type: number
                y:
                  type: number
        comments:
          type: array
          items:
            type: string
        run:
          type: array
          items:
            type: string
            description: list of executable action ids
        listen:
          type: array
          items:
            type: string
            description: list of listener action ids
    action:
      type: object
      required:
        - action
        - plugin
        - payload
      properties:
        id:
          type: string
          description: auto generated unique action id
        name:
          type: string
          description: name of action instance
        action:
          type: string
          description: action name as defined by plugin
        plugin:
          type: string
          description: the plugin that provides this action
        mode:
          $ref: "#/components/schemas/action_mode"
        payload:
          description: action as described by plugin
    content:
      type: object
      description: each content element is referred to by an action. content element properties depend on what content types there are (e.g. different languages)
      additionalProperties: true
    listener:
      type: object
      properties:
        id:
          type: string
          description: auto generated unique listener action id
        name:
          type: string
          description: name of the listener action instance
        _id:
          type: string
          description: the listeners collection document id of this listener
        date:
          type: string
          description: UTC date and time the listener has been started
        state:
          type: object
          description: the state the listener action is part of
          properties:
            id:
              type: string
            name:
              type: string
        session:
          type: string
          description: the session the listener action has been started in
        action:
          type: string
          description: listener action name as defined by plugin
        plugin:
          type: string
          description: the plugin that provides this listener action
        mode:
          type: string
          enum: ["listen"]
        payload:
          type: object
          description: action data as it was edited by a user
        status:
          type: string
          enum: ["active", "muted", "stalled"]
        persistent:
          type: boolean
          description: wether the listener will be canceled whenever the containing state is left. If `true` the listener will keep listening but not dispatch any next States (`"status":"muted"`)
        queue:
          type: array
          description: list of ingoing messages that have been added to queue during "muted" status. Each message contains list of all args that will be forwarded to listener callback function once it is reinstalled.
          items:
            type: array
        max_queue_length:
          type: integer
          description: maximum number of ingoing messages that will be added to queue. If maximum is exceeded, oldest messages are discarded in favor of latest ingoing messages.
    action_schema:
      type: object
      description: payload is action schema as described by plugin
      properties:
        action:
          type: string
          description: action name as defined by plugin
        title:
          type: string
          description: friendly name
        mode:
          $ref: "#/components/schemas/action_mode"
        icon:
          type: string
          description: action icon filename or svg
        tooltip:
          type: string
          description: brief description of action
        documentation:
          type: string
          description: link to documentation or help page
        plugin:
          type: string
          description: the plugin that provides this action
        schema:
          $ref: "#/components/schemas/meta_schema"
    action_mode:
      type: string
      enum:
        - run
        - listen
      default: run
      description: action will finish during state init (run) or persist waiting for input (listen)
    meta_schema:
      description: >
        A json schema.
        TODO: this should be a reference to a meta schema somewhere else ($ref: "url://to.some.meta/schema/in/the/internetz.json") that describes how a json schema can look like.
      type: object
    issues:
      description: >
        Indicator in a response to a successful create or update request that there was an internal error
        that should be noted although it did not prevent the requested operation to succeed.
      type: array
      items:
        type: object
        properties:
          name:
            type: string
            description: Name of Error type that ocurred during the operation
            enum:
              [
                "InvalidError",
                "ValidationError",
                "DuplicateError",
                "SyntaxError",
                "OutdatedError",
                "ForbiddenError",
                "ConnectionError",
                "NotFoundError"
              ]
          message:
            type: string
            description: Text describing the error.
    prompt:
      description: >
        Form information about a prompt that is supposed to be shown following an update or create request.
        Might include a webhook where any inserted data is supposed to be forwarded to.
      type: object
      required:
        - message
      properties:
        message:
          type: string
          description: Message Text that should be prompted to the user
        schema:
          description: A json schema that describes what kind of data is requested by the user
          $ref: "#/components/schemas/meta_schema"
        webhook:
          type: string
          description: URL where to forward the requested data to. Webhook address will be relative to the base API url
        method:
          type: string
          description: Webhook request method to use.
          enum:
            - post
            - get
    path_update:
      type: object
      description: Updated paths for all states. Contains state elements cut down to the path property.
      properties:
        paths:
          type: array
          items:
            type: array
            items:
              type: string
        states:
          type: object
          additionalProperties:
            type: object
            properties:
              path:
                type: array
                items:
                  type: string
      example:
        paths:
          [
            [start],
            [start, sidequest],
            [start, timeout],
            [start, sidequest, timeout],
            [start, easteregg]
          ]
        states:
          state_0:
            path: [start]
          state_1:
            path: [start]
          state_2:
            path: [start, sidequest]
          state_3:
            path: [start, timeout]
          state_4:
            path: [start, sidequest, timeout]
          state_5:
            path: [start, easteregg]
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
  responses:
    200Update:
      description: update successful
      content:
        application/json:
          schema:
            type: object
            properties:
              changed:
                type: number
                default: 1
                description: >
                  Indicate if and how many resources have changed. If no resource has changed, modified properties are omitted. If adaptor uses mongodb, PUT requests for level and document will always respond with changed >= 1 and append modified information.
              modified_at:
                type: string
              modified_by:
                type: string
              modified_with:
                type: string
                description: adaptor server version the update was processed with
              prompt:
                $ref: "#/components/schemas/prompt"
              issues:
                $ref: "#/components/schemas/issues"
    200StateUpdate:
      description: >
        state update, create or delete  successful. Response includes updates on paths for all states that might have changed.
        Modification information refers to respective level document. 
        That is why even on a state create or delete operation, response will always contain 'modified' and not 'created' properties.
      content:
        application/json:
          schema:
            type: object
            properties:
              changed:
                type: boolean
                description: >
                  Indicate if resource has changed. If resource has not changed, modified properties are omitted. If adaptor uses mongodb, PUT requests for level and document will always respond with changed: true and append modified information
              modified_at:
                type: string
              modified_by:
                type: string
              modified_with:
                type: string
                description: adaptor server version the update was processed with
              path_update:
                $ref: "#/components/schemas/path_update"
    200Executed:
      description: operation executed
      content:
        application/json:
          schema:
            type: object
    200Connect:
      description: connection function executed
      content:
        application/json:
          schema:
            type: object
            properties:
              connected:
                type: boolean
                description: optional indicator if connection was established
              prompt:
                $ref: "#/components/schemas/prompt"
              issues:
                $ref: "#/components/schemas/issues"
    201Created:
      description: create successful
      content:
        application/json:
          schema:
            type: object
            properties:
              created_id:
                type: string
              created_at:
                type: string
              created_by:
                type: string
              created_path:
                type: string
              created_with:
                type: string
                description: adaptor server version the element was created with
              prompt:
                $ref: "#/components/schemas/prompt"
              issues:
                $ref: "#/components/schemas/issues"
    201StateCreated:
      $ref: "#/components/responses/200StateUpdate"
    201UploadDone:
      description: upload successful
      content:
        application/json:
          schema:
            type: array
            description: List of successfully uploaded files.
            items:
              $ref: "#/components/schemas/file"
    400Invalid:
      description: Invalid request. See error object for details.
      content:
        application/json:
          schema:
            type: object
            properties:
              name:
                type: string
                enum:
                  [
                    "InvalidError",
                    "ValidationError",
                    "DuplicateError",
                    "SyntaxError",
                    "OutdatedError",
                    "ForbiddenError",
                    "ConnectionError"
                  ]
              message:
                type: string
    401Unauthorized:
      description: Authentication information is missing or invalid
      headers:
        WWW_Authenticate:
          schema:
            type: string
      content:
        application/json:
          schema:
            type: object
            properties:
              name:
                type: string
                enum: ["AuthenticationError"]
              message:
                type: string
    403AccessDenied:
      description: User does not have the role that is required to access this resource
      content:
        application/json:
          schema:
            type: object
            properties:
              name:
                type: string
                enum: ["AuthenticationError"]
              message:
                type: string
    404NotFound:
      description: Resource was not found. See error object for details.
      content:
        application/json:
          schema:
            type: object
            properties:
              name:
                type: string
                enum: ["NotFoundError"]
              message:
                type: string
    500ServerError:
      description: An internal Server Error occurred. Consider bug report.
      content:
        application/json:
          schema:
            type: object
            properties:
              name:
                type: string
              message:
                type: string
              stack:
                type: string
security:
  - basicAuth: [admin, owner, developer, author, operator, viewer]
