openapi: 3.1.0
info:
  title: VWPrg – gemeinsamer API-Vertrag
  version: 3.0.0
  description: Gilt für Express/Prisma und FastAPI/SQLModel. Fehlertexte können abweichen; Statuscodes
    und message sind verbindlich. Geldwerte in Antworten sind Dezimalstrings. Schreibzugriffe verwenden
    JSON (maximal 128 KiB); Media-Uploads verwenden einen binären Body (maximal 5 MiB). PUT aktualisiert die angegebenen Felder; unbekannte Felder werden abgewiesen.
    Siehe docs/API.md.
paths:
  /user/register:
    post:
      tags:
      - User
      summary: Register
      operationId: register_api_user_register_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Register'
        required: true
      responses:
        '201':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegisteredUser'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      parameters: []
      security: []
  /user/login:
    post:
      tags:
      - User
      summary: Login
      operationId: login_api_user_login_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Login'
        required: true
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Token'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      parameters: []
      security: []
  /user/me:
    get:
      tags:
      - User
      summary: Me
      operationId: me_api_user_me_get
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profile'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
  /user/{id}:
    get:
      tags:
      - User
      summary: Get User
      operationId: get_user_api_user__id__get
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profile'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
    put:
      tags:
      - User
      summary: Update User
      operationId: update_user_api_user__id__put
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProfileUpdate'
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profile'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
    delete:
      tags:
      - User
      summary: Delete User
      operationId: delete_user_api_user__id__delete
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '204':
          description: Successful Response
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /shop/categories:
    get:
      tags:
      - Shop
      summary: Categories
      operationId: categories_api_shop_categories_get
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Category'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      parameters: []
      security: []
    post:
      tags:
      - Shop
      summary: Create Category
      operationId: create_category_api_shop_categories_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CategoryCreate'
        required: true
      responses:
        '201':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Category'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
  /shop/categories/{id}:
    get:
      tags:
      - Shop
      summary: Category
      operationId: category_api_shop_categories__id__get
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Category'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security: []
    put:
      tags:
      - Shop
      summary: Update Category
      operationId: update_category_api_shop_categories__id__put
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CategoryCreate'
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Category'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
    delete:
      tags:
      - Shop
      summary: Delete Category
      operationId: delete_category_api_shop_categories__id__delete
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '204':
          description: Successful Response
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /shop/products:
    get:
      tags:
      - Shop
      summary: Products
      operationId: products_api_shop_products_get
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ProductView'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      parameters: []
      security: []
    post:
      tags:
      - Shop
      summary: Create Product
      operationId: create_product_api_shop_products_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductCreate'
        required: true
      responses:
        '201':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
  /shop/products/{id}:
    get:
      tags:
      - Shop
      summary: Product
      operationId: product_api_shop_products__id__get
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductDetail'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security: []
    put:
      tags:
      - Shop
      summary: Update Product
      operationId: update_product_api_shop_products__id__put
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductUpdate'
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
    delete:
      tags:
      - Shop
      summary: Delete Product
      operationId: delete_product_api_shop_products__id__delete
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '204':
          description: Successful Response
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /shop/ratings/product/{productId}:
    get:
      tags:
      - Shop
      summary: Ratings
      operationId: ratings_api_shop_ratings_product__productId__get
      parameters:
      - name: productId
        in: path
        required: true
        schema:
          type: string
          title: Productid
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/RatingView'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security: []
  /shop/ratings:
    post:
      tags:
      - Shop
      summary: Create Rating
      operationId: create_rating_api_shop_ratings_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RatingCreate'
        required: true
      responses:
        '201':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Rating'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
  /shop/ratings/{id}:
    put:
      tags:
      - Shop
      summary: Update Rating
      operationId: update_rating_api_shop_ratings__id__put
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RatingUpdate'
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Rating'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
    delete:
      tags:
      - Shop
      summary: Delete Rating
      operationId: delete_rating_api_shop_ratings__id__delete
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '204':
          description: Successful Response
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /communication/posts:
    get:
      tags:
      - Communication
      summary: Posts
      operationId: posts_api_communication_posts_get
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PostView'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      parameters: []
      security: []
    post:
      tags:
      - Communication
      summary: Create Post
      operationId: create_post_api_communication_posts_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostCreate'
        required: true
      responses:
        '201':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Post'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
  /communication/posts/{id}:
    get:
      tags:
      - Communication
      summary: Post
      operationId: post_api_communication_posts__id__get
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PostDetail'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security: []
    put:
      tags:
      - Communication
      summary: Update Post
      operationId: update_post_api_communication_posts__id__put
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostUpdate'
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Post'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
    delete:
      tags:
      - Communication
      summary: Delete Post
      operationId: delete_post_api_communication_posts__id__delete
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '204':
          description: Successful Response
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /communication/comments/post/{postId}:
    get:
      tags:
      - Communication
      summary: Comments
      operationId: comments_api_communication_comments_post__postId__get
      parameters:
      - name: postId
        in: path
        required: true
        schema:
          type: string
          title: Postid
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CommentView'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security: []
  /communication/comments:
    post:
      tags:
      - Communication
      summary: Create Comment
      operationId: create_comment_api_communication_comments_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CommentCreate'
        required: true
      responses:
        '201':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Comment'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
  /communication/comments/{id}:
    put:
      tags:
      - Communication
      summary: Update Comment
      operationId: update_comment_api_communication_comments__id__put
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CommentUpdate'
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Comment'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
    delete:
      tags:
      - Communication
      summary: Delete Comment
      operationId: delete_comment_api_communication_comments__id__delete
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '204':
          description: Successful Response
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /communication/chat/{recipientId}:
    get:
      tags:
      - Communication
      summary: Chat
      operationId: chat_api_communication_chat__recipientId__get
      security:
      - BearerAuth: []
      parameters:
      - name: recipientId
        in: path
        required: true
        schema:
          type: string
          title: Recipientid
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ChatView'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /communication/chat:
    post:
      tags:
      - Communication
      summary: Send Message
      operationId: send_message_api_communication_chat_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatCreate'
        required: true
      responses:
        '201':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatMessage'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
  /order/payments/order/{orderId}:
    get:
      tags:
      - Payments (simulation)
      summary: List Payments
      operationId: list_payments_api_order_payments_order__orderId__get
      security:
      - BearerAuth: []
      parameters:
      - name: orderId
        in: path
        required: true
        schema:
          type: string
          title: Orderid
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Payment'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /order/payments:
    post:
      tags:
      - Payments (simulation)
      summary: Create Payment
      operationId: create_payment_api_order_payments_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PaymentCreate'
        required: true
      responses:
        '201':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Payment'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
  /order:
    get:
      tags:
      - Order
      summary: List Orders
      operationId: list_orders_api_order_get
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/OrderView'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
    post:
      tags:
      - Order
      summary: Create Order
      operationId: create_order_api_order_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrderCreate'
        required: true
      responses:
        '201':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreatedOrder'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
  /order/{id}:
    get:
      tags:
      - Order
      summary: Get Order
      operationId: get_order_api_order__id__get
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderDetail'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /order/{id}/status:
    put:
      tags:
      - Order
      summary: Cancel
      operationId: cancel_api_order__id__status_put
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StatusUpdate'
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /booking:
    get:
      tags:
      - Booking
      summary: List Orders
      operationId: list_orders_api_booking_get
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BookingView'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
    post:
      tags:
      - Booking
      summary: Create Order
      operationId: create_order_api_booking_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrderCreate'
        required: true
      responses:
        '201':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreatedOrder'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      security:
      - BearerAuth: []
      parameters: []
  /booking/{id}:
    get:
      tags:
      - Booking
      summary: Get Order
      operationId: get_order_api_booking__id__get
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BookingDetail'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /booking/{id}/status:
    put:
      tags:
      - Booking
      summary: Cancel
      operationId: cancel_api_booking__id__status_put
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          title: Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StatusUpdate'
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
  /:
    get:
      summary: Info
      operationId: info_api_get
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: object
                properties:
                  message: &id001
                    type: string
                required:
                - message
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
      parameters: []
      security: []
  /health:
    get:
      summary: Health
      operationId: health_api_health_get
      responses:
        '200':
          description: Erfolg
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    const: ok
                    type: string
                required:
                - status
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '409':
          $ref: '#/components/responses/Error409'
        '413':
          $ref: '#/components/responses/Error413'
        '500':
          $ref: '#/components/responses/Error500'
        '503':
          $ref: '#/components/responses/Error503'
      parameters: []
      security: []
  "/media":
    "get":
      "tags":
        - "Media"
      "summary": "Öffentliche und eigene Dateien (max. 100, neueste zuerst)"
      "security": []
      "responses":
        "200":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "type": "array"
                "items":
                  "$ref": "#/components/schemas/Media"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "description": "Optionaler Bearer-Token ergänzt eigene private Dateien. Produkt-/Beitragsfilter sind kombinierbar."
      "parameters":
        - {"name": "productId", "in": "query", "schema": {"type": "string", "format": "uuid"}}
        - {"name": "postId", "in": "query", "schema": {"type": "string", "format": "uuid"}}
    "post":
      "tags":
        - "Media"
      "summary": "Eine zunächst private Datei hochladen"
      "security":
        - {"BearerAuth": []}
      "responses":
        "201":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Media"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "description": "Datei direkt als Request-Body, kein Multipart/FormData. Max. 5 MiB; Content-Type muss zur Signatur passen. Keine komprimierten Requests."
      "parameters":
        - {"name": "filename", "in": "query", "required": true, "schema": {"type": "string", "minLength": 1, "maxLength": 180}}
      "requestBody":
        "required": true
        "content":
          "image/png":
            "schema":
              "type": "string"
              "format": "binary"
          "image/jpeg":
            "schema":
              "type": "string"
              "format": "binary"
          "image/webp":
            "schema":
              "type": "string"
              "format": "binary"
          "application/pdf":
            "schema":
              "type": "string"
              "format": "binary"
  "/media/{id}":
    "get":
      "tags":
        - "Media"
      "summary": "Metadaten: öffentlich oder Eigentümer"
      "security": []
      "responses":
        "200":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Media"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
    "put":
      "tags":
        - "Media"
      "summary": "Eigene Datei veröffentlichen oder einem eigenen Produkt/Beitrag zuordnen"
      "security":
        - {"BearerAuth": []}
      "responses":
        "200":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Media"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "description": "Höchstens eine Zuordnung; mit null lösen. Veröffentlichung nur ausdrücklich über isPublic."
      "requestBody":
        "required": true
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/MediaUpdate"
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
    "delete":
      "tags":
        - "Media"
      "summary": "Eigene Datei und Metadaten löschen"
      "security":
        - {"BearerAuth": []}
      "responses":
        "204":
          "description": "Erfolg"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
  "/media/{id}/content":
    "get":
      "tags":
        - "Media"
      "summary": "Datei abrufen: öffentlich oder Eigentümer"
      "security": []
      "responses":
        "200":
          "description": "Erfolg"
          "content":
            "image/png":
              "schema":
                "type": "string"
                "format": "binary"
            "image/jpeg":
              "schema":
                "type": "string"
                "format": "binary"
            "image/webp":
              "schema":
                "type": "string"
                "format": "binary"
            "application/pdf":
              "schema":
                "type": "string"
                "format": "binary"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
      "description": "PNG/JPEG/WebP inline; PDF als Anhang. nosniff, CSP sandbox und Cache-Control private, no-store. Private Dateien benötigen einen Bearer-Token."
  "/events":
    "get":
      "tags":
        - "Events"
      "summary": "Öffentliche Termine (max. 100, Beginn aufsteigend)"
      "security": []
      "responses":
        "200":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "type": "array"
                "items":
                  "$ref": "#/components/schemas/Event"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
    "post":
      "tags":
        - "Events"
      "summary": "Termin anlegen; Veranstalter aus Anmeldung"
      "security":
        - {"BearerAuth": []}
      "responses":
        "201":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Event"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "requestBody":
        "required": true
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/EventCreate"
  "/events/{id}":
    "get":
      "tags":
        - "Events"
      "summary": "Termin und Zahl aktiver Anmeldungen"
      "security": []
      "responses":
        "200":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Event"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
    "put":
      "tags":
        - "Events"
      "summary": "Eigenen Termin ändern"
      "security":
        - {"BearerAuth": []}
      "responses":
        "200":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Event"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "description": "Ende nach Beginn. Kapazität darf nicht unter die aktuelle Zahl aktiver Anmeldungen sinken."
      "requestBody":
        "required": true
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/EventUpdate"
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
    "delete":
      "tags":
        - "Events"
      "summary": "Eigenen Termin samt Anmeldungen löschen"
      "security":
        - {"BearerAuth": []}
      "responses":
        "204":
          "description": "Erfolg"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
  "/events/{id}/registrations":
    "get":
      "tags":
        - "Events"
      "summary": "Anmeldeliste ausschließlich für Veranstalter"
      "security":
        - {"BearerAuth": []}
      "responses":
        "200":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "type": "array"
                "items":
                  "$ref": "#/components/schemas/EventRegistrationView"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
  "/events/{id}/registration":
    "get":
      "tags":
        - "Events"
      "summary": "Eigene Anmeldung und Status"
      "security":
        - {"BearerAuth": []}
      "responses":
        "200":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/EventRegistration"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
    "post":
      "tags":
        - "Events"
      "summary": "Selbst anmelden oder stornierte Anmeldung reaktivieren"
      "security":
        - {"BearerAuth": []}
      "responses":
        "201":
          "description": "Erfolg"
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/EventRegistration"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "description": "409 bei bereits aktiver Anmeldung, vollem oder begonnenem Termin. Ein Platz pro Person. Kapazitätsprüfung durch DB-Transaktion und Zeilensperre geschützt."
      "requestBody":
        "required": true
        "content":
          "application/json":
            "schema":
              "$ref": "#/components/schemas/EmptyInput"
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
    "delete":
      "tags":
        - "Events"
      "summary": "Eigene Anmeldung stornieren"
      "security":
        - {"BearerAuth": []}
      "responses":
        "204":
          "description": "Erfolg"
        "400":
          "$ref": "#/components/responses/Error400"
        "401":
          "$ref": "#/components/responses/Error401"
        "403":
          "$ref": "#/components/responses/Error403"
        "404":
          "$ref": "#/components/responses/Error404"
        "409":
          "$ref": "#/components/responses/Error409"
        "413":
          "$ref": "#/components/responses/Error413"
        "415":
          "$ref": "#/components/responses/Error415"
        "500":
          "$ref": "#/components/responses/Error500"
      "description": "Status CANCELLED; wiederholtes Stornieren ist erlaubt. Eine neue Anmeldung reaktiviert denselben Datensatz."
      "parameters":
        - {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
components:
  schemas:
    CategoryCreate:
      properties:
        name:
          type: string
          maxLength: 64
          minLength: 1
          title: Name
      additionalProperties: false
      type: object
      required:
      - name
      title: CategoryCreate
    ChatCreate:
      properties:
        recipientId:
          type: string
          pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$
          title: Recipientid
        message:
          type: string
          maxLength: 5000
          minLength: 1
          title: Message
      additionalProperties: false
      type: object
      required:
      - recipientId
      - message
      title: ChatCreate
    CommentCreate:
      properties:
        postId:
          type: string
          pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$
          title: Postid
        text:
          type: string
          maxLength: 5000
          minLength: 1
          title: Text
      additionalProperties: false
      type: object
      required:
      - postId
      - text
      title: CommentCreate
    CommentUpdate:
      properties:
        text:
          type: string
          maxLength: 5000
          minLength: 1
          title: Text
      additionalProperties: false
      type: object
      required:
      - text
      title: CommentUpdate
    Login:
      properties:
        email:
          type: string
          maxLength: 64
          minLength: 1
          title: Email
          format: email
        password:
          type: string
          maxLength: 72
          minLength: 1
          title: Password
          description: Höchstens 72 UTF-8-Bytes; Registrierung mindestens 10 Zeichen.
      additionalProperties: false
      type: object
      required:
      - email
      - password
      title: Login
    OrderCreate:
      properties:
        items:
          items:
            $ref: '#/components/schemas/OrderItemCreate'
          type: array
          maxItems: 100
          minItems: 1
          title: Items
      additionalProperties: false
      type: object
      required:
      - items
      title: OrderCreate
    OrderItemCreate:
      properties:
        productId:
          type: string
          pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$
          title: Productid
        quantity:
          type: integer
          maximum: 999.0
          minimum: 1.0
          title: Quantity
      additionalProperties: false
      type: object
      required:
      - productId
      - quantity
      title: OrderItemCreate
    PaymentCreate:
      properties:
        orderId:
          type: string
          pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$
          title: Orderid
        amount:
          type: number
          multipleOf: 0.01
          maximum: 9999.99
          exclusiveMinimum: 0.0
          title: Amount
        paymentMethod:
          type: string
          const: DEMO
          title: Paymentmethod
      additionalProperties: false
      type: object
      required:
      - orderId
      - amount
      - paymentMethod
      title: PaymentCreate
    PostCreate:
      properties:
        title:
          type: string
          maxLength: 64
          minLength: 1
          title: Title
        content:
          type: string
          maxLength: 20000
          minLength: 1
          title: Content
      additionalProperties: false
      type: object
      required:
      - title
      - content
      title: PostCreate
    PostUpdate:
      properties:
        title:
          title: Title
          type: string
          maxLength: 64
          minLength: 1
        content:
          title: Content
          type: string
          maxLength: 20000
          minLength: 1
      additionalProperties: false
      type: object
      title: PostUpdate
      minProperties: 1
    ProductCreate:
      properties:
        name:
          type: string
          maxLength: 64
          minLength: 1
          title: Name
        price:
          type: number
          multipleOf: 0.01
          maximum: 9999.99
          minimum: 0.0
          title: Price
        categoryId:
          anyOf:
          - type: string
            pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$
          - type: 'null'
          title: Categoryid
      additionalProperties: false
      type: object
      required:
      - name
      - price
      title: ProductCreate
    ProductUpdate:
      properties:
        name:
          title: Name
          type: string
          maxLength: 64
          minLength: 1
        price:
          title: Price
          type: number
          multipleOf: 0.01
          maximum: 9999.99
          minimum: 0.0
        categoryId:
          anyOf:
          - type: string
            pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$
          - type: 'null'
          title: Categoryid
      additionalProperties: false
      type: object
      title: ProductUpdate
      minProperties: 1
    ProfileUpdate:
      properties:
        name:
          title: Name
          type: string
          maxLength: 64
          minLength: 1
        userType:
          anyOf:
          - type: string
            maxLength: 64
            minLength: 1
          - type: 'null'
          title: Usertype
      additionalProperties: false
      type: object
      title: ProfileUpdate
      minProperties: 1
    RatingCreate:
      properties:
        productId:
          type: string
          pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$
          title: Productid
        stars:
          type: integer
          maximum: 5.0
          minimum: 1.0
          title: Stars
        text:
          anyOf:
          - type: string
            maxLength: 5000
          - type: 'null'
          title: Text
      additionalProperties: false
      type: object
      required:
      - productId
      - stars
      title: RatingCreate
    RatingUpdate:
      properties:
        stars:
          title: Stars
          type: integer
          maximum: 5.0
          minimum: 1.0
        text:
          anyOf:
          - type: string
            maxLength: 5000
          - type: 'null'
          title: Text
      additionalProperties: false
      type: object
      title: RatingUpdate
      minProperties: 1
    Register:
      properties:
        email:
          type: string
          maxLength: 64
          minLength: 1
          title: Email
          format: email
        password:
          type: string
          maxLength: 72
          minLength: 10
          title: Password
          description: Höchstens 72 UTF-8-Bytes; Registrierung mindestens 10 Zeichen.
        name:
          type: string
          maxLength: 64
          minLength: 1
          title: Name
      additionalProperties: false
      type: object
      required:
      - email
      - password
      - name
      title: Register
    StatusUpdate:
      properties:
        status:
          type: string
          const: CANCELLED
          title: Status
      additionalProperties: false
      type: object
      required:
      - status
      title: StatusUpdate
    Category:
      properties:
        id:
          type: string
        name:
          type: string
      required:
      - id
      - name
      type: object
    ChatMessage:
      properties:
        id:
          type: string
        senderId:
          type: string
        recipientId:
          type: string
        message:
          type: string
        sentAt:
          format: date-time
          type: string
      required:
      - id
      - senderId
      - recipientId
      - message
      - sentAt
      type: object
    Comment:
      properties:
        id:
          type: string
        userId:
          type: string
        postId:
          type: string
        text:
          anyOf:
          - type: string
          - type: 'null'
        createdAt:
          format: date-time
          type: string
      required:
      - id
      - userId
      - postId
      - text
      - createdAt
      type: object
    Order:
      properties:
        id:
          type: string
        userId:
          type: string
        orderDate:
          format: date-time
          type: string
        amount:
          type: string
          pattern: ^\d+(\.\d{1,2})?$
          description: Dezimalstring ohne Gleitkomma-Verlust, z. B. 12.34
        status:
          type: string
        type:
          type: string
      required:
      - id
      - userId
      - orderDate
      - amount
      - status
      - type
      type: object
    OrderItem:
      properties:
        id:
          type: string
        orderId:
          type: string
        productId:
          type: string
        quantity:
          type: integer
        singlePrice:
          type: string
          pattern: ^\d+(\.\d{1,2})?$
          description: Dezimalstring ohne Gleitkomma-Verlust, z. B. 12.34
      required:
      - id
      - orderId
      - productId
      - quantity
      - singlePrice
      type: object
    Payment:
      properties:
        id:
          type: string
        status:
          type: string
        postDate:
          format: date-time
          type: string
        orderId:
          type: string
        paymentMethod:
          anyOf:
          - type: string
          - type: 'null'
        amount:
          type:
          - string
          - 'null'
          pattern: ^\d+(\.\d{1,2})?$
          description: Dezimalstring ohne Gleitkomma-Verlust, z. B. 12.34
      required:
      - id
      - status
      - postDate
      - orderId
      - paymentMethod
      - amount
      type: object
    Post:
      properties:
        id:
          type: string
        content:
          type: string
        userId:
          type: string
        createdAt:
          format: date-time
          type: string
      required:
      - id
      - content
      - userId
      - createdAt
      type: object
    Product:
      properties:
        id:
          type: string
        name:
          type: string
        price:
          type: string
          pattern: ^\d+(\.\d{1,2})?$
          description: Dezimalstring ohne Gleitkomma-Verlust, z. B. 12.34
        categoryId:
          anyOf:
          - type: string
          - type: 'null'
        creatorId:
          anyOf:
          - type: string
          - type: 'null'
      required:
      - id
      - name
      - price
      - categoryId
      - creatorId
      type: object
    ProductAttribute:
      properties:
        id:
          type: string
        key:
          type: string
        value:
          anyOf:
          - type: string
          - type: 'null'
        productId:
          type: string
      required:
      - id
      - key
      - value
      - productId
      type: object
    Rating:
      properties:
        id:
          type: string
        productId:
          type: string
        customerId:
          type: string
        stars:
          anyOf:
          - type: integer
          - type: 'null'
        text:
          anyOf:
          - type: string
          - type: 'null'
      required:
      - id
      - productId
      - customerId
      - stars
      - text
      type: object
    ShoppingCartItem:
      properties:
        id:
          type: string
        userId:
          type: string
        productId:
          type: string
        quantity:
          type: integer
      required:
      - id
      - userId
      - productId
      - quantity
      type: object
    UserAttribute:
      properties:
        id:
          type: string
        userId:
          type: string
        key:
          type: string
        value:
          anyOf:
          - type: string
          - type: 'null'
      required:
      - id
      - userId
      - key
      - value
      type: object
    UserFollower:
      properties:
        followeeId:
          type: string
        followerId:
          type: string
        followedAt:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
      required:
      - followeeId
      - followerId
      - followedAt
      type: object
    PublicUser:
      type: object
      properties:
        id: &id002
          type: string
          format: uuid
        name: *id001
      required:
      - id
      - name
    RegisteredUser:
      type: object
      properties:
        id: *id002
        name: *id001
        email: &id003
          type: string
          format: email
      required:
      - id
      - name
      - email
    Profile:
      type: object
      properties:
        id: *id002
        name: *id001
        email: *id003
        userType:
          type:
          - string
          - 'null'
          description: Profilinformation, keine Berechtigungsrolle.
      required:
      - id
      - name
      - email
      - userType
    Token:
      type: object
      properties:
        token: *id001
      required:
      - token
    Error:
      type: object
      properties:
        message: *id001
      required:
      - message
    RatingView:
      allOf:
      - $ref: '#/components/schemas/Rating'
      - type: object
        properties:
          customer:
            $ref: '#/components/schemas/PublicUser'
        required:
        - customer
    CommentView:
      allOf:
      - $ref: '#/components/schemas/Comment'
      - type: object
        properties:
          user:
            $ref: '#/components/schemas/PublicUser'
        required:
        - user
    PostView:
      allOf:
      - $ref: '#/components/schemas/Post'
      - type: object
        properties:
          author:
            $ref: '#/components/schemas/PublicUser'
        required:
        - author
    PostDetail:
      allOf:
      - $ref: '#/components/schemas/PostView'
      - type: object
        properties:
          comments:
            type: array
            items:
              $ref: '#/components/schemas/CommentView'
        required:
        - comments
    ProductView:
      allOf:
      - $ref: '#/components/schemas/Product'
      - type: object
        properties:
          category:
            anyOf:
            - $ref: '#/components/schemas/Category'
            - type: 'null'
          creator:
            anyOf:
            - $ref: '#/components/schemas/PublicUser'
            - type: 'null'
        required:
        - category
        - creator
    ProductDetail:
      allOf:
      - $ref: '#/components/schemas/ProductView'
      - type: object
        properties:
          attributes:
            type: array
            items:
              $ref: '#/components/schemas/ProductAttribute'
          ratings:
            type: array
            items:
              $ref: '#/components/schemas/RatingView'
        required:
        - attributes
        - ratings
    ChatView:
      allOf:
      - $ref: '#/components/schemas/ChatMessage'
      - type: object
        properties:
          sender:
            $ref: '#/components/schemas/PublicUser'
          recipient:
            $ref: '#/components/schemas/PublicUser'
        required:
        - sender
        - recipient
    OrderItemView:
      allOf:
      - $ref: '#/components/schemas/OrderItem'
      - type: object
        properties:
          product:
            $ref: '#/components/schemas/Product'
        required:
        - product
    CreatedOrder:
      allOf:
      - $ref: '#/components/schemas/Order'
      - type: object
        properties:
          items:
            type: array
            items:
              $ref: '#/components/schemas/OrderItem'
        required:
        - items
    BookingView:
      allOf:
      - $ref: '#/components/schemas/Order'
      - type: object
        properties:
          items:
            type: array
            items:
              $ref: '#/components/schemas/OrderItemView'
        required:
        - items
    OrderView:
      allOf:
      - $ref: '#/components/schemas/BookingView'
      - type: object
        properties:
          payments:
            type: array
            items:
              $ref: '#/components/schemas/Payment'
        required:
        - payments
    BookingDetail:
      allOf:
      - $ref: '#/components/schemas/BookingView'
      - type: object
        properties:
          user:
            $ref: '#/components/schemas/RegisteredUser'
        required:
        - user
    OrderDetail:
      allOf:
      - $ref: '#/components/schemas/OrderView'
      - type: object
        properties:
          user:
            $ref: '#/components/schemas/RegisteredUser'
        required:
        - user
    "Media":
      "type": "object"
      "properties":
        "id":
          "type": "string"
          "format": "uuid"
        "ownerId":
          "type": "string"
          "format": "uuid"
        "originalName":
          "type": "string"
          "maxLength": 180
        "mimeType":
          "enum":
            - "image/png"
            - "image/jpeg"
            - "image/webp"
            - "application/pdf"
        "size":
          "type": "integer"
          "minimum": 1
          "maximum": 5242880
        "isPublic":
          "type": "boolean"
        "productId":
          "type":
            - "string"
            - "null"
          "format": "uuid"
        "postId":
          "type":
            - "string"
            - "null"
          "format": "uuid"
        "createdAt":
          "type": "string"
          "format": "date-time"
        "url":
          "type": "string"
      "required":
        - "id"
        - "ownerId"
        - "originalName"
        - "mimeType"
        - "size"
        - "isPublic"
        - "productId"
        - "postId"
        - "createdAt"
        - "url"
      "additionalProperties": false
    "MediaUpdate":
      "type": "object"
      "properties":
        "isPublic":
          "type": "boolean"
        "productId":
          "type":
            - "string"
            - "null"
          "format": "uuid"
        "postId":
          "type":
            - "string"
            - "null"
          "format": "uuid"
      "required": []
      "additionalProperties": false
      "minProperties": 1
    "EventCreate":
      "type": "object"
      "properties":
        "title":
          "type": "string"
          "minLength": 1
          "maxLength": 128
        "description":
          "type": "string"
          "maxLength": 20000
        "startsAt":
          "type": "string"
          "format": "date-time"
          "pattern": "^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(?:\\.\\d{3})?Z$"
          "description": "UTC mit Z; Sekunden oder genau drei Millisekundenstellen."
        "endsAt":
          "type": "string"
          "format": "date-time"
          "pattern": "^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(?:\\.\\d{3})?Z$"
          "description": "UTC mit Z; Sekunden oder genau drei Millisekundenstellen."
        "location":
          "type":
            - "string"
            - "null"
          "minLength": 1
          "maxLength": 255
        "capacity":
          "type":
            - "integer"
            - "null"
          "minimum": 1
          "maximum": 100000
      "required":
        - "title"
        - "description"
        - "startsAt"
        - "endsAt"
      "additionalProperties": false
    "EventUpdate":
      "type": "object"
      "properties":
        "title":
          "type": "string"
          "minLength": 1
          "maxLength": 128
        "description":
          "type": "string"
          "maxLength": 20000
        "startsAt":
          "type": "string"
          "format": "date-time"
          "pattern": "^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(?:\\.\\d{3})?Z$"
          "description": "UTC mit Z; Sekunden oder genau drei Millisekundenstellen."
        "endsAt":
          "type": "string"
          "format": "date-time"
          "pattern": "^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(?:\\.\\d{3})?Z$"
          "description": "UTC mit Z; Sekunden oder genau drei Millisekundenstellen."
        "location":
          "type":
            - "string"
            - "null"
          "minLength": 1
          "maxLength": 255
        "capacity":
          "type":
            - "integer"
            - "null"
          "minimum": 1
          "maximum": 100000
      "required": []
      "additionalProperties": false
      "minProperties": 1
    "Event":
      "type": "object"
      "properties":
        "id":
          "type": "string"
          "format": "uuid"
        "organizerId":
          "type": "string"
          "format": "uuid"
        "title":
          "type": "string"
          "minLength": 1
          "maxLength": 128
        "description":
          "type": "string"
          "maxLength": 20000
        "startsAt":
          "type": "string"
          "format": "date-time"
          "pattern": "^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(?:\\.\\d{3})?Z$"
          "description": "UTC mit Z; Sekunden oder genau drei Millisekundenstellen."
        "endsAt":
          "type": "string"
          "format": "date-time"
          "pattern": "^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(?:\\.\\d{3})?Z$"
          "description": "UTC mit Z; Sekunden oder genau drei Millisekundenstellen."
        "location":
          "type":
            - "string"
            - "null"
          "minLength": 1
          "maxLength": 255
        "capacity":
          "type":
            - "integer"
            - "null"
          "minimum": 1
          "maximum": 100000
        "createdAt":
          "type": "string"
          "format": "date-time"
        "registrationCount":
          "type": "integer"
          "minimum": 0
      "required":
        - "id"
        - "organizerId"
        - "title"
        - "description"
        - "startsAt"
        - "endsAt"
        - "location"
        - "capacity"
        - "createdAt"
        - "registrationCount"
      "additionalProperties": false
    "EventRegistration":
      "type": "object"
      "properties":
        "id":
          "type": "string"
          "format": "uuid"
        "eventId":
          "type": "string"
          "format": "uuid"
        "userId":
          "type": "string"
          "format": "uuid"
        "status":
          "enum":
            - "REGISTERED"
            - "CANCELLED"
        "registeredAt":
          "type": "string"
          "format": "date-time"
      "required":
        - "id"
        - "eventId"
        - "userId"
        - "status"
        - "registeredAt"
      "additionalProperties": false
    "EventRegistrationView":
      "type": "object"
      "properties":
        "id":
          "type": "string"
          "format": "uuid"
        "eventId":
          "type": "string"
          "format": "uuid"
        "userId":
          "type": "string"
          "format": "uuid"
        "status":
          "enum":
            - "REGISTERED"
            - "CANCELLED"
        "registeredAt":
          "type": "string"
          "format": "date-time"
        "user":
          "$ref": "#/components/schemas/PublicUser"
      "required":
        - "id"
        - "eventId"
        - "userId"
        - "status"
        - "registeredAt"
        - "user"
      "additionalProperties": false
    "EmptyInput":
      "type": "object"
      "properties": {}
      "required": []
      "additionalProperties": false
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  responses:
    Error400:
      description: Ungültige Eingabe
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Error401:
      description: Anmeldung fehlt/ungültig
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Error403:
      description: Zugriff verweigert
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Error404:
      description: Nicht gefunden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Error409:
      description: Datenkonflikt
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Error413:
      description: Anfrage zu groß
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Error500:
      description: Interner Fehler
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Error503:
      description: Datenbank nicht verfügbar
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    "Error415":
      "description": "Nicht unterstützter Dateityp oder Content-Encoding"
      "content":
        "application/json":
          "schema":
            "$ref": "#/components/schemas/Error"
servers:
- url: /api
