{
  "openapi": "3.1.2",
  "info": {
    "title": "Space-Market",
    "version": "4.0.0",
    "summary": "An API ment for communication in a simple market system.",
    "description": "A API inspired by the [Space-Market](https://github.com/Space-Market/API) API. Its ment for communication of a simple market system.",
    "license": {
      "name": "MIT License",
      "identifier": "MIT",
      "url": "https://spdx.org/licenses/MIT.html"
    }
  },
  "servers": [
    {
      "url": "http://example.space-market.server/api/v4"
    }
  ],
  "security": [],
  "tags": [
    {
      "name": "auth",
      "description": "These endpoints define how clients can authenticate to the server to create and change protected items."
    },
    {
      "name": "info",
      "description": "These show informations about the server"
    },
    {
      "name": "products",
      "description": "These define how the products can be used"
    },
    {
      "name": "users",
      "description": "Defines how the user is defined and can be used"
    },
    {
      "name": "images",
      "description": "Define how a image is created and can be obtained.\n\nDue to human error, the server should not expect the client to delete the image, when it is not used anymore.\nThe server should implerment a garbage collection system for that.\n"
    },
    {
      "name": "barcodes",
      "description": "Defines how a barcode is crreated and can be used to find different objects.\n"
    },
    {
      "name": "denominations",
      "description": "Defines what amounts users can depoist."
    },
    {
      "name": "transactions",
      "description": "Defines how transactions are stored."
    }
  ],
  "paths": {
    "/server": {
      "get": {
        "tags": [
          "info"
        ],
        "summary": "Server Information",
        "description": "This returns preferences and additional information for the frontend.",
        "responses": {
          "200": {
            "description": "Returns information and preferences of the server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/server-info"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/products": {
      "get": {
        "tags": [
          "products"
        ],
        "summary": "Returns all products",
        "responses": {
          "200": {
            "description": "Returns the data for all products",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Product"
                  }
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "post": {
        "tags": [
          "products"
        ],
        "summary": "Creates a product",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCreate"
              }
            }
          }
        },
        "security": [
          {
            "RootAccess": []
          }
        ],
        "responses": {
          "200": {
            "description": "Created the product and returns the details for the product",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Product"
                    },
                    {
                      "example": {
                        "name": "Mio Mio Cola"
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The inputs used were incorrect.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "verificationsFailed": {
                      "type": "object",
                      "properties": {
                        "field": {
                          "type": "string"
                        },
                        "failedVerification": {
                          "type": "string",
                          "enum": [
                            "IMAGE_DOES_NOT_EXIST"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/products/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": [
          "products"
        ],
        "summary": "Returns details about a product",
        "responses": {
          "200": {
            "description": "Returns the details for the product",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "patch": {
        "tags": [
          "products"
        ],
        "summary": "Updates a product",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductUpdate"
              }
            }
          }
        },
        "security": [
          {
            "RootAccess": []
          }
        ],
        "responses": {
          "200": {
            "description": "Updated the product and returns the details for the updated product",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Product"
                    },
                    {
                      "example": {
                        "name": "Mio Mio Mate with pep"
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The inputs used were incorrect.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "verificationsFailed": {
                      "type": "object",
                      "properties": {
                        "field": {
                          "type": "string"
                        },
                        "failedVerification": {
                          "type": "string",
                          "enum": [
                            "IMAGE_DOES_NOT_EXIST"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "delete": {
        "tags": [
          "products"
        ],
        "summary": "Deletes a product by ID",
        "security": [
          {
            "RootAccess": []
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Success"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/users": {
      "get": {
        "tags": [
          "users"
        ],
        "summary": "Get all users",
        "description": "This endpoint returns all users",
        "responses": {
          "200": {
            "description": "Returns details of all users",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/User"
                  }
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "post": {
        "tags": [
          "users"
        ],
        "summary": "Create user",
        "description": "This endpoint creates a new user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/UserDetails"
                  },
                  {
                    "type": "object",
                    "required": [
                      "username",
                      "balance",
                      "active",
                      "store_changes"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created the user and returns details of that user",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/User"
                    },
                    {
                      "example": {
                        "name": "Mio Mio Cola"
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InputError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/users/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": [
          "users"
        ],
        "summary": "Returns details about the user",
        "responses": {
          "200": {
            "description": "Returns details about the user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "patch": {
        "tags": [
          "users"
        ],
        "summary": "Updates a user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/UserDetails"
                  },
                  {
                    "example": {
                      "username": "you"
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated the user and returns the updated user.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/User"
                    },
                    {
                      "example": {
                        "username": "you"
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InputError"
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "delete": {
        "tags": [
          "users"
        ],
        "summary": "Deletes a user by ID",
        "security": [
          {
            "RootAccess": []
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Success"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/users/{id}/deposit": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "tags": [
          "users"
        ],
        "summary": "Deposits funds to a user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "number",
                    "format": "int32"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The generated transaction for the purchase",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transaction"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/users/{id}/purchase": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "tags": [
          "users"
        ],
        "summary": "Purchase a product (or use up balance) for user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Using this will buy a product.",
                "properties": {
                  "product_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The generated transaction for the purchase",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transaction"
                }
              }
            }
          },
          "400": {
            "description": "The product id is incorrect.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": false
                    },
                    "reason": {
                      "type": "string",
                      "const": "INVALID_PRODUCT_ID"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/InsufficiantFundsError"
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/auth": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Authentication Information",
        "description": "This returns information how the API can be used to authenticate for additional permissions.",
        "responses": {
          "200": {
            "description": "Returns the authentication method the server expects. If \"NONE\" is returned, the \"Authentication\" header should always be ignored by the server, even if the frontend sends it.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "method": {
                      "type": "string",
                      "enum": [
                        "NONE",
                        "PASSPHRASE"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Create authentication token",
        "description": "This creates a authentication token, that can be used to modify specific data.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "passphrase": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token was created and the returned token should be used to gain RootAccess",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenReturn"
                }
              }
            }
          },
          "401": {
            "description": "The passphrase or credentials are invalid!"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "delete": {
        "tags": [
          "auth"
        ],
        "summary": "Delete authentication token",
        "description": "This invalidates the token, which is used as Bearer for the API. This should also invalidate the refresh token.",
        "security": [
          {
            "RootAccess": []
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Success"
          },
          "401": {
            "description": "Token was not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": false
                    }
                  }
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/auth/update": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Refresh token",
        "description": "This creates a new token, with a refresh token as authentication. The refresh token should be used as Bearer.",
        "security": [
          {
            "UpdateAccess": []
          }
        ],
        "responses": {
          "200": {
            "description": "Token was refreshed and can be used",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenReturn"
                }
              }
            }
          },
          "401": {
            "description": "Refresh Token is invalid"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/images": {
      "get": {
        "tags": [
          "images"
        ],
        "summary": "Returns the capabilities and guidelines for images",
        "description": "This endpoint informs the UI, what kind of images are allowed by the server.",
        "responses": {
          "200": {
            "description": "Returns guidelines for uploading images",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImageInfo"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "post": {
        "tags": [
          "images"
        ],
        "summary": "Create a new image",
        "description": "Creates a new image with the provided information.",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "file": {
                    "type": "array",
                    "items": {}
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The image got uploaded and stored and the returned object is the detailed image",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Image"
                }
              }
            }
          },
          "413": {
            "description": "The image is too large",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "maximum_size": {
                      "type": "number",
                      "format": "int32",
                      "description": "Maximum size of a image. in bytes",
                      "default": 5242880
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "The image does not comply with accepted Mime Types",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accepted_mime_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "default": [
                        "image/png",
                        "image/jpeg",
                        "image/gif",
                        "image/svg+xml"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/images/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": [
          "images"
        ],
        "summary": "Returns image metadata",
        "description": "This endpoint offers metadata about the specified image",
        "responses": {
          "200": {
            "description": "Returns the image metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Image"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "delete": {
        "tags": [
          "images"
        ],
        "summary": "Deletes the image",
        "description": "This will delete the image from the server, removing both the database entry and the file from the server.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/Success"
          },
          "400": {
            "description": "The image is still in use and should not be deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": false
                    },
                    "reason": {
                      "type": "string",
                      "const": "IN_USE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "The ID used does not exist. If this is called after a update to a object that removes or changes the image, this may mean the server already removed the requested image.",
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/images/{id}/raw": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": [
          "images"
        ],
        "summary": "Image as a raw data stream",
        "description": "This endpoint sends the image as a raw image stream.",
        "responses": {
          "200": {
            "description": "Should contain the image. Due to different server implermentation and capabilities, the content and mime type is not further specified"
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/barcodes": {
      "get": {
        "tags": [
          "barcodes"
        ],
        "summary": "Find barcode by type and barcode or id",
        "description": "Returns details for the barcode requested.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BarcodeSearch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Returns objects with stored data for the barcode assoicated with the barcode or id",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Barcode"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No barcode was found for the defined type and barcode string",
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "post": {
        "tags": [
          "barcodes"
        ],
        "summary": "Creates a barcode for an object",
        "description": "This endpoint allows to create a barcode, which points to a object",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BarcodeDetails"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Creates a barcode object, that is automatically linked to a object.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Barcode"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The inputs used were incorrect.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "verificationsFailed": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "field": {
                            "type": "string"
                          },
                          "failedVerification": {
                            "type": "string",
                            "enum": [
                              "ALREADY_EXISTS",
                              "OBJECT_DOES_NOT_EXIST"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/barcodes/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": [
          "barcodes"
        ],
        "summary": "Get Barcode Details",
        "description": "This endpoint returns the stored data for this barcode",
        "responses": {
          "200": {
            "description": "Returns a object with stored data for the barcode",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Barcode"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "patch": {
        "tags": [
          "barcodes"
        ],
        "summary": "Updates a barcode",
        "responses": {
          "200": {
            "description": "The change was accepted and returns the changed barcode",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Barcode"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InputError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "delete": {
        "tags": [
          "barcodes"
        ],
        "summary": "Deletes a barcode by ID",
        "responses": {
          "200": {
            "$ref": "#/components/responses/Success"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/InvalidIdError"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/denominations": {
      "get": {
        "tags": [
          "denominations"
        ],
        "summary": "Get all denominations",
        "description": "This endpoint returns all denominations. The denominations are expected to be defined by the server.",
        "responses": {
          "200": {
            "description": "Returns all denominations defined.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Denomination"
                  }
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/transactions": {
      "get": {
        "tags": [
          "transactions"
        ],
        "summary": "List all transactions",
        "description": "This endpoint returns all transactions, with optional filtering",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user_id": {
                    "description": "The user id to filter for.",
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lists all transactions that were found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Transaction"
                  }
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "post": {
        "tags": [
          "transactions"
        ],
        "summary": "Create a new transactions",
        "description": "Creates a new transaction with the provided information. This is primarily used for migration.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionDetails"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The image got uploaded and stored and the returned object is the detailed image",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transaction"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    },
    "/transactions/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": [
          "transactions"
        ],
        "summary": "Get transaction details from id",
        "description": "Get transaction details from the provided id",
        "responses": {
          "200": {
            "description": "The transaction details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transaction"
                }
              }
            }
          },
          "404": {
            "description": "The transaction doesn't exist"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      },
      "delete": {
        "tags": [
          "transactions"
        ],
        "summary": "Remove transaction details from id",
        "description": "Remove the transaction details from the id",
        "responses": {
          "200": {
            "description": "The transaction was successfully deleted."
          },
          "404": {
            "description": "The transaction doesn't exist"
          },
          "default": {
            "$ref": "#/components/responses/GenericError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "RootAccess": {
        "type": "http",
        "description": "This key should be used to modify specific properties. Use /auth/ to create the token.",
        "scheme": "bearer"
      },
      "UpdateAccess": {
        "type": "http",
        "description": "This key should be used to create a new token, when the previous was invalidated due to time",
        "scheme": "bearer"
      }
    },
    "responses": {
      "GenericError": {
        "description": "The API was called incorrectly or a server side error happend. This is intentionally undefined, since generic errors are usually handled by the webserver from the API."
      },
      "UnauthorizedError": {
        "description": "The Bearer token is invalid or missing!"
      },
      "InvalidIdError": {
        "description": "The ID used does not exist.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "success": {
                  "type": "boolean",
                  "const": false
                },
                "reason": {
                  "type": "string",
                  "const": "INVALID_ID"
                }
              }
            }
          }
        }
      },
      "Success": {
        "description": "The request was performed successfully",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "success": {
                  "type": "boolean",
                  "const": true
                }
              }
            }
          }
        }
      },
      "InputError": {
        "description": "The inputs used were incorrect.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "verificationsFailed": {
                  "type": "object",
                  "properties": {
                    "field": {
                      "type": "string"
                    },
                    "failedVerification": {
                      "type": "string",
                      "enum": [
                        "MISSING_REQUIRED_VALUE",
                        "IMAGE_DOES_NOT_EXIST",
                        "NAME_ALREADY_USED",
                        "ALREADY_EXISTS",
                        "INVALID_TYPE",
                        "OBJECT_DOES_NOT_EXIST"
                      ]
                    }
                  }
                }
              },
              "example": {
                "verificationsFailed": [
                  {
                    "field": "image",
                    "failedVerification": "IMAGE_DOES_NOT_EXIST"
                  },
                  {
                    "field": "name",
                    "failedVerification": "MISSING_REQUIRED_VALUE"
                  },
                  {
                    "field": "name",
                    "failedVerification": "NAME_ALREADY_USED"
                  }
                ]
              }
            }
          }
        }
      },
      "InsufficiantFundsError": {
        "description": "The user has not enough funds to use this endpoint",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "success": {
                  "type": "boolean",
                  "const": false
                },
                "reason": {
                  "type": "string",
                  "const": "INSUFFICIANT_FUNDS"
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "server-info": {
        "type": "object",
        "properties": {
          "version": {
            "type": "string",
            "description": "Defines a version string the client may use to display to the user. Due to undefined format, clients should not attempt to parse it.",
            "example": "Matender v0.0.1-beta"
          },
          "credit_limit": {
            "type": "number",
            "format": "int32",
            "description": "Defines the credit limit for users. This should be enforced by the server.",
            "default": 2000
          },
          "currency": {
            "type": "object",
            "description": "Contains information for the currency",
            "properties": {
              "symbol": {
                "type": "string",
                "example": "€"
              },
              "symbol_location": {
                "type": "string",
                "description": "Gives the frontend a hit, where the symbol should be placed",
                "example": "AFTER_AMOUNT",
                "enum": [
                  "BEFORE_AMOUNT",
                  "AFTER_AMOUNT"
                ]
              }
            }
          },
          "energy_unit": {
            "type": "string",
            "description": "Defines what energy format, a energy defintion should be.",
            "default": "kcal"
          },
          "mass_unit": {
            "type": "string",
            "description": "Defines what unit should be used for labels.",
            "default": "g"
          }
        }
      },
      "ItemAttributes": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The internal ID that should be used to point to this specific item."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "The time and date, when the item was created."
          }
        },
        "required": [
          "id"
        ]
      },
      "UpdateableItemAttributes": {
        "type": "object",
        "allOf": [
          {
            "$ref": "#/components/schemas/ItemAttributes"
          },
          {
            "type": "object",
            "properties": {
              "updated_at": {
                "type": "string",
                "format": "date-time",
                "description": "The time and date, when the item was last modified."
              }
            }
          }
        ]
      },
      "DrinkLabel": {
        "type": "object",
        "description": "The label of the drink. Usually contains additional information like size or caffeine.",
        "properties": {
          "type": {
            "type": "string",
            "const": "DRINK"
          },
          "bottle_size": {
            "type": "number",
            "format": "float",
            "description": "size in litres"
          },
          "caffeine": {
            "type": "number",
            "format": "int32",
            "description": "mg of caffeine per 100ml/unit"
          },
          "energy": {
            "type": "number",
            "format": "int32",
            "description": "energy per 100ml"
          },
          "alcohol": {
            "type": "number",
            "format": "float",
            "description": "vol % alcohol"
          }
        },
        "example": {
          "bottle_size": 0.5,
          "caffeine": 20,
          "energy": 102,
          "alcohol": 0
        }
      },
      "FoodLabel": {
        "type": "object",
        "description": "The label for the food.",
        "properties": {
          "type": {
            "type": "string",
            "const": "FOOD"
          },
          "vegetarian": {
            "type": "boolean"
          },
          "vegan": {
            "type": "boolean"
          },
          "energy": {
            "type": "number",
            "format": "int32",
            "description": "The energy for the food per 100g. The unit is defined by the server under \"/server\" from the property \"energy\"."
          },
          "fat": {
            "type": "number",
            "format": "int32",
            "description": "The fat amount for the food per 100g. The unit is defined by the server under \"/server\" from the property \"mass_unit\""
          },
          "carbohydrate": {
            "type": "number",
            "format": "int32",
            "description": "The carbohydrate amount for the food per 100g. The unit is defined by the server under \"/server\" from the property \"mass_unit\"."
          },
          "sugar": {
            "type": "number",
            "format": "int32",
            "description": "The sugar amount for the food per 100g. The unit is defined by the server under \"/server\" from the property \"mass_unit\"."
          },
          "protein": {
            "type": "number",
            "format": "int32",
            "description": "The protein amount for the food per 100g. The unit is defined by the server under \"/server\" from the property \"mass_unit\"."
          },
          "salt": {
            "type": "number",
            "format": "int32",
            "description": "The salt amount for the food per 100g. The unit is defined by the server under \"/server\" from the property \"mass_unit\"."
          }
        }
      },
      "ActionLabel": {
        "type": "object",
        "description": "The label for a action. This is ment for stuff like printing.",
        "properties": {
          "type": {
            "type": "string",
            "const": "ACTION"
          },
          "description": {
            "type": "string",
            "description": "A closer description, what the action actually is and for what the user is paying for."
          }
        }
      },
      "ProductLabel": {
        "description": "The label of the product. Usually contains additional information like size or caffeine.",
        "discriminator": {
          "propertyName": "type"
        },
        "properties": {
          "type": {
            "type": "string"
          }
        },
        "oneOf": [
          {
            "$ref": "#/components/schemas/DrinkLabel"
          },
          {
            "$ref": "#/components/schemas/FoodLabel"
          },
          {
            "$ref": "#/components/schemas/ActionLabel"
          }
        ]
      },
      "ProductDetails": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "price": {
            "type": "number",
            "format": "int32",
            "description": "Price in the smallest format of the currency (f.E. cents)"
          },
          "active": {
            "type": "boolean",
            "description": "If active is false, its considered to be not avaliable. This should not prevent people to buy it, however. Frontend may use this value to add a dialog to notify users of the fact, its not avaliable."
          },
          "image_id": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "$ref": "#/components/schemas/ProductLabel"
          }
        }
      },
      "ProductDetailsExample": {
        "example": {
          "name": "Mio Mio Mate",
          "price": 170,
          "active": true,
          "image_id": "b25afde4-07a4-45a3-a99d-bad3a7780cbb",
          "label": {
            "bottle_size": 0.5,
            "caffeine": 20,
            "energy": 102,
            "alcohol": 0
          }
        }
      },
      "Product": {
        "type": "object",
        "allOf": [
          {
            "$ref": "#/components/schemas/UpdateableItemAttributes"
          },
          {
            "$ref": "#/components/schemas/ProductDetails"
          },
          {
            "$ref": "#/components/schemas/ProductDetailsExample"
          },
          {
            "required": [
              "name",
              "price",
              "active"
            ]
          }
        ]
      },
      "ProductCreate": {
        "type": "object",
        "description": "Defines what values can be used to create the product. Missing values should be set to the default values by the server.",
        "allOf": [
          {
            "$ref": "#/components/schemas/ProductDetails"
          },
          {
            "required": [
              "name",
              "price",
              "active",
              "label"
            ],
            "example": {
              "name": "Mio Mio Cola"
            }
          }
        ]
      },
      "ProductUpdate": {
        "type": "object",
        "description": "Defines what values can be used to create the product. Missing values should not be overridden by the server",
        "allOf": [
          {
            "$ref": "#/components/schemas/ProductDetails"
          },
          {
            "example": {
              "name": "Mio Mio Mate with pep"
            }
          }
        ]
      },
      "UserDetailsProperties": {
        "type": "object",
        "properties": {
          "balance": {
            "description": "The balance of the user in cents",
            "type": "number",
            "format": "int32"
          },
          "active": {
            "type": "boolean"
          },
          "track_transactions": {
            "description": "If set to true, transactions should contain the users id as related user id.\nSetting it to false, the server should remove the user id from related transactions.\n",
            "type": "boolean"
          },
          "avatar_id": {
            "description": "The avatar image for the user.",
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "UserDetails": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string"
          }
        },
        "allOf": [
          {
            "$ref": "#/components/schemas/UserDetailsProperties"
          }
        ]
      },
      "User": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UpdateableItemAttributes"
          },
          {
            "$ref": "#/components/schemas/UserDetails"
          },
          {
            "type": "object",
            "required": [
              "username",
              "balance",
              "active",
              "track_transactions"
            ]
          }
        ]
      },
      "TransactionDetails": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "The timestamp when the transaction happend"
          },
          "type": {
            "type": "string",
            "enum": [
              "PURCHASE",
              "DEPOSIT"
            ]
          },
          "amount": {
            "type": "number",
            "format": "int32"
          },
          "related_user_id": {
            "type": "string",
            "format": "uuid"
          },
          "related_product_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "timestamp",
          "type",
          "amount"
        ]
      },
      "Transaction": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              }
            },
            "required": [
              "id"
            ]
          },
          {
            "$ref": "#/components/schemas/TransactionDetails"
          }
        ]
      },
      "TokenReturn": {
        "type": "object",
        "properties": {
          "token": {
            "description": "the token to be used",
            "type": "string"
          },
          "token_valid_until": {
            "description": "the time the token will be invalid. the duration is not specified by the api and may be different across server implermentations",
            "format": "datetime",
            "type": "string"
          },
          "refresh_token": {
            "description": "the token to be used, when the previous token has become invalid.",
            "type": "string"
          },
          "refresh_token_valid_until": {
            "description": "the time the refresh_token will be invalid. the duration is not specified by the api and may be different across server implermentations",
            "format": "datetime",
            "type": "string"
          }
        }
      },
      "ImageInfo": {
        "type": "object",
        "description": "This object defines, what images the server accept.",
        "properties": {
          "accepted_mime_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "default": [
              "image/png",
              "image/jpeg",
              "image/gif",
              "image/svg+xml"
            ]
          },
          "maximum_size": {
            "type": "number",
            "format": "int32",
            "description": "Maximum size of a image. in bytes",
            "default": 5242880
          }
        }
      },
      "Image": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ItemAttributes"
          },
          {
            "type": "object",
            "properties": {
              "filename": {
                "type": "string",
                "description": "The name of the file. This most likely will not be the same name, the file got upload with. Do not use it to check if the frontend needs to upload a new image. Use hash instead.",
                "example": "44d3e5d4-60a9-4a16-a20b-1b68c2662e1a.png"
              },
              "hash": {
                "type": "string",
                "description": "The hash for the file, which should be generated using sha256. This can be used by the frontend to check if they need to upload a new image.",
                "example": "dd593e6cbf80204e5a68bc64c50a4156a3da7569650f61d7cfe6437428a805d4"
              },
              "filesize": {
                "type": "number",
                "format": "int32",
                "description": "The size of the file in bytes",
                "example": 1048576
              },
              "mime_type": {
                "type": "string",
                "description": "The mime type of the file",
                "example": "image/png"
              }
            }
          }
        ],
        "required": [
          "filename",
          "hash",
          "filesize",
          "mime_type"
        ]
      },
      "BarcodeSearch": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "PRODUCT",
              "USER"
            ]
          }
        },
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "barcode": {
                "type": "string"
              }
            }
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        ],
        "required": [
          "type",
          "barcode",
          "id"
        ]
      },
      "BarcodeDetails": {
        "type": "object",
        "properties": {
          "barcode": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PRODUCT",
              "USER"
            ]
          },
          "linked_object": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "barcode",
          "type",
          "linked_object"
        ]
      },
      "Barcode": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UpdateableItemAttributes"
          },
          {
            "$ref": "#/components/schemas/BarcodeDetails"
          }
        ]
      },
      "Denomination": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "format": "int32"
          },
          "image_url": {
            "description": "The URI that should be used when a frontend wants to use an image for the amount. \n\nWhile it can be any URI renderable by a web-browser, its recommended to only use server-located uri to prevent issues.\n",
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "amount",
          "image_url"
        ]
      }
    }
  }
}