openapi: 3.0.3
info:
  title: ZEP REST API
  description: This is the ZEP REST API based on the OpenAPI 3.0 specification.
  contact:
    email: support@zep.de
  version: 7.12.49
externalDocs:
  description: Developer Hub
  url: https://developer.zep.de
tags:
- name: Projects
  description: You can use this endpoint get a paginated list of all projects.
- name: Attendances
  description: You can use this endpoint get a paginated list of all attendances.
- name: Employees
  description: You can use this endpoint get a paginated list of all employees.
- name: Customers
  description: You can use this endpoint get a paginated list of all customers.
- name: Absences
  description: You can use this endpoint get a paginated list of all absences.
- name: Departments
  description: You can use this endpoint get a paginated list of all departments.
- name: Devices
  description: You can use this endpoint get a paginated list of all devices.
- name: Receipts
  description: You can use this endpoint get a paginated list of all receipts.
- name: Tickets
  description: You can use this endpoint get a paginated list of all tickets.
- name: Invoices
  description: You can use this endpoint get a paginated list of all invoices.
- name: Offers
  description: You can use this endpoint get a paginated list of all offers.
- name: Articles
  description: You can use this endpoint get a paginated list of all articles.
- name: WorkhourBalances
  description: Read-only access to the cached overtime and vacation entitlement balances (previous-day
    snapshot per employee).
- name: Documents
  description: Document folders and their documents.
- name: Masterdata
  description: Master data resources (price groups, activities, absence reasons, categories, location
    lists, locations, dynamic attributes).
- name: Plannings
  description: You can use this endpoint to get a paginated list of all planning entries.
paths:
  /projects:
    get:
      tags:
      - Projects
      description: Get all projects
      parameters:
      - name: start_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: end_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: id[]
        in: query
        required: false
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
    post:
      tags:
      - Projects
      description: Create a new project. Project names can be auto-generated based on system configuration.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - name
              - department_id
              - start_date
              properties:
                name:
                  type: string
                  maxLength: 64
                  description: Unique project name/identifier. Must contain only valid characters and
                    be unique. May be auto-generated if system config enabled.
                department_id:
                  type: integer
                  description: Department ID (must exist in departments table). Defaults to standard department
                    if not provided.
                description:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Project description
                start_date:
                  type: string
                  format: date
                  description: Project start date (required, Y-m-d format)
                end_date:
                  type: string
                  format: date
                  nullable: true
                  description: Project end date (must be after start_date if provided)
                location_address:
                  type: string
                  maxLength: 64
                  nullable: true
                  description: Project location street address
                location_city:
                  type: string
                  maxLength: 64
                  nullable: true
                  description: Project location city
                location_state:
                  type: string
                  maxLength: 64
                  nullable: true
                  description: Project location state/province
                location_country:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Project location country
                comments:
                  type: string
                  nullable: true
                  description: Additional comments about the project
                plan_expenses:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                  description: Planned expenses budget
                plan_hours:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                  description: Planned hours budget
                plan_wage:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                  description: Planned wage/salary budget
                plan_expenses_travel:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                  description: Planned travel expenses
                cost_object:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Cost object identifier
                plan_hours_done:
                  type: number
                  format: float
                  nullable: true
                  description: Hours completed against plan
                plan_hours_invoiced:
                  type: number
                  format: float
                  nullable: true
                  description: Hours invoiced
                customer_project_reference:
                  type: string
                  maxLength: 64
                  nullable: true
                  description: Customer's project reference number
                customer_billing_address_id:
                  type: integer
                  nullable: true
                  description: Customer billing address ID (must exist)
                customer_shipping_address_id:
                  type: integer
                  nullable: true
                  description: Customer shipping address ID (must exist)
                has_multiple_customers:
                  type: boolean
                  nullable: true
                  description: Whether project has multiple customers
                cost_object_identifier:
                  type: string
                  nullable: true
                  description: Cost center identifier. Type (string/integer) depends on system configuration.
                  oneOf:
                  - type: string
                    maxLength: 32
                  - type: integer
                    minimum: 0
                project_status_id:
                  type: string
                  maxLength: 64
                  nullable: true
                  description: Project status name (must exist in project_statuses table)
                billing_type:
                  type: integer
                  nullable: true
                  description: Billing type enum value
                default_billability:
                  type: integer
                  nullable: true
                  description: Default billability setting enum value
                receipts_billability:
                  type: integer
                  nullable: true
                  description: Receipts billability enum value. Set to NEVER for intern projects without
                    customer.
                currency:
                  type: string
                  nullable: true
                  description: Currency code (must exist in currencies table)
                language:
                  type: integer
                  nullable: true
                  description: Project language enum value
                url:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Project URL
                reference_commission:
                  type: string
                  maxLength: 100
                  nullable: true
                  description: Commission reference
                reference_procurement:
                  type: string
                  maxLength: 100
                  nullable: true
                  description: Procurement reference
                reference_object:
                  type: string
                  maxLength: 100
                  nullable: true
                  description: Object reference
                reference_order:
                  type: string
                  maxLength: 100
                  nullable: true
                  description: Order reference
                indicate_hours_for_daily_proof:
                  type: integer
                  nullable: true
                  description: Setting for indicating hours in daily proof
                indicate_remarks_for_daily_proof:
                  type: integer
                  nullable: true
                  description: Setting for indicating remarks in daily proof
                indicate_all_locations_per_day:
                  type: integer
                  nullable: true
                  description: Setting for showing all locations per day
                also_take_into_account_the_price_factors_for_hourly_rates:
                  type: integer
                  nullable: true
                  description: Setting for price factors in hourly rates
                indicate_all_activities_per_day:
                  type: integer
                  nullable: true
                  description: Setting for showing all activities per day
                employee_name_time_report_format:
                  type: integer
                  nullable: true
                  description: Format for employee names in time reports
                employee_name_project_sales_volume_format:
                  type: integer
                  nullable: true
                  description: Format for employee names in sales volume
                employee_name_invoice_attachment_format:
                  type: integer
                  nullable: true
                  description: Format for employee names in invoice attachments
                travel_flat_rate:
                  type: number
                  format: float
                  nullable: true
                  description: Travel flat rate amount
                billing_tasks:
                  type: boolean
                  nullable: true
                  description: Enable billing tasks
                revenue_account:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Revenue account number
                plan_hours_children:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                  description: Planned hours for child projects
                plan_hours_per_day:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                  description: Planned hours per day
                plan_warning_percent:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                  description: First warning threshold percentage
                plan_warning_percent_2:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                  description: Second warning threshold percentage
                plan_warning_percent_3:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                  description: Third warning threshold percentage
                plan_can_exceed:
                  type: boolean
                  nullable: true
                  description: Whether plan can be exceeded
                keywords:
                  type: array
                  nullable: true
                  description: Array of project keywords/tags
                  items:
                    type: string
                dynamic_attributes:
                  type: array
                  nullable: true
                  description: Custom dynamic attributes
                  items:
                    type: object
                categories:
                  type: array
                  nullable: true
                  description: Array of category IDs
                  items:
                    type: integer
                customer_id:
                  type: integer
                  nullable: true
                  description: Customer ID (customer_number from customers table). Set to null for intern
                    projects.
                customer_contact_id:
                  type: integer
                  nullable: true
                  description: Customer contact person ID (must exist in customer_contacts table)
      responses:
        '201':
          description: Project created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Project'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '422':
          description: Validation error. One or more fields failed validation constraints.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Error message
                  errors:
                    type: object
                    description: Field-specific validation errors
                    additionalProperties:
                      type: array
                      items:
                        type: string
  /projects/{id}:
    get:
      tags:
      - Projects
      description: Get project by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectWithPricesResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Projects
      description: Update an existing project. All fields are optional; only provided fields will be updated.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
        description: Project ID to update
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  maxLength: 64
                  description: Project name/identifier (must be unique if provided)
                department_id:
                  type: integer
                  description: Department ID
                description:
                  type: string
                  maxLength: 255
                  nullable: true
                start_date:
                  type: string
                  format: date
                  nullable: true
                end_date:
                  type: string
                  format: date
                  nullable: true
                  description: Must be after start_date if both provided
                location_address:
                  type: string
                  maxLength: 64
                  nullable: true
                location_city:
                  type: string
                  maxLength: 64
                  nullable: true
                location_state:
                  type: string
                  maxLength: 64
                  nullable: true
                location_country:
                  type: string
                  maxLength: 32
                  nullable: true
                comments:
                  type: string
                  nullable: true
                plan_expenses:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                plan_hours:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                plan_wage:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                plan_expenses_travel:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                cost_object:
                  type: string
                  maxLength: 32
                  nullable: true
                plan_hours_done:
                  type: number
                  format: float
                  nullable: true
                plan_hours_invoiced:
                  type: number
                  format: float
                  nullable: true
                customer_project_reference:
                  type: string
                  maxLength: 64
                  nullable: true
                customer_billing_address_id:
                  type: integer
                  nullable: true
                customer_shipping_address_id:
                  type: integer
                  nullable: true
                has_multiple_customers:
                  type: boolean
                  nullable: true
                cost_object_identifier:
                  type: string
                  nullable: true
                  oneOf:
                  - type: string
                    maxLength: 32
                  - type: integer
                    minimum: 0
                project_status_id:
                  type: string
                  maxLength: 64
                  nullable: true
                billing_type:
                  type: integer
                  nullable: true
                default_billability:
                  type: integer
                  nullable: true
                receipts_billability:
                  type: integer
                  nullable: true
                currency:
                  type: string
                  nullable: true
                language:
                  type: integer
                  nullable: true
                url:
                  type: string
                  maxLength: 255
                  nullable: true
                reference_commission:
                  type: string
                  maxLength: 100
                  nullable: true
                reference_procurement:
                  type: string
                  maxLength: 100
                  nullable: true
                reference_object:
                  type: string
                  maxLength: 100
                  nullable: true
                reference_order:
                  type: string
                  maxLength: 100
                  nullable: true
                indicate_hours_for_daily_proof:
                  type: integer
                  nullable: true
                indicate_remarks_for_daily_proof:
                  type: integer
                  nullable: true
                indicate_all_locations_per_day:
                  type: integer
                  nullable: true
                also_take_into_account_the_price_factors_for_hourly_rates:
                  type: integer
                  nullable: true
                indicate_all_activities_per_day:
                  type: integer
                  nullable: true
                employee_name_time_report_format:
                  type: integer
                  nullable: true
                employee_name_project_sales_volume_format:
                  type: integer
                  nullable: true
                employee_name_invoice_attachment_format:
                  type: integer
                  nullable: true
                travel_flat_rate:
                  type: number
                  format: float
                  nullable: true
                billing_tasks:
                  type: boolean
                  nullable: true
                revenue_account:
                  type: string
                  maxLength: 32
                  nullable: true
                plan_hours_children:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                plan_hours_per_day:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                plan_warning_percent:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                plan_warning_percent_2:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                plan_warning_percent_3:
                  type: number
                  format: float
                  nullable: true
                  minimum: 0
                plan_can_exceed:
                  type: integer
                  nullable: true
                  description: Plan can exceed option enum value
                keywords:
                  type: array
                  nullable: true
                  items:
                    type: string
                dynamic_attributes:
                  type: array
                  nullable: true
                  items:
                    type: object
                categories:
                  type: array
                  nullable: true
                  items:
                    type: integer
                customer_id:
                  type: integer
                  nullable: true
                customer_contact_id:
                  type: integer
                  nullable: true
      responses:
        '200':
          description: Project updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Project'
                  info:
                    type: object
                    nullable: true
                    description: Optional consistency information when project data was adjusted during
                      update
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    additionalProperties:
                      type: array
                      items:
                        type: string
    delete:
      tags:
      - Projects
      description: Delete a project by ID. This operation permanently removes the project from the system.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
        description: Project ID to delete
      responses:
        '200':
          description: Project deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Success message
                    example: Project deleted successfully
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          description: Project could not be deleted. This may occur if the project has related records
            that prevent deletion.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Error message
                    example: Project could not be deleted
  /projects/{id}/activities:
    get:
      tags:
      - Projects
      description: Get project activities
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActivitiesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{id}/employees:
    get:
      tags:
      - Projects
      description: Get the employees of a project
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectEmployeesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{id}/tasks:
    get:
      tags:
      - Projects
      description: Get project tasks
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: start_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: end_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectTasksListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      tags:
      - Projects
      description: Create a new project task
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
        description: Project ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - name
              - status_id
              properties:
                name:
                  type: string
                  maxLength: 64
                  description: Task name/identifier
                description:
                  type: string
                  nullable: true
                  description: Task description
                status_id:
                  type: string
                  description: Project task status identifier
                billing_type:
                  type: integer
                  nullable: true
                  enum:
                  - 0
                  - 1
                  - 2
                  - 3
                  description: Billing type (0 = Like project, 1 = Hourly rate, 2 = Daily rate, 3 = Flat
                    rate)
                start_date:
                  type: string
                  format: date
                  nullable: true
                  description: Task start date (must be >= project start date if set)
                end_date:
                  type: string
                  format: date
                  nullable: true
                  description: Task end date (must be > start_date and <= project end date if set)
                parent_id:
                  type: integer
                  nullable: true
                  description: Parent task ID for creating subtasks
                dynamic_attributes:
                  type: array
                  nullable: true
                  items:
                    type: object
                project_id:
                  type: integer
      responses:
        '201':
          description: Project task created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectTask'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ProjectTask'
  /projects/{id}/tasks/{task_id}:
    get:
      tags:
      - Projects
      description: Get project task by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: task_id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectTaskResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Projects
      summary: Update a project task
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: task_id
        in: path
        required: true
        schema:
          type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
    delete:
      tags:
      - Projects
      summary: Delete a project task
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: task_id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      summary: Update a project task
      tags:
      - Projects
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - id
              - project_id
              - name
              - status_id
              properties:
                id:
                  type: integer
                project_id:
                  type: integer
                name:
                  type: string
                  maxLength: 64
                description:
                  type: string
                  nullable: true
                status_id:
                  type: string
                billing_type:
                  type: string
                  nullable: true
                start_date:
                  type: string
                  format: date
                  nullable: true
                end_date:
                  type: string
                  format: date
                  nullable: true
                parent_id:
                  type: integer
                  nullable: true
                dynamic_attributes:
                  type: array
                  nullable: true
                  items:
                    type: object
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ProjectTask'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
  /projects/{id}/price-tables:
    get:
      tags:
      - Projects
      description: Get project price tables
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: fallback
        in: query
        required: false
        description: Include fallback (base) price table
        schema:
          type: boolean
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectPriceTablesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /attendances:
    get:
      tags:
      - Attendances
      description: Get all attendances
      parameters:
      - name: start_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: end_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: employee_id
        in: query
        required: false
        schema:
          type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AttendancesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
    post:
      tags:
      - Attendances
      description: Create a new attendance
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - employee_id
              - date
              - from
              - to
              - project_task_id
              - project_id
              - activity_id
              properties:
                employee_id:
                  type: string
                  description: The username of the employee creating the project time entry.
                date:
                  type: string
                  format: date
                  description: The date of the project time entry.
                from:
                  type: string
                  format: time
                  description: Start time of the project time entry (format H:i:s).
                to:
                  type: string
                  format: time
                  description: End time of the project time entry (format H:i:s). Must be after `from`.
                project_task_id:
                  type: integer
                  description: The ID of the related project task.
                project_id:
                  type: integer
                  description: The ID of the related project.
                activity_id:
                  type: string
                  description: The ID of the associated activity.
                duration:
                  type: number
                  format: float
                  description: Total duration of the project time in hours.
                  nullable: true
                locked:
                  type: boolean
                  description: Indicates whether the project time entry is locked.
                  default: false
                is_travel:
                  type: boolean
                  description: Indicates whether this time entry counts as travel time.
                  default: false
                billable:
                  type: boolean
                  description: Indicates whether the time entry is billable.
                  default: false
                work_location_is_project_relevant:
                  type: boolean
                  description: Indicates whether the work location is project-related.
                  default: false
                color:
                  type: string
                  pattern: ^#(?:[0-9a-fA-F]{3}){1,2}$
                  description: Hex color value (e.g.
                  nullable: true
                start:
                  type: string
                  description: Starting point of the trip.
                  nullable: true
                destination:
                  type: string
                  description: Destination of the trip.
                  nullable: true
                vehicle_id:
                  type: integer
                  description: The ID of the vehicle used.
                  nullable: true
                private:
                  type: boolean
                  description: Indicates whether the trip was private.
                  default: false
                km:
                  type: integer
                  description: Distance traveled in kilometers.
                  nullable: true
                passengers:
                  type: integer
                  description: Number of passengers.
                  nullable: true
                direction_of_travel:
                  type: string
                  enum:
                  - outbound
                  - return
                  - continue
                  description: Direction of travel (e.g. continue).
                  nullable: true
                note:
                  type: string
                  nullable: true
                project_release:
                  type: string
                  nullable: true
                  description: ProjectRelease enum.
                project_released_at:
                  type: string
                  format: date
                  nullable: true
                project_released_by:
                  type: string
                  nullable: true
                work_location_id:
                  type: string
                  nullable: true
                  description: Must exist for the given project_id.
      responses:
        '201':
          description: Attendance created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Attendance'
        '400':
          description: Invalid input
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '200':
          description: Attendance created successfully (main@7.12.35 reports this same success as HTTP
            200 instead of 201; documented here rather than silently dropped.)
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Attendance'
  /employees:
    get:
      tags:
      - Employees
      description: Get all employees
      parameters:
      - name: personal_number[]
        in: query
        required: false
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployeesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
    post:
      tags:
      - Employees
      description: Create a new employee
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - username
              - firstname
              - lastname
              - email
              - password
              - price_group
              properties:
                username:
                  type: string
                  description: Unique username (5–255 characters)
                  minLength: 1
                  maxLength: 32
                firstname:
                  type: string
                  description: First name
                  maxLength: 32
                lastname:
                  type: string
                  description: Last name
                  maxLength: 64
                email:
                  type: string
                  format: email
                  description: Unique email address
                  maxLength: 64
                password:
                  type: string
                  format: password
                  description: Password (min. 8 characters, max. 48)
                  minLength: 8
                  maxLength: 64
                personal_number:
                  type: string
                  nullable: true
                  description: Personal number (optional, unique)
                  maxLength: 32
                birthdate:
                  type: string
                  format: date
                  nullable: true
                  description: Birth date
                phone:
                  type: string
                  nullable: true
                  description: Work phone number
                department_id:
                  type: integer
                  nullable: true
                  description: Department ID
                rights:
                  type: string
                  nullable: true
                  enum:
                  - 0
                  - 1
                  - 2
                  - 3
                  - 4
                  description: Access rights
                employment:
                  type: string
                  nullable: true
                  enum:
                  - 0
                  - 1
                  - 2
                  description: Type of employment
                price_group:
                  type: string
                  description: Name of the price group
                oauthUsername:
                  type: string
                  nullable: true
                  description: OAuth username (must be unique)
                street:
                  type: string
                  nullable: true
                  maxLength: 64
                zip:
                  type: string
                  nullable: true
                  maxLength: 32
                city:
                  type: string
                  nullable: true
                  maxLength: 64
                country:
                  type: string
                  nullable: true
                  maxLength: 64
                abbreviation:
                  type: string
                  nullable: true
                  maxLength: 32
                salutation:
                  type: string
                  nullable: true
                title:
                  type: string
                  nullable: true
                  maxLength: 32
                mobile:
                  type: string
                  nullable: true
                  maxLength: 32
                fax:
                  type: string
                  nullable: true
                  maxLength: 32
                private_phone:
                  type: string
                  nullable: true
                  maxLength: 32
                iban:
                  type: string
                  nullable: true
                  maxLength: 34
                bic:
                  type: string
                  nullable: true
                  maxLength: 11
                account_no:
                  type: string
                  nullable: true
                  maxLength: 32
                bank_name:
                  type: string
                  nullable: true
                  maxLength: 64
                bank_code:
                  type: string
                  nullable: true
                  maxLength: 32
                currency:
                  type: string
                  nullable: true
                  maxLength: 32
                approval_date:
                  type: string
                  format: date
                  nullable: true
                vat:
                  type: string
                  nullable: true
                personio_id:
                  type: string
                  nullable: true
                  maxLength: 32
                cost_bearer:
                  type: string
                  nullable: true
                  maxLength: 32
                tax_id:
                  type: string
                  nullable: true
                  maxLength: 32
                creditor_number:
                  type: string
                  nullable: true
                  maxLength: 32
                categories:
                  type: array
                  items:
                    type: string
                  nullable: true
                dynamicAttributes:
                  type: array
                  items:
                    type: object
                  nullable: true
                birth_date:
                  type: string
                  format: date
                  nullable: true
                connector_external_ids:
                  type: array
                  nullable: true
                  items:
                    type: string
                cost_accounting_ads:
                  type: boolean
                  nullable: true
                oauth_username:
                  type: string
                  nullable: true
                  description: Unique.
      responses:
        '201':
          description: Employee created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Employee'
        '400':
          description: Invalid input
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '409':
          description: Duplicate field value (e.g. username, email)
        '200':
          description: Employee created successfully (main@7.12.35 reports this same success as HTTP 200
            instead of 201; documented here rather than silently dropped.)
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Employee'
  /employees/{username}:
    get:
      tags:
      - Employees
      description: Get employee by username
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployeeResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Employees
      summary: Update an employee
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                firstname:
                  type: string
                  maxLength: 255
                lastname:
                  type: string
                  maxLength: 255
                email:
                  type: string
                  format: email
                  maxLength: 255
                  description: Unique (excluding current employee).
                price_group:
                  type: string
                  description: PriceGroup name. Must exist.
                personal_number:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Unique (excluding current employee).
                birth_date:
                  type: string
                  format: date
                  nullable: true
                phone:
                  type: string
                  nullable: true
                department_id:
                  type: integer
                  nullable: true
                rights:
                  type: string
                  nullable: true
                  description: EmployeeRights enum.
                employment:
                  type: string
                  nullable: true
                  description: EmploymentType enum.
                oauth_username:
                  type: string
                  nullable: true
                  description: Unique (excluding current employee).
                salutation:
                  type: string
                  nullable: true
                street:
                  type: string
                  maxLength: 64
                  nullable: true
                zip:
                  type: string
                  maxLength: 32
                  nullable: true
                city:
                  type: string
                  maxLength: 64
                  nullable: true
                country:
                  type: string
                  maxLength: 64
                  nullable: true
                abbreviation:
                  type: string
                  maxLength: 32
                  nullable: true
                title:
                  type: string
                  maxLength: 32
                  nullable: true
                mobile:
                  type: string
                  maxLength: 32
                  nullable: true
                fax:
                  type: string
                  maxLength: 32
                  nullable: true
                private_phone:
                  type: string
                  maxLength: 32
                  nullable: true
                iban:
                  type: string
                  maxLength: 34
                  nullable: true
                bic:
                  type: string
                  maxLength: 11
                  nullable: true
                account_no:
                  type: string
                  maxLength: 32
                  nullable: true
                bank_name:
                  type: string
                  maxLength: 64
                  nullable: true
                bank_code:
                  type: string
                  maxLength: 32
                  nullable: true
                currency:
                  type: string
                  maxLength: 32
                  nullable: true
                approval_date:
                  type: string
                  format: date
                  nullable: true
                vat:
                  type: number
                  nullable: true
                personio_id:
                  type: string
                  maxLength: 32
                  nullable: true
                connector_external_ids:
                  type: array
                  nullable: true
                  items:
                    type: string
                cost_bearer:
                  type: string
                  maxLength: 32
                  nullable: true
                tax_id:
                  type: string
                  maxLength: 32
                  nullable: true
                creditor_number:
                  type: string
                  maxLength: 32
                  nullable: true
                cost_accounting_ads:
                  type: boolean
                  nullable: true
                categories:
                  type: array
                  nullable: true
                  items:
                    type: string
                dynamicAttributes:
                  type: array
                  nullable: true
                  items:
                    type: object
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployeeResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
  /employees/{username}/absences:
    get:
      tags:
      - Employees
      description: Get absences of an employee
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployeeAbsencesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /employees/{username}/employment-periods:
    get:
      tags:
      - Employees
      description: Get employment periods of an employee
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmploymentPeriodsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      tags:
      - Employees
      summary: Create an employment period
      description: employee_id must also be sent in the body; it is not taken from the path.
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - employee_id
              - start_date
              - annual_leave_entitlement
              properties:
                employee_id:
                  type: string
                  maxLength: 32
                  description: Username of the employee. Must exist.
                start_date:
                  type: string
                  format: date
                  description: First day of the employment period. Must be on or before end_date when
                    that is given.
                end_date:
                  nullable: true
                  type: string
                  format: date
                note:
                  nullable: true
                  type: string
                  maxLength: 255
                annual_leave_entitlement:
                  type: number
                  minimum: 0
                beginning_of_year:
                  nullable: true
                  type: string
                  format: date
                period_holiday_entitlement:
                  nullable: true
                  type: number
                  minimum: 0
                is_holiday_per_year:
                  type: boolean
                  nullable: true
                day_absent_in_hours:
                  nullable: true
                  type: number
                  minimum: 0
      responses:
        '201':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmploymentPeriodResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
        '200':
          description: OK (main@7.12.35 reports this same success as HTTP 200 instead of 201; documented
            here rather than silently dropped.)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmploymentPeriodResponse'
  /employees/{username}/employment-periods/{id}:
    get:
      tags:
      - Employees
      description: Get employment period by id
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmploymentPeriodResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Employees
      summary: Update an employment period
      description: id and employee_id must also be sent in the body; neither is taken from the path.
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - id
              - employee_id
              - start_date
              properties:
                id:
                  type: integer
                  description: Must match the id in the path.
                employee_id:
                  type: string
                  maxLength: 32
                  description: Username of the employee. Must exist.
                start_date:
                  type: string
                  format: date
                  description: Must be a valid date.
                end_date:
                  nullable: true
                  type: string
                  format: date
                note:
                  nullable: true
                  type: string
                  maxLength: 255
                annual_leave_entitlement:
                  type: number
                  minimum: 0
                  nullable: true
                beginning_of_year:
                  nullable: true
                  type: string
                  format: date
                period_holiday_entitlement:
                  nullable: true
                  type: number
                  minimum: 0
                is_holiday_per_year:
                  type: boolean
                  nullable: true
                day_absent_in_hours:
                  nullable: true
                  type: number
                  minimum: 0
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmploymentPeriodResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
  /employees/{username}/internal-rates:
    get:
      tags:
      - Employees
      description: Get internal rates of an employee
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalRatesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /employees/{username}/internal-rates/{id}:
    get:
      tags:
      - Employees
      description: Get internal rate by id
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalRateResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /employees/{username}/regular-working-times:
    get:
      tags:
      - Employees
      description: Get regular working times of an employee
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegularWorkingTimesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      tags:
      - Employees
      summary: Create a regular working time
      description: employee_id must also be sent in the body; it is not taken from the path. start_date
        is required once the employee already has a regular working time, and must be unique per employee.
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - employee_id
              properties:
                employee_id:
                  type: string
                  maxLength: 32
                  description: Username of the employee. Must exist.
                start_date:
                  type: string
                  format: date
                  description: Valid from. Required once the employee already has a regular working time,
                    and unique per employee.
                  nullable: true
                monday:
                  nullable: true
                  type: number
                  minimum: 0
                tuesday:
                  nullable: true
                  type: number
                  minimum: 0
                wednesday:
                  nullable: true
                  type: number
                  minimum: 0
                thursday:
                  nullable: true
                  type: number
                  minimum: 0
                friday:
                  nullable: true
                  type: number
                  minimum: 0
                saturday:
                  nullable: true
                  type: number
                  minimum: 0
                sunday:
                  nullable: true
                  type: number
                  minimum: 0
                monday_workday:
                  type: boolean
                  nullable: true
                tuesday_workday:
                  type: boolean
                  nullable: true
                wednesday_workday:
                  type: boolean
                  nullable: true
                thursday_workday:
                  type: boolean
                  nullable: true
                friday_workday:
                  type: boolean
                  nullable: true
                saturday_workday:
                  type: boolean
                  nullable: true
                sunday_workday:
                  type: boolean
                  nullable: true
                is_monthly:
                  type: boolean
                  nullable: true
                monthly_hours:
                  nullable: true
                  type: number
                  minimum: 0
                max_hours_in_month:
                  nullable: true
                  type: number
                  minimum: 0
                max_hours_in_week:
                  nullable: true
                  type: number
                  minimum: 0
                break_regulation_type_id:
                  nullable: true
                  type: integer
                  description: ID of the break regulation type. Must exist.
                holiday_calendar_id:
                  nullable: true
                  type: integer
                  description: ID of the holiday calendar. Must exist. Defaults to the tenant's default
                    calendar when omitted.
      responses:
        '201':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegularWorkingTimeResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
        '200':
          description: OK (main@7.12.35 reports this same success as HTTP 200 instead of 201; documented
            here rather than silently dropped.)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegularWorkingTimeResponse'
  /employees/{username}/regular-working-times/{id}:
    get:
      tags:
      - Employees
      description: Get regular working time by id
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegularWorkingTimeResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Employees
      summary: Update a regular working time
      description: id and employee_id must also be sent in the body; neither is taken from the path. Omitting
        holiday_calendar_id writes the tenant default calendar.
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - id
              - employee_id
              properties:
                id:
                  type: integer
                  description: Must match the id in the path.
                employee_id:
                  type: string
                  maxLength: 32
                  description: Username of the employee. Must exist.
                start_date:
                  nullable: true
                  type: string
                  format: date
                monday:
                  nullable: true
                  type: number
                  minimum: 0
                tuesday:
                  nullable: true
                  type: number
                  minimum: 0
                wednesday:
                  nullable: true
                  type: number
                  minimum: 0
                thursday:
                  nullable: true
                  type: number
                  minimum: 0
                friday:
                  nullable: true
                  type: number
                  minimum: 0
                saturday:
                  nullable: true
                  type: number
                  minimum: 0
                sunday:
                  nullable: true
                  type: number
                  minimum: 0
                monday_workday:
                  type: boolean
                  nullable: true
                tuesday_workday:
                  type: boolean
                  nullable: true
                wednesday_workday:
                  type: boolean
                  nullable: true
                thursday_workday:
                  type: boolean
                  nullable: true
                friday_workday:
                  type: boolean
                  nullable: true
                saturday_workday:
                  type: boolean
                  nullable: true
                sunday_workday:
                  type: boolean
                  nullable: true
                is_monthly:
                  type: boolean
                  nullable: true
                monthly_hours:
                  nullable: true
                  type: number
                  minimum: 0
                max_hours_in_month:
                  nullable: true
                  type: number
                  minimum: 0
                max_hours_in_week:
                  nullable: true
                  type: number
                  minimum: 0
                break_regulation_type_id:
                  nullable: true
                  type: integer
                  description: ID of the break regulation type. Must exist.
                holiday_calendar_id:
                  nullable: true
                  type: integer
                  description: ID of the holiday calendar. Must exist. Defaults to the tenant's default
                    calendar when omitted.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegularWorkingTimeResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
  /customers:
    get:
      tags:
      - Customers
      description: Get all customers
      parameters:
      - name: start_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: end_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: customer_number[]
        in: query
        required: false
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
      - name: inactive
        in: query
        required: false
        schema:
          type: boolean
        description: Filter by active/inactive status. true = inactive customers only, false = active
          customers only. Replaces the former `status` filter as of v7.12.49.
      - name: modified_after
        in: query
        required: false
        description: Only return customers modified after this timestamp (ISO 8601 or "Y-m-d H:i:s")
        schema:
          type: string
          format: date-time
      - name: modified_before
        in: query
        required: false
        description: Only return customers modified before or at this timestamp (ISO 8601 or "Y-m-d H:i:s")
        schema:
          type: string
          format: date-time
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
      - name: status
        in: query
        required: false
        deprecated: true
        description: 'Deprecated alias for `inactive` with inverted polarity:

          * 0 - Inactive only

          * 1 - Active only


          `inactive` takes precedence if both are sent. An unparseable or empty value is ignored

          rather than guessed, so no status filter is applied. Use `inactive` instead.

          '
        schema:
          type: integer
          nullable: true
          enum:
          - 0
          - 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomersListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
    post:
      tags:
      - Customers
      description: Create a new customer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - customer_number
              - name
              - currency
              - department_id
              properties:
                customer_number:
                  type: string
                  maxLength: 32
                  description: Unique customer number/identifier. Must contain only valid characters and
                    be unique across all customers.
                name:
                  type: string
                  maxLength: 120
                  description: Primary customer name
                additional_name:
                  type: string
                  maxLength: 120
                  nullable: true
                  description: Additional name or legal entity name
                website:
                  type: string
                  maxLength: 120
                  nullable: true
                  description: Customer website URL
                email:
                  type: string
                  format: email
                  maxLength: 320
                  nullable: true
                  description: Primary contact email
                phone:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Primary contact phone number
                fax:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Fax number
                currency:
                  type: string
                  description: Currency code (must exist in currencies table). Defaults to base currency
                    if not provided.
                comments:
                  type: string
                  nullable: true
                  description: Additional comments or notes about the customer
                industry:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Industry or business sector
                vat:
                  type: number
                  nullable: true
                  description: VAT percentage rate
                  minimum: 0
                  maximum: 100
                tax_number:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Tax identification number
                iban:
                  type: string
                  maxLength: 34
                  nullable: true
                  description: International Bank Account Number
                bic:
                  type: string
                  maxLength: 11
                  nullable: true
                  description: Bank Identifier Code (SWIFT code)
                payment_target:
                  type: integer
                  nullable: true
                  description: Payment target in days
                  minimum: 0
                payment_target_discount:
                  type: integer
                  nullable: true
                  description: Early payment discount period in days
                  minimum: 0
                inactive:
                  type: boolean
                  nullable: true
                  description: Whether the customer is inactive. Defaults to false (active) when omitted.
                    Replaces the former `status` field as of v7.12.49.
                billing_procedure:
                  type: boolean
                  nullable: true
                  description: Enable special billing procedure
                automated_invoicing:
                  type: boolean
                  nullable: true
                  description: Enable automated invoicing
                debit_payment:
                  type: boolean
                  nullable: true
                  description: Enable debit payment method
                department_id:
                  type: integer
                  description: Department ID (must exist in departments table). Defaults to standard department
                    if not provided.
                dynamic_attributes:
                  type: array
                  nullable: true
                  description: Custom dynamic attributes for the customer
                  items:
                    type: object
                categories:
                  type: array
                  nullable: true
                  description: Array of category IDs to associate with this customer
                  items:
                    type: integer
                travel_expense_flat_per_day:
                  type: integer
                  nullable: true
                  description: Flat rate for travel expenses per day in cents. Defaults to system configuration
                    if not provided.
                  minimum: 0
                travel_expense_flat_per_journey:
                  type: integer
                  nullable: true
                  description: Flat rate for travel expenses per journey in cents. Defaults to system
                    configuration if not provided.
                  minimum: 0
                status:
                  type: integer
                  nullable: true
                  deprecated: true
                  enum:
                  - 0
                  - 1
                  description: 'Deprecated alias for `inactive` with inverted polarity: 1 = active, 0
                    = inactive.

                    `inactive` takes precedence if both are sent. An unparseable value is ignored, leaving

                    the customer active. Use `inactive` instead.

                    '
      responses:
        '201':
          description: Customer created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Customer'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '422':
          description: Validation error. One or more fields failed validation constraints.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Error message
                  errors:
                    type: object
                    description: Field-specific validation errors
                    additionalProperties:
                      type: array
                      items:
                        type: string
  /customers/{customer_number}:
    get:
      tags:
      - Customers
      description: Get customer by customer_number
      parameters:
      - name: customer_number
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Customers
      description: Update an existing customer. All fields are optional; only provided fields will be
        updated.
      parameters:
      - name: customer_number
        in: path
        required: true
        schema:
          type: string
        description: Customer number to update
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                customer_number:
                  type: string
                  maxLength: 32
                  description: Unique customer number/identifier. Must contain only valid characters.
                    Use 'sometimes' validation - only validated if provided.
                name:
                  type: string
                  maxLength: 120
                  description: Primary customer name
                additional_name:
                  type: string
                  maxLength: 120
                  nullable: true
                  description: Additional name or legal entity name
                website:
                  type: string
                  maxLength: 120
                  nullable: true
                  description: Customer website URL
                email:
                  type: string
                  format: email
                  maxLength: 320
                  nullable: true
                  description: Primary contact email
                phone:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Primary contact phone number
                fax:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Fax number
                currency:
                  type: string
                  description: Currency code (must exist in currencies table)
                comments:
                  type: string
                  nullable: true
                  description: Additional comments or notes about the customer
                industry:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Industry or business sector
                vat:
                  type: number
                  nullable: true
                  description: VAT percentage rate
                  minimum: 0
                  maximum: 100
                tax_number:
                  type: string
                  maxLength: 32
                  nullable: true
                  description: Tax identification number
                iban:
                  type: string
                  maxLength: 34
                  nullable: true
                  description: International Bank Account Number
                bic:
                  type: string
                  maxLength: 11
                  nullable: true
                  description: Bank Identifier Code (SWIFT code)
                payment_target:
                  type: integer
                  nullable: true
                  description: Payment target in days
                  minimum: 0
                payment_target_discount:
                  type: integer
                  nullable: true
                  description: Early payment discount period in days
                  minimum: 0
                inactive:
                  type: boolean
                  nullable: true
                  description: Whether the customer is inactive. Defaults to false (active) when omitted.
                    Replaces the former `status` field as of v7.12.49.
                billing_procedure:
                  type: boolean
                  nullable: true
                  description: Enable special billing procedure
                automated_invoicing:
                  type: boolean
                  nullable: true
                  description: Enable automated invoicing
                debit_payment:
                  type: boolean
                  nullable: true
                  description: Enable debit payment method
                department_id:
                  type: integer
                  description: Department ID (must exist in departments table)
                dynamic_attributes:
                  type: array
                  nullable: true
                  description: Custom dynamic attributes for the customer
                  items:
                    type: object
                categories:
                  type: array
                  nullable: true
                  description: Array of category IDs to associate with this customer
                  items:
                    type: integer
                status:
                  type: integer
                  nullable: true
                  deprecated: true
                  enum:
                  - 0
                  - 1
                  description: 'Deprecated alias for `inactive` with inverted polarity: 1 = active, 0
                    = inactive.

                    `inactive` takes precedence if both are sent. An unparseable value is ignored, leaving

                    the current value unchanged. Use `inactive` instead.

                    '
      responses:
        '200':
          description: Customer updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Customer'
                  info:
                    type: object
                    nullable: true
                    description: Optional consistency information when customer data was adjusted during
                      update
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: Validation error. One or more fields failed validation constraints.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Error message
                  errors:
                    type: object
                    description: Field-specific validation errors
                    additionalProperties:
                      type: array
                      items:
                        type: string
    delete:
      tags:
      - Customers
      description: Delete a customer by customer_number. This operation permanently removes the customer
        from the system.
      parameters:
      - name: customer_number
        in: path
        required: true
        schema:
          type: string
        description: Customer number to delete
      responses:
        '200':
          description: Customer deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Success message
                    example: Customer deleted successfully.
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          description: Customer could not be deleted. This may occur if the customer has related records
            that prevent deletion.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Error message
                    example: Customer could not be deleted.
  /customers/{customer_number}/contacts:
    get:
      tags:
      - Customers
      description: Get customer contacts
      parameters:
      - name: customer_number
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerContactsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      tags:
      - Customers
      summary: Create a customer contact
      description: customer_number must also be sent in the body; it is not taken from the path.
      parameters:
      - name: customer_number
        in: path
        required: true
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - customer_number
              - first_name
              - last_name
              properties:
                customer_number:
                  type: string
                salutation:
                  nullable: true
                  type: string
                  maxLength: 255
                first_name:
                  type: string
                  maxLength: 255
                last_name:
                  type: string
                  maxLength: 255
                email:
                  nullable: true
                  type: string
                  format: email
                  maxLength: 255
                phone:
                  nullable: true
                  type: string
                  maxLength: 255
                fax:
                  nullable: true
                  type: string
                  maxLength: 255
                mobile:
                  nullable: true
                  type: string
                  maxLength: 255
                primary:
                  nullable: true
                  type: string
                  description: 'Contact role: `prim` for the primary contact, `sec` for the default contact.'
                department:
                  nullable: true
                  type: string
                  maxLength: 255
                job_title:
                  nullable: true
                  type: string
                  maxLength: 255
                language:
                  nullable: true
                  type: string
                  maxLength: 255
                inactive:
                  nullable: true
                  type: boolean
                title:
                  nullable: true
                  type: string
                  maxLength: 255
                username:
                  nullable: true
                  type: string
                  maxLength: 32
                  description: Portal login. Must be unique across customer contacts and employees.
                password:
                  nullable: true
                  type: string
                  minLength: 4
                categories:
                  nullable: true
                  type: array
      responses:
        '201':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
  /absences:
    get:
      tags:
      - Absences
      description: Get all absences
      parameters:
      - name: start_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: end_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: employee_id
        in: query
        required: false
        schema:
          type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AbsencesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
    post:
      tags:
      - Absences
      summary: Create an absence
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - employee_id
              - start_date
              - end_date
              - absence_reason_id
              properties:
                employee_id:
                  type: string
                  maxLength: 32
                  description: Username of the employee. Must exist.
                type:
                  nullable: true
                  type: string
                  maxLength: 64
                  description: 'Extent of the absence: 0 full day, 1 half day, 2 hours. With 2, from/to/hours/timezone
                    are required.'
                  enum:
                  - 0
                  - 1
                  - 2
                  default: 0
                hours:
                  type: number
                  minimum: 0
                  description: Duration in hours. Required when type is 2 (hours).
                  nullable: true
                from:
                  type: string
                  description: Start time (H:i:s). Required when type is 2 (hours).
                  nullable: true
                to:
                  type: string
                  description: End time (H:i:s), at or after from. Required when type is 2 (hours).
                  nullable: true
                timezone:
                  nullable: true
                  type: string
                  description: Timezone name for from/to, e.g. "Europe/Berlin". Required when type is
                    2 (hours).
                note:
                  nullable: true
                  type: string
                  maxLength: 255
                planned:
                  nullable: true
                  type: boolean
                  default: false
                start_date:
                  type: string
                  format: date
                end_date:
                  type: string
                  format: date
                absence_reason_id:
                  type: string
                  description: ID of the absence reason. Must exist.
      responses:
        '201':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '422':
          $ref: '#/components/responses/ValidationError'
        '200':
          description: OK (main@7.12.35 reports this same success as HTTP 200 instead of 201; documented
            here rather than silently dropped.)
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
  /absences/{id}:
    get:
      tags:
      - Absences
      description: Get absence by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AbsenceDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /departments:
    get:
      tags:
      - Departments
      description: Get all departments
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DepartmentListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
      parameters:
      - name: limit
        in: query
        required: false
        description: Number of results per page (default 15)
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        description: Page number (default 1)
        schema:
          type: integer
          minimum: 1
          default: 1
  /departments/{id}:
    get:
      tags:
      - Departments
      description: Get department by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DepartmentResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /devices:
    get:
      tags:
      - Devices
      description: Get all devices
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
  /devices/{id}:
    get:
      tags:
      - Devices
      description: Get devices by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /receipts:
    get:
      tags:
      - Receipts
      description: Get all receipts
      parameters:
      - name: start_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: end_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReceiptsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
    post:
      tags:
      - Receipts
      description: Create a new receipt
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - employee_id
              - date
              - receipt_type_id
              - project_id
              - payment_method
              - currency
              - is_amount_net
              - receiptAmounts
              properties:
                employee_id:
                  type: string
                  maxLength: 255
                  description: Username of the employee
                date:
                  type: string
                  format: date
                  description: Receipt date
                performance_date:
                  type: string
                  format: date
                  nullable: true
                  description: Performance date (optional), can be different from receipt date, if receipt
                    type supports it
                receipt_type_id:
                  type: string
                  maxLength: 255
                  description: Receipt type identifier
                project_id:
                  type: integer
                  description: Project ID
                project_task_id:
                  type: integer
                  nullable: true
                  description: Project task ID (optional)
                payment_method:
                  type: string
                  maxLength: 255
                  description: Payment method
                currency:
                  type: string
                  maxLength: 32
                  description: Currency code (e.g., EUR, USD)
                is_amount_net:
                  type: boolean
                  description: Whether the amount is net (true) or gross (false)
                is_invoice_amount_net:
                  type: boolean
                  nullable: true
                  description: Whether the invoice amount is net (true) or gross (false). Required if
                    any receiptAmount has invoicing_share > 0
                note:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Receipt notes
                receiptAmounts:
                  type: array
                  minItems: 1
                  description: Array of receipt amounts
                  items:
                    type: object
                    required:
                    - tax
                    - quantity
                    - amount
                    properties:
                      tax:
                        type: number
                        format: float
                        minimum: 0
                        maximum: 100
                        description: Tax rate percentage must match the tax rate of the receipt type
                      quantity:
                        type: number
                        format: float
                        minimum: 1
                        description: Quantity
                      amount:
                        type: number
                        format: float
                        minimum: 0
                        description: Amount
                      private_share:
                        type: number
                        format: float
                        minimum: 0
                        nullable: true
                        description: Private share amount
                      invoicing_share:
                        type: number
                        format: float
                        minimum: 0
                        nullable: true
                        description: Invoicing share amount, will be only considered if project allow
                          invoicing.
      responses:
        '200':
          description: Receipt created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Receipt'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '422':
          description: Validation error
  /receipts/{id}:
    get:
      tags:
      - Receipts
      description: Get receipt by receipt id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReceiptDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Receipts
      description: Update an existing receipt. All fields are optional; only provided fields will be updated.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                employee_id:
                  type: string
                  maxLength: 255
                  description: Username of the employee
                date:
                  type: string
                  format: date
                  description: Receipt date
                performance_date:
                  type: string
                  format: date
                  nullable: true
                  description: Performance date (optional)
                receipt_type_id:
                  type: string
                  maxLength: 255
                  description: Receipt type identifier
                project_id:
                  type: integer
                  description: Project ID
                project_task_id:
                  type: integer
                  nullable: true
                  description: Project task ID (optional)
                payment_method:
                  type: string
                  maxLength: 255
                  description: Payment method
                currency:
                  type: string
                  maxLength: 32
                  description: Currency code (e.g., EUR, USD)
                is_amount_net:
                  type: boolean
                  description: Whether the amount is net (true) or gross (false)
                is_invoice_amount_net:
                  type: boolean
                  nullable: true
                  description: Whether the invoice amount is net (true) or gross (false). Required if
                    any receiptAmount has invoicing_share > 0
                note:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Receipt notes
                receiptAmounts:
                  type: array
                  description: Array of receipt amounts
                  items:
                    type: object
                    properties:
                      tax:
                        type: number
                        format: float
                        minimum: 0
                        maximum: 100
                        description: Tax rate percentage
                      quantity:
                        type: number
                        format: float
                        minimum: 1
                        description: Quantity
                      amount:
                        type: number
                        format: float
                        minimum: 0
                        description: Amount
                      private_share:
                        type: number
                        format: float
                        minimum: 0
                        nullable: true
                        description: Private share amount
                      invoicing_share:
                        type: number
                        format: float
                        minimum: 0
                        nullable: true
                        description: Invoicing share amount
      responses:
        '200':
          description: Receipt updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Receipt'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: Validation error
    delete:
      tags:
      - Receipts
      description: Delete a receipt
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: Receipt deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates if the deletion was successful
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          description: Deletion failed
  /receipts/{id}/amounts:
    get:
      tags:
      - Receipts
      description: Get receipt amounts
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReceiptAmountsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /receipts/{id}/amounts/{amount_id}:
    get:
      tags:
      - Receipts
      description: Get receipt amount by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: amount_id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReceiptAmountResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /tickets:
    get:
      tags:
      - Tickets
      description: Get all tickets
      parameters:
      - name: start_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: end_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
    post:
      tags:
      - Tickets
      description: Create a new ticket
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - status
              - project_id
              - project_task_id
              - priority
              - subject
              properties:
                status:
                  type: integer
                  enum:
                  - 1
                  - 2
                  - 3
                  - 4
                  - 5
                  - 8
                  description: 'Ticket status:

                    * 1 - STATUS_NEW: New ticket

                    * 2 - STATUS_IN_PROCESS: Ticket is being processed

                    * 3 - STATUS_DONE: Ticket is completed

                    * 4 - STATUS_REJECTED: Ticket has been rejected

                    * 5 - STATUS_APPROVED: Ticket has been approved

                    * 8 - STATUS_BILLED: Ticket has been billed

                    '
                project_id:
                  type: integer
                  description: ID of the project this ticket belongs to. Must exist in the projects table.
                project_task_id:
                  type: string
                  description: ID of the project task this ticket is associated with. Must exist in the
                    project_tasks table.
                priority:
                  type: integer
                  minimum: 1
                  maximum: 5
                  description: Ticket priority level from 1 (lowest) to 5 (highest)
                subject:
                  type: string
                  maxLength: 255
                  description: Ticket subject/title
                planned_hours:
                  type: number
                  format: float
                  nullable: true
                  description: Estimated hours to complete the ticket
                creator_username:
                  type: string
                  nullable: true
                  description: Username of the employee who created this ticket. Required if customer_contact_person
                    is not provided. Must be a valid employee username.
                receipt_date:
                  type: string
                  format: date
                  nullable: true
                  description: Date when the ticket was received (Eingangsdatum)
                processor_username:
                  type: string
                  nullable: true
                  description: Username of the employee processing this ticket. Must be a valid employee
                    username.
                start_date:
                  type: string
                  format: date
                  nullable: true
                  description: Date when work on the ticket started
                deadline:
                  type: string
                  format: date
                  nullable: true
                  description: Deadline for completing the ticket
                from_mail:
                  type: string
                  nullable: true
                  description: Email address from which this ticket was created (usually extracted from
                    emails)
                external_ticket_number:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: External ticket reference number from another system
                notify_of_completion:
                  type: boolean
                  nullable: true
                  description: Whether to notify stakeholders when the ticket is completed
                prevent_overbooking:
                  type: integer
                  enum:
                  - 0
                  - 1
                  - 2
                  - 3
                  - 4
                  nullable: true
                  description: 'Overbooking prevention setting:

                    * 0 - YES_ALL: Allow all work to exceed planned hours

                    * 1 - YES_ONLY_NON_BILLABLE: Allow only non-billable work to exceed

                    * 2 - NO_ALL: Prevent all work from exceeding planned hours

                    * 3 - YES_TRAVEL_OR_NON_BILLABLE: Allow travel or non-billable work to exceed

                    * 4 - YES_ONLY_TRAVEL: Allow only travel work to exceed

                    '
                customer_contact_person:
                  type: string
                  format: email
                  nullable: true
                  description: Email address of the customer contact person. Required if creator_username
                    is not provided. Must exist in customer_contacts table and match the project's customer.
                customer_reference:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Customer's reference number or identifier for this ticket
                keywords:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Comma-separated list of keywords/tags for the ticket
                categories:
                  type: array
                  nullable: true
                  description: Array of category names to associate with this ticket
                  items:
                    type: string
                    description: Category name/ID. Must exist in the categories table.
      responses:
        '200':
          description: Ticket created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Ticket'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '422':
          description: Validation error. One or more fields failed validation constraints.
  /tickets/{id}:
    get:
      tags:
      - Tickets
      description: Get ticket by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Tickets
      description: Update an existing ticket. All fields are optional; only provided fields will be updated.
        Existing ticket data is merged with incoming request data.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
        description: Ticket ID to update
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: integer
                  enum:
                  - 1
                  - 2
                  - 3
                  - 4
                  - 5
                  - 8
                  description: 'Ticket status:

                    * 1 - STATUS_NEW: New ticket

                    * 2 - STATUS_IN_PROCESS: Ticket is being processed

                    * 3 - STATUS_DONE: Ticket is completed

                    * 4 - STATUS_REJECTED: Ticket has been rejected

                    * 5 - STATUS_APPROVED: Ticket has been approved

                    * 8 - STATUS_BILLED: Ticket has been billed

                    '
                project_id:
                  type: integer
                  description: ID of the project this ticket belongs to. Must exist in the projects table.
                project_task_id:
                  type: string
                  description: ID of the project task this ticket is associated with. Must exist in the
                    project_tasks table.
                priority:
                  type: integer
                  minimum: 1
                  maximum: 5
                  description: Ticket priority level from 1 (lowest) to 5 (highest)
                subject:
                  type: string
                  maxLength: 255
                  description: Ticket subject/title
                planned_hours:
                  type: number
                  format: float
                  nullable: true
                  description: Estimated hours to complete the ticket
                creator_username:
                  type: string
                  nullable: true
                  description: Username of the employee who created this ticket. Required if customer_contact_person
                    is not provided. Must be a valid employee username.
                receipt_date:
                  type: string
                  format: date
                  nullable: true
                  description: Date when the ticket was received (Eingangsdatum)
                processor_username:
                  type: string
                  nullable: true
                  description: Username of the employee processing this ticket. Must be a valid employee
                    username.
                start_date:
                  type: string
                  format: date
                  nullable: true
                  description: Date when work on the ticket started
                deadline:
                  type: string
                  format: date
                  nullable: true
                  description: Deadline for completing the ticket
                from_mail:
                  type: string
                  nullable: true
                  description: Email address from which this ticket was created (usually extracted from
                    emails)
                external_ticket_number:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: External ticket reference number from another system
                notify_of_completion:
                  type: boolean
                  nullable: true
                  description: Whether to notify stakeholders when the ticket is completed
                prevent_overbooking:
                  type: integer
                  enum:
                  - 0
                  - 1
                  - 2
                  - 3
                  - 4
                  nullable: true
                  description: 'Overbooking prevention setting:

                    * 0 - YES_ALL: Allow all work to exceed planned hours

                    * 1 - YES_ONLY_NON_BILLABLE: Allow only non-billable work to exceed

                    * 2 - NO_ALL: Prevent all work from exceeding planned hours

                    * 3 - YES_TRAVEL_OR_NON_BILLABLE: Allow travel or non-billable work to exceed

                    * 4 - YES_ONLY_TRAVEL: Allow only travel work to exceed

                    '
                customer_contact_person:
                  type: string
                  format: email
                  nullable: true
                  description: Email address of the customer contact person. Required if creator_username
                    is not provided. Must exist in customer_contacts table and match the project's customer.
                customer_reference:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Customer's reference number or identifier for this ticket
                keywords:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Comma-separated list of keywords/tags for the ticket
                categories:
                  type: array
                  nullable: true
                  description: Array of category names to associate with this ticket
                  items:
                    type: string
                    description: Category name/ID. Must exist in the categories table.
      responses:
        '200':
          description: Ticket updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Ticket'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: Validation error. One or more fields failed validation constraints.
    delete:
      tags:
      - Tickets
      description: Delete a ticket
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
        description: Ticket ID to delete
      responses:
        '200':
          description: Ticket deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates if the deletion was successful
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          description: Deletion failed
  /tickets/{id}/attachments:
    post:
      tags:
      - Tickets
      description: Upload an attachment for a ticket
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
        description: Ticket ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - filename
              - file_contents
              properties:
                filename:
                  type: string
                  description: The name of the file being uploaded
                file_contents:
                  type: string
                  format: byte
                  description: Base64-encoded file contents
      responses:
        '200':
          description: Attachment uploaded successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates if the upload was successful
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          description: Upload failed
  /tickets/{id}/subtasks:
    get:
      tags:
      - Tickets
      description: Get ticket subtasks
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketSubtasksListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      tags:
      - Tickets
      description: Create a new subtask for a ticket
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
        description: Parent ticket ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - subject
              - name
              - creator_username
              - status
              - categories
              properties:
                subject:
                  type: string
                  maxLength: 255
                  description: Subtask subject/title
                name:
                  type: string
                  maxLength: 255
                  description: Subtask name
                creator_username:
                  type: string
                  description: Username of the employee who created this subtask. Must be a valid employee
                    username.
                status:
                  type: integer
                  enum:
                  - 1
                  - 2
                  - 3
                  - 4
                  - 5
                  - 8
                  description: 'Subtask status:

                    * 1 - STATUS_NEW: New subtask

                    * 2 - STATUS_IN_PROCESS: Subtask is being processed

                    * 3 - STATUS_DONE: Subtask is completed

                    * 4 - STATUS_REJECTED: Subtask has been rejected

                    * 5 - STATUS_APPROVED: Subtask has been approved

                    * 8 - STATUS_BILLED: Subtask has been billed

                    '
                categories:
                  type: array
                  description: Array of category names to associate with this subtask
                  items:
                    type: string
                    description: Category name/ID. Must exist in the categories table.
                customer_reference:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Customer's reference number or identifier for this subtask
                start_date:
                  type: string
                  format: date
                  nullable: true
                  description: Date when work on the subtask started
                receipt_date:
                  type: string
                  format: date
                  nullable: true
                  description: Date when the subtask was received
                deadline:
                  type: string
                  format: date
                  nullable: true
                  description: Deadline for completing the subtask
                planned_hours:
                  type: number
                  format: float
                  nullable: true
                  description: Estimated hours to complete the subtask
                prevent_overbooking:
                  type: integer
                  enum:
                  - 0
                  - 1
                  - 2
                  - 3
                  - 4
                  nullable: true
                  description: 'Overbooking prevention setting:

                    * 0 - YES_ALL: Allow all work to exceed planned hours

                    * 1 - YES_ONLY_NON_BILLABLE: Allow only non-billable work to exceed

                    * 2 - NO_ALL: Prevent all work from exceeding planned hours

                    * 3 - YES_TRAVEL_OR_NON_BILLABLE: Allow travel or non-billable work to exceed

                    * 4 - YES_ONLY_TRAVEL: Allow only travel work to exceed

                    '
                processor_username:
                  type: string
                  nullable: true
                  description: Username of the employee processing this subtask. Must be a valid employee
                    username.
                keywords:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Comma-separated list of keywords/tags for the subtask
                customer_contact_person:
                  type: string
                  format: email
                  nullable: true
                  description: Email address of the customer contact person. Must exist in customer_contacts
                    table and match the parent ticket's project customer.
      responses:
        '200':
          description: Subtask created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/TicketSubtaskResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          description: Parent ticket not found
        '422':
          description: Validation error. One or more fields failed validation constraints.
  /tickets/{id}/subtasks/{subtask_id}:
    get:
      tags:
      - Tickets
      description: Get ticket subtask by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: subtask_id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketSubtaskResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Tickets
      description: Update an existing subtask. All fields are optional; only provided fields will be updated.
        Existing subtask data is merged with incoming request data.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
        description: Parent ticket ID
      - name: subtask_id
        in: path
        required: true
        schema:
          type: integer
        description: Subtask ID to update
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                subject:
                  type: string
                  maxLength: 255
                  description: Subtask subject/title
                name:
                  type: string
                  maxLength: 255
                  description: Subtask name
                creator_username:
                  type: string
                  description: Username of the employee who created this subtask. Must be a valid employee
                    username.
                status:
                  type: integer
                  enum:
                  - 1
                  - 2
                  - 3
                  - 4
                  - 5
                  - 8
                  description: 'Subtask status:

                    * 1 - STATUS_NEW: New subtask

                    * 2 - STATUS_IN_PROCESS: Subtask is being processed

                    * 3 - STATUS_DONE: Subtask is completed

                    * 4 - STATUS_REJECTED: Subtask has been rejected

                    * 5 - STATUS_APPROVED: Subtask has been approved

                    * 8 - STATUS_BILLED: Subtask has been billed

                    '
                categories:
                  type: array
                  nullable: true
                  description: Array of category names to associate with this subtask
                  items:
                    type: string
                    description: Category name/ID. Must exist in the categories table.
                customer_reference:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Customer's reference number or identifier for this subtask
                start_date:
                  type: string
                  format: date
                  nullable: true
                  description: Date when work on the subtask started
                receipt_date:
                  type: string
                  format: date
                  nullable: true
                  description: Date when the subtask was received
                deadline:
                  type: string
                  format: date
                  nullable: true
                  description: Deadline for completing the subtask
                planned_hours:
                  type: number
                  format: float
                  nullable: true
                  description: Estimated hours to complete the subtask
                prevent_overbooking:
                  type: integer
                  enum:
                  - 0
                  - 1
                  - 2
                  - 3
                  - 4
                  nullable: true
                  description: 'Overbooking prevention setting:

                    * 0 - YES_ALL: Allow all work to exceed planned hours

                    * 1 - YES_ONLY_NON_BILLABLE: Allow only non-billable work to exceed

                    * 2 - NO_ALL: Prevent all work from exceeding planned hours

                    * 3 - YES_TRAVEL_OR_NON_BILLABLE: Allow travel or non-billable work to exceed

                    * 4 - YES_ONLY_TRAVEL: Allow only travel work to exceed

                    '
                processor_username:
                  type: string
                  nullable: true
                  description: Username of the employee processing this subtask. Must be a valid employee
                    username.
                keywords:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: Comma-separated list of keywords/tags for the subtask
                customer_contact_person:
                  type: string
                  format: email
                  nullable: true
                  description: Email address of the customer contact person. Must exist in customer_contacts
                    table and match the parent ticket's project customer.
      responses:
        '200':
          description: Subtask updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/TicketSubtask'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          description: Subtask or parent ticket not found
        '422':
          description: Validation error. One or more fields failed validation constraints.
    delete:
      tags:
      - Tickets
      description: Delete a subtask
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
        description: Parent ticket ID
      - name: subtask_id
        in: path
        required: true
        schema:
          type: integer
        description: Subtask ID to delete
      responses:
        '200':
          description: Subtask deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates if the deletion was successful
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          description: Subtask or parent ticket not found
        '500':
          description: Deletion failed
  /invoices:
    get:
      tags:
      - Invoices
      description: Get all invoices
      parameters:
      - name: start_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: end_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: customer_number
        in: query
        required: false
        schema:
          type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoicesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /invoices/{id}:
    get:
      tags:
      - Invoices
      description: Get invoice by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoiceDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /invoices/{id}/items:
    get:
      tags:
      - Invoices
      description: Get invoice items
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: status
        in: query
        required: false
        description: 'Filter by status. Accepts a single value or an array (`status[]=0&status[]=1`).
          Values: 0=PLANNED, 1=APPROVED, 2=BILLED, 3=CANCELED

          '
        style: form
        explode: true
        schema:
          type: array
          items:
            type: integer
            enum:
            - 0
            - 1
            - 2
            - 3
      - name: planned_from
        in: query
        required: false
        description: Filter items with planned_date >= this date (inclusive)
        schema:
          type: string
          format: date
      - name: planned_to
        in: query
        required: false
        description: Filter items with planned_date <= this date (inclusive)
        schema:
          type: string
          format: date
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoiceItemsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/invoice-items:
    get:
      tags:
      - Invoices
      summary: List invoice items for a project
      description: 'Returns a paginated list of invoice items belonging to the given project. Supports
        the same filters as `/invoice-items` except `project_id` (which is set implicitly).

        '
      parameters:
      - name: project
        in: path
        required: true
        description: Project id
        schema:
          type: integer
      - name: status
        in: query
        required: false
        description: 'Filter by status. Values: 0=PLANNED, 1=APPROVED, 2=BILLED, 3=CANCELED

          '
        style: form
        explode: true
        schema:
          type: array
          items:
            type: integer
            enum:
            - 0
            - 1
            - 2
            - 3
      - name: planned_from
        in: query
        required: false
        description: Filter items with planned_date >= this date (inclusive)
        schema:
          type: string
          format: date
      - name: planned_to
        in: query
        required: false
        description: Filter items with planned_date <= this date (inclusive)
        schema:
          type: string
          format: date
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoiceItemsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /offers:
    get:
      tags:
      - Offers
      description: Get all offers
      parameters:
      - name: start_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: end_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: customer_number
        in: query
        required: false
        schema:
          type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 15
      - name: id[]
        in: query
        required: false
        description: Filter by one or more offer ids
        style: form
        explode: true
        schema:
          type: array
          items:
            type: integer
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OffersListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /offers/{id}:
    get:
      tags:
      - Offers
      description: Get offer by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OfferDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /employees/{username}/meals:
    get:
      tags:
      - Employees
      description: Get meals of an employee
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      - name: start_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: end_date
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployeeMealsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /employees/{username}/meals/{id}:
    get:
      tags:
      - Employees
      description: Get meal by id
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployeeMealResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /employees/{username}/projects:
    get:
      tags:
      - Employees
      description: Get projects of an employee
      parameters:
      - name: username
        in: path
        required: true
        schema:
          type: string
      - name: project_status
        in: query
        required: false
        description: Filter by project status (string or array)
        schema:
          oneOf:
          - type: string
          - type: array
            items:
              type: string
      - name: project_start_date
        in: query
        required: false
        description: Filter by project start date (YYYY-MM-DD)
        schema:
          type: string
          format: date
      - name: project_end_date
        in: query
        required: false
        description: Filter by project end date (YYYY-MM-DD)
        schema:
          type: string
          format: date
      - name: project_status[]
        in: query
        required: false
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployeeProjectsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /departments/{id}/children:
    get:
      tags:
      - Departments
      description: Get child departments
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DepartmentChildrenListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /departments/{id}/employees:
    get:
      tags:
      - Departments
      description: Get employees of a department
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DepartmentEmployeesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /receipts/{id}/attachments:
    get:
      tags:
      - Receipts
      description: Get receipt attachments
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReceiptAttachmentsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      tags:
      - Receipts
      description: Upload an attachment for a receipt
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - filename
              - file_contents
              properties:
                filename:
                  type: string
                  description: The name of the file being uploaded
                file_contents:
                  type: string
                  format: byte
                  description: Base64-encoded file contents
      responses:
        '200':
          description: Attachment uploaded successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates if the upload was successful
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          description: Upload failed
    delete:
      tags:
      - Receipts
      description: Delete a receipt attachment
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: Attachment deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates if the deletion was successful
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          description: Deletion failed
  /articles:
    get:
      tags:
      - Articles
      description: Get all articles
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArticlesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /articles/{id}:
    get:
      tags:
      - Articles
      description: Get article by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArticleDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /workhour-balances:
    get:
      tags:
      - WorkhourBalances
      summary: List workhour balances
      description: 'Returns a paginated list of the cached overtime / work-hour balances and vacation
        entitlements. Each record is a previous-day snapshot calculated by the WorkHourBalanceCalculator.

        '
      parameters:
      - name: employee_id
        in: query
        required: false
        description: Filter by employee username
        schema:
          type: string
      - name: limit
        in: query
        required: false
        description: Number of results per page (default 15)
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        description: Page number (default 1)
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkHourBalancesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /workhour-balances/{id}:
    get:
      tags:
      - WorkhourBalances
      summary: Get workhour balance by id
      description: Returns a single workhour balance record by its numeric id.
      parameters:
      - name: id
        in: path
        required: true
        description: WorkHourBalance record id
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkHourBalanceDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /invoices/{id}/attachments:
    get:
      tags:
      - Invoices
      summary: Get attachments for an invoice
      description: Returns the document attachments linked to the given invoice.
      parameters:
      - name: id
        in: path
        required: true
        description: Invoice id
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      files:
                        type: array
                        description: The invoice document plus every attachment.
                        items:
                          $ref: '#/components/schemas/InvoiceFile'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /invoice-items:
    get:
      tags:
      - Invoices
      summary: List all invoice items
      description: 'Returns a paginated list of invoice items across all invoices. Supports filtering
        by id, status, project_id and planned date range. All array filters accept both scalar (`status=0`)
        and array form (`status[]=0&status[]=1`).

        '
      parameters:
      - name: id
        in: query
        required: false
        description: Filter by one or more invoice item ids
        style: form
        explode: true
        schema:
          type: array
          items:
            type: integer
            minimum: 1
      - name: status
        in: query
        required: false
        description: 'Filter by status. Values: 0=PLANNED, 1=APPROVED, 2=BILLED, 3=CANCELED'
        style: form
        explode: true
        schema:
          type: array
          items:
            type: integer
            enum:
            - 0
            - 1
            - 2
            - 3
      - name: project_id
        in: query
        required: false
        description: Filter by one or more project ids
        style: form
        explode: true
        schema:
          type: array
          items:
            type: integer
            minimum: 1
      - name: planned_from
        in: query
        required: false
        description: Filter items with planned_date >= this date (inclusive)
        schema:
          type: string
          format: date
      - name: planned_to
        in: query
        required: false
        description: Filter items with planned_date <= this date (inclusive)
        schema:
          type: string
          format: date
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoiceItemsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /invoice-items/{id}:
    get:
      tags:
      - Invoices
      summary: Get invoice item by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoiceItemDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /employees/{username}/transponders:
    get:
      tags:
      - Employees
      summary: List transponders of an employee
      parameters:
      - name: username
        in: path
        required: true
        description: Employee username
        schema:
          type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TranspondersListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /customers/{customer_number}/price-tables:
    get:
      tags:
      - Customers
      summary: List price tables for a customer
      parameters:
      - name: customer_number
        in: path
        required: true
        description: Customer number
        schema:
          type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PriceTablesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /customers/{customer_number}/price-tables/{id}:
    get:
      tags:
      - Customers
      summary: Get a price table for a customer
      parameters:
      - name: customer_number
        in: path
        required: true
        description: Customer number
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PriceTableDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{id}/price-tables/{price_table_id}:
    get:
      tags:
      - Projects
      summary: Get a price table for a project
      parameters:
      - name: id
        in: path
        required: true
        description: Project id
        schema:
          type: integer
      - name: price_table_id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PriceTableDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{id}/locations:
    get:
      tags:
      - Projects
      summary: List locations for a project
      parameters:
      - name: id
        in: path
        required: true
        description: Project id
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectLocationsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{id}/tasks/{task_id}/employees:
    get:
      tags:
      - Projects
      summary: List employees assigned to a project task
      parameters:
      - name: id
        in: path
        required: true
        description: Project id
        schema:
          type: integer
      - name: task_id
        in: path
        required: true
        description: Project task id
        schema:
          type: integer
      - name: employee_id
        in: query
        required: false
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
      - name: from
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: to
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: price_group
        in: query
        required: false
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectTaskEmployeesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{id}/tasks/{task_id}/employees/{project_task_employee_id}:
    get:
      tags:
      - Projects
      summary: Get an employee assignment for a project task
      parameters:
      - name: id
        in: path
        required: true
        description: Project id
        schema:
          type: integer
      - name: task_id
        in: path
        required: true
        description: Project task id
        schema:
          type: integer
      - name: project_task_employee_id
        in: path
        required: true
        description: Project task employee assignment id
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectTaskEmployeeResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /receipts-amounts:
    get:
      tags:
      - Receipts
      summary: List all receipt amounts (filterable)
      parameters:
      - name: date_from
        in: query
        required: false
        description: 'Filter: receipt date >= date_from (format: YYYY-MM-DD)'
        schema:
          type: string
          format: date
      - name: date_to
        in: query
        required: false
        description: 'Filter: receipt date <= date_to (format: YYYY-MM-DD), must be >= date_from'
        schema:
          type: string
          format: date
      - name: employee_id
        in: query
        required: false
        description: 'Filter: only amounts belonging to receipts of this employee'
        schema:
          type: string
          minLength: 1
      - name: receipt_id
        in: query
        required: false
        description: 'Filter: only amounts belonging to this receipt'
        schema:
          type: integer
          minimum: 1
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReceiptAmountsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /offers/{id}/items:
    get:
      tags:
      - Offers
      summary: List items for an offer
      parameters:
      - name: id
        in: path
        required: true
        description: Offer id
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OfferItemsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /offers/{id}/items/{item_id}:
    get:
      tags:
      - Offers
      summary: Get offer item by id
      parameters:
      - name: id
        in: path
        required: true
        description: Offer id
        schema:
          type: integer
      - name: item_id
        in: path
        required: true
        description: Offer item id
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OfferItemResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /folders:
    get:
      tags:
      - Documents
      summary: List document folders
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentFoldersListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /folders/{id}:
    get:
      tags:
      - Documents
      summary: Get a document folder by id
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentFolderResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /folders/{id}/documents:
    get:
      tags:
      - Documents
      summary: List documents in a folder
      parameters:
      - name: id
        in: path
        required: true
        description: Folder id
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /folders/{id}/documents/{document_id}:
    get:
      tags:
      - Documents
      summary: Get a document by id within a folder
      parameters:
      - name: id
        in: path
        required: true
        description: Folder id
        schema:
          type: integer
      - name: document_id
        in: path
        required: true
        description: Document id
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /price-groups:
    get:
      tags:
      - Masterdata
      summary: List price groups
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PriceGroupsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /price-groups/{id}:
    get:
      tags:
      - Masterdata
      summary: Get a price group
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PriceGroupResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /activities:
    get:
      tags:
      - Masterdata
      summary: List activities
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MasterDataActivitiesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /activities/{id}:
    get:
      tags:
      - Masterdata
      summary: Get an activity
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MasterDataActivityResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /absence-reasons:
    get:
      tags:
      - Masterdata
      summary: List absence reasons
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MasterDataAbsenceReasonsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /absence-reasons/{id}:
    get:
      tags:
      - Masterdata
      summary: Get an absence reason
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MasterDataAbsenceReasonResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /categories:
    get:
      tags:
      - Masterdata
      summary: List categories
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CategoriesListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /categories/{id}:
    get:
      tags:
      - Masterdata
      summary: Get a category
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CategoryResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /location-lists:
    get:
      tags:
      - Masterdata
      summary: List location lists
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LocationListsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /location-lists/{id}:
    get:
      tags:
      - Masterdata
      summary: Get a location list
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LocationListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /location-lists/{id}/locations:
    get:
      tags:
      - Masterdata
      summary: List locations for a location list
      parameters:
      - name: id
        in: path
        required: true
        description: Location list id
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LocationsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /locations:
    get:
      tags:
      - Masterdata
      summary: List locations
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LocationsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /locations/{id}:
    get:
      tags:
      - Masterdata
      summary: Get a location
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LocationDetailResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /dynamic-attributes:
    get:
      tags:
      - Masterdata
      summary: List dynamic attribute definitions
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DynamicAttributeDefinitionsListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /dynamic-attributes/{id}:
    get:
      tags:
      - Masterdata
      summary: Get a dynamic attribute definition
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DynamicAttributeDefinitionResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /plannings:
    get:
      tags:
      - Plannings
      summary: List planning entries
      description: Returns a paginated list of planning entries with optional filters.
      parameters:
      - name: date_from
        in: query
        required: false
        description: Filter entries on or after this date
        schema:
          type: string
          format: date
      - name: date_to
        in: query
        required: false
        description: Filter entries on or before this date
        schema:
          type: string
          format: date
      - name: employee_ids[]
        in: query
        required: false
        description: Filter by one or more employee usernames
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
      - name: project_ids[]
        in: query
        required: false
        description: Filter by one or more project ids
        style: form
        explode: true
        schema:
          type: array
          items:
            type: integer
      - name: customer_numbers[]
        in: query
        required: false
        description: Filter by one or more customer numbers
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
      - name: include_defaults
        in: query
        required: false
        description: Include default planning entries
        schema:
          type: boolean
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 15
      - name: page
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          default: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Planning'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /attendances/{id}:
    get:
      tags:
      - Attendances
      summary: Get an attendance
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Attendances
      summary: Update an attendance
      description: Fields you omit keep their current value. The booking rules are checked before the
        record is written; violations answer with 422.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - employee_id
              - date
              - from
              - to
              - project_task_id
              - project_id
              - activity_id
              properties:
                employee_id:
                  type: string
                date:
                  type: string
                  format: date
                from:
                  type: string
                to:
                  type: string
                  description: Must be a valid time (H:i:s).
                duration:
                  nullable: true
                  type: number
                locked:
                  nullable: true
                  type: boolean
                is_travel:
                  nullable: true
                  type: boolean
                billable:
                  nullable: true
                  type: boolean
                work_location_is_project_relevant:
                  nullable: true
                  type: boolean
                color:
                  nullable: true
                  type: string
                project_task_id:
                  type: number
                project_id:
                  type: number
                activity_id:
                  type: string
                start:
                  nullable: true
                  type: string
                destination:
                  nullable: true
                  type: string
                vehicle_id:
                  nullable: true
                  type: number
                private:
                  nullable: true
                  type: boolean
                km:
                  nullable: true
                  type: number
                passengers:
                  nullable: true
                  type: number
                direction_of_travel:
                  nullable: true
                  type: string
                  description: 'Leg of the journey: 0 outbound, 1 onward, 2 return.'
                work_location_id:
                  nullable: true
                  type: string
                  description: ID of the work location. Must exist.
                note:
                  nullable: true
                  type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
    delete:
      tags:
      - Attendances
      summary: Delete an attendance
      description: 'Only the lock periods are checked: closed month, approval date and recording period.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /customers/{customer_number}/contacts/{contact_id}:
    get:
      tags:
      - Customers
      summary: Get a customer contact
      parameters:
      - name: customer_number
        in: path
        required: true
        schema:
          type: string
      - name: contact_id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags:
      - Customers
      summary: Update a customer contact
      parameters:
      - name: customer_number
        in: path
        required: true
        schema:
          type: string
      - name: contact_id
        in: path
        required: true
        schema:
          type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                salutation:
                  nullable: true
                  type: string
                  maxLength: 255
                first_name:
                  type: string
                  maxLength: 255
                last_name:
                  type: string
                  maxLength: 255
                email:
                  nullable: true
                  type: string
                  format: email
                  maxLength: 255
                phone:
                  nullable: true
                  type: string
                  maxLength: 255
                fax:
                  nullable: true
                  type: string
                  maxLength: 255
                mobile:
                  nullable: true
                  type: string
                  maxLength: 255
                primary:
                  nullable: true
                  type: string
                  description: 'Contact role: `prim` for the primary contact, `sec` for the default contact.'
                department:
                  nullable: true
                  type: string
                  maxLength: 255
                job_title:
                  nullable: true
                  type: string
                  maxLength: 255
                language:
                  nullable: true
                  type: string
                  maxLength: 255
                inactive:
                  nullable: true
                  type: boolean
                title:
                  nullable: true
                  type: string
                  maxLength: 255
                username:
                  nullable: true
                  type: string
                  maxLength: 32
                  description: Portal login. Must be unique across customer contacts and employees.
                password:
                  nullable: true
                  type: string
                  minLength: 4
                categories:
                  nullable: true
                  type: array
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
    delete:
      tags:
      - Customers
      summary: Delete a customer contact
      parameters:
      - name: customer_number
        in: path
        required: true
        schema:
          type: string
      - name: contact_id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
  /planning:
    get:
      tags:
      - Plannings
      summary: Legacy alias for /plannings
      description: Kept for backwards compatibility. Answers 301 Moved Permanently to /plannings and forwards
        the query string unchanged. Use /plannings directly.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
        '401':
          $ref: '#/components/responses/UnauthorizedError'
servers:
- url: https://www.zep-online.de/{zepinstanz}/next/api/v1
  variables:
    zepinstanz:
      description: The ZEP instance name
      default: zepinstanz
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
  responses:
    NotFound:
      description: Entity not found
    UnauthorizedError:
      description: Bearer token is missing or invalid
    ValidationError:
      description: Validation error. One or more fields failed validation constraints.
      content:
        application/json:
          schema:
            type: object
            properties:
              message:
                type: string
                description: Error message
              errors:
                type: object
                description: Field-specific validation errors
                additionalProperties:
                  type: array
                  items:
                    type: string
  schemas:
    Planning:
      type: object
      properties:
        id:
          type: integer
        date:
          type: string
          format: date
          nullable: true
        employee_id:
          type: string
          nullable: true
          description: Username of the planned employee.
        project_id:
          type: integer
          nullable: true
        customer_number:
          type: string
          nullable: true
        project_task_id:
          type: integer
          nullable: true
        ticket_id:
          type: integer
          nullable: true
        subtask_id:
          type: integer
          nullable: true
        type:
          type: integer
          nullable: true
          enum:
          - 0
          - 1
          - 2
          - 3
          description: 'What the entry is planned against:

            * 0 - Internal

            * 1 - Customer

            * 2 - Project

            * 3 - Project task

            '
        kind:
          type: integer
          nullable: true
          enum:
          - 0
          - 1
          - 2
          - 3
          description: 'How the planned amount is expressed:

            * 0 - Percent

            * 1 - Days

            * 2 - Hours

            * 3 - From/to times

            '
        planning:
          type: number
          nullable: true
          description: The planned amount in the unit given by `kind`.
        from:
          type: string
          format: time
          nullable: true
        to:
          type: string
          format: time
          nullable: true
        planning_in_hours:
          type: number
          nullable: true
        planning_in_days:
          type: number
          nullable: true
        planning_in_percent:
          type: number
          nullable: true
        working_day:
          type: boolean
          nullable: true
        note:
          type: string
          nullable: true
        planning_details:
          type: object
          nullable: true
          description: Breakdown derived from `kind`.
        employee:
          type: object
          nullable: true
          description: Only present when the relation is loaded.
          properties:
            username:
              type: string
            firstname:
              type: string
              nullable: true
            lastname:
              type: string
              nullable: true
            email:
              type: string
              nullable: true
        project:
          type: object
          nullable: true
          description: Only present when the relation is loaded.
          properties:
            id:
              type: integer
            name:
              type: string
              nullable: true
        customer:
          type: object
          nullable: true
          description: Only present when the relation is loaded.
          properties:
            customer_number:
              type: string
            name:
              type: string
              nullable: true
        created_at:
          type: string
          format: date-time
          nullable: true
        updated_at:
          type: string
          format: date-time
          nullable: true
    InvoiceFile:
      type: object
      description: One downloadable file belonging to an invoice.
      properties:
        filename:
          type: string
        file_type:
          type: string
          nullable: true
        kind:
          type: string
          enum:
          - invoice
          - invoice_mail
          - attachment
          description: '* invoice - the invoice document itself

            * invoice_mail - the mail version of the invoice document

            * attachment - a file attached to the invoice

            '
        file_contents:
          type: string
          format: byte
          description: Base64-encoded file contents.
    DynamicAttributeValue:
      type: object
      description: One dynamic attribute value on a record.
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        type:
          type: string
          nullable: true
        value:
          nullable: true
          description: Type depends on the attribute definition.
    PriceFactor:
      type: object
      description: A time-based multiplier inside a price table.
      properties:
        id:
          type: integer
        price_table_id:
          type: integer
          nullable: true
        activity_id:
          type: string
          nullable: true
        day:
          type: integer
          nullable: true
          description: Weekday the factor applies to.
        start_time:
          type: string
          format: time
          nullable: true
        end_time:
          type: string
          format: time
          nullable: true
        factor:
          type: number
          nullable: true
          format: float
    PaginationLinks:
      type: object
      properties:
        first:
          type: string
          format: uri
        last:
          type: string
          format: uri
        prev:
          type: string
          format: uri
          nullable: true
        next:
          type: string
          format: uri
          nullable: true
    PaginationMeta:
      type: object
      properties:
        current_page:
          type: integer
        from:
          type: integer
        last_page:
          type: integer
        links:
          type: array
          items:
            type: object
            properties:
              url:
                type: string
                format: uri
                nullable: true
              label:
                type: string
              active:
                type: boolean
        path:
          type: string
          format: uri
        per_page:
          type: integer
        to:
          type: integer
        total:
          type: integer
    Project:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        description:
          type: string
          nullable: true
        start_date:
          type: string
          format: date-time
        end_date:
          type: string
          format: date-time
          nullable: true
        project_status_id:
          type: string
        status:
          type: object
          properties:
            id:
              type: string
            name:
              type: string
            description:
              type: string
            bookable:
              type: boolean
            order:
              type: integer
            color:
              type: string
              nullable: true
            abrechnungsrelevant:
              type: integer
        comments:
          type: string
          nullable: true
        cost_object:
          type: string
          nullable: true
        cost_object_identifier:
          type: string
          nullable: true
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
        keywords:
          type: array
          items:
            type: string
        reference_order:
          type: string
          nullable: true
        reference_commission:
          type: string
          nullable: true
        reference_procurement:
          type: string
          nullable: true
        reference_object:
          type: string
          nullable: true
        language:
          type: string
          nullable: true
        currency:
          type: string
        url:
          type: string
          nullable: true
        location_address:
          type: string
          nullable: true
        location_city:
          type: string
          nullable: true
        location_state:
          type: string
          nullable: true
        location_country:
          type: string
          nullable: true
        revenue_account:
          type: string
          nullable: true
        customer_id:
          type: integer
          nullable: true
        customer_contact_id:
          type: integer
          nullable: true
        customer_project_reference:
          type: string
          nullable: true
        customer_billing_address_id:
          type: integer
          nullable: true
        customer_shipping_address_id:
          type: integer
          nullable: true
        has_multiple_customers:
          type: boolean
          nullable: true
        department_id:
          type: integer
        billing_type:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
        billing_tasks:
          type: string
          nullable: true
        plan_hours:
          type: number
          nullable: true
        plan_hours_children:
          type: number
        plan_hours_per_day:
          type: number
          nullable: true
        plan_can_exceed:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
        plan_warning_percent:
          type: number
          nullable: true
        plan_warning_percent_2:
          type: number
          nullable: true
        plan_warning_percent_3:
          type: number
          nullable: true
        plan_wage:
          type: number
          nullable: true
        plan_expenses:
          type: string
        plan_expenses_travel:
          type: number
          nullable: true
        plan_hours_done:
          type: number
        plan_hours_invoiced:
          type: number
        default_billability:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
        receipts_billability:
          type: string
          nullable: true
        plan_wage_children:
          type: number
        categories:
          type: array
          items:
            type: string
        dynamicAttributes:
          type: array
          items:
            type: object
        tasks_count:
          type: integer
        employees_count:
          type: integer
        activities_count:
          type: integer
        priceTables:
          type: array
          items:
            $ref: '#/components/schemas/PriceTable'
    ProjectsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Project'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ProjectWithPricesResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Project'
    PriceTable:
      type: object
      properties:
        customer_number:
          type: string
          nullable: true
          description: Present only for customer price tables
        project_id:
          type: integer
          nullable: true
          description: Present only for project price tables
        id:
          type: integer
        start_date:
          type: string
          format: date
          nullable: true
        type:
          $ref: '#/components/schemas/PriceTableType'
          type: object
          nullable: true
        prices:
          type: array
          items:
            $ref: '#/components/schemas/Price'
        factors:
          type: array
          items:
            $ref: '#/components/schemas/PriceFactor'
    PriceTableType:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
    Price:
      type: object
      properties:
        activity:
          type: string
          nullable: true
        id:
          type: integer
        price_group:
          type: string
        price:
          type: string
          format: float
        price_table_id:
          type: integer
        type:
          $ref: '#/components/schemas/PriceType'
          type: object
          nullable: true
    PriceType:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
    Activity:
      type: object
      properties:
        description:
          type: string
          nullable: true
        is_travel:
          type: boolean
        is_goodwill:
          type: boolean
        note:
          type: string
          nullable: true
        travel_type:
          type: object
          nullable: true
        id:
          type: integer
        name:
          type: string
        default_factor:
          type: number
    ActivitiesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Activity'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ProjectEmployee:
      type: object
      properties:
        id:
          type: integer
        employee_id:
          type: string
        project_id:
          type: integer
        from:
          type: string
          format: date
          nullable: true
        to:
          type: string
          format: date
          nullable: true
        note:
          type: string
          nullable: true
        availability:
          type: integer
          nullable: true
        internal_rate:
          type: number
          nullable: true
        rate_type:
          type: object
          nullable: true
          properties:
            id:
              type: integer
            name:
              type: string
        type:
          type: object
          properties:
            id:
              type: string
            name:
              type: string
        priceGroup:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
            number:
              type: string
              nullable: true
            status:
              type: boolean
            description:
              type: object
              properties:
                de:
                  type: string
    ProjectEmployeesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ProjectEmployee'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ProjectTask:
      type: object
      properties:
        dynamic_attributes:
          type: array
          items:
            $ref: '#/components/schemas/DynamicAttributeValue'
        id:
          type: integer
          description: Project task ID
        name:
          type: string
          description: Task name/identifier
        status:
          type: string
          nullable: true
          description: Project task status identifier (null for parent tasks with children)
        description:
          type: string
          nullable: true
          description: Task description
        parent_id:
          type: integer
          nullable: true
          description: Parent task ID (for subtasks)
        start_date:
          type: string
          format: date
          nullable: true
          description: Task start date
        end_date:
          type: string
          format: date
          nullable: true
          description: Task end date
        billing_type:
          type: object
          nullable: true
          description: Billing type enum object
          properties:
            value:
              type: integer
              enum:
              - 0
              - 1
              - 2
              - 3
              description: Billing type value (0 = Like project, 1 = Hourly rate, 2 = Daily rate, 3 =
                Flat rate)
            label:
              type: string
              description: Human-readable billing type label
            id:
              type: integer
            name:
              type: string
        project_id:
          type: integer
          description: Project ID
        created_at:
          type: string
          format: date-time
          nullable: true
          description: Creation timestamp
        updated_at:
          type: string
          format: date-time
          nullable: true
          description: Last modification timestamp
        plan_hours_children:
          type: number
          format: float
          nullable: true
          description: Planned hours for child tasks
        plan_hours_done:
          type: number
          format: float
          nullable: true
          description: Hours completed
        plan_wage:
          type: number
          format: float
          nullable: true
          description: Planned wage/cost
        plan_hours:
          type: number
          format: float
          nullable: true
          description: Planned hours for this task
        plan_wage_children:
          type: number
          format: float
          nullable: true
          description: Planned wage/cost for child tasks
        plan_hours_invoiced:
          type: number
          format: float
          nullable: true
          description: Hours invoiced
        order_number:
          type: string
          nullable: true
          description: Order number
        tickets_import_mailbox_name:
          type: string
          nullable: true
          description: Mailbox name for ticket imports
        created:
          type: string
          format: date-time
        modified:
          type: string
          format: date-time
    ProjectTasksListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ProjectTask'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ProjectTaskResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/ProjectTask'
    ProjectPriceTablesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PriceTable'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    Attendance:
      type: object
      properties:
        id:
          type: integer
        date:
          type: string
          format: date-time
        from:
          type: string
          format: time
        to:
          type: string
          format: time
        end_date:
          type: string
          format: date
          description: 'Calendar day the booking ends on. Added in v7.12.49: `to` alone is ambiguous for
            a day-end booking, which is stored as `to = 00:00:00` on the start date but means midnight
            of the following day.'
        employee_id:
          type: string
        department_id:
          type: integer
        duration:
          type: number
        billable:
          type: boolean
        work_location_id:
          type: string
          nullable: true
        note:
          type: string
          nullable: true
        activity_id:
          type: string
        start:
          type: string
          nullable: true
        destination:
          type: string
          nullable: true
        vehicle_id:
          type: integer
          nullable: true
        private:
          type: boolean
          nullable: true
        passengers:
          type: integer
          nullable: true
        km:
          type: integer
          nullable: true
        direction_of_travel:
          type: string
          nullable: true
        created:
          type: string
          format: date-time
        modified:
          type: string
          format: date-time
        project_id:
          type: integer
        project_task_id:
          type: integer
        invoice_item_id:
          type: integer
          nullable: true
        ticket_id:
          type: integer
          nullable: true
        subtask_id:
          type: integer
          nullable: true
        work_location_is_project_relevant:
          type: boolean
        issue_id:
          type: integer
          nullable: true
        project_release:
          type: object
          nullable: true
          properties:
            id:
              type: integer
            name:
              type: string
        project_released_at:
          type: string
          nullable: true
        project_released_by:
          type: string
          nullable: true
    AttendancesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Attendance'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    Employee:
      type: object
      properties:
        username:
          type: string
        firstname:
          type: string
        lastname:
          type: string
        personal_number:
          type: string
          nullable: true
        street:
          type: string
          nullable: true
        zip:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        country:
          type: string
          nullable: true
        abbreviation:
          type: string
          nullable: true
        salutation:
          type: object
          nullable: true
          properties:
            id:
              type: string
            name:
              type: string
        title:
          type: string
          nullable: true
        email:
          type: string
          format: email
        phone:
          type: string
          nullable: true
        mobile:
          type: string
          nullable: true
        fax:
          type: string
          nullable: true
        private_phone:
          type: string
          nullable: true
        birthdate:
          type: string
          format: date-time
          nullable: true
        iban:
          type: string
          nullable: true
        bic:
          type: string
          nullable: true
        account_no:
          type: string
          nullable: true
        bank_name:
          type: string
          nullable: true
        bank_code:
          type: string
          nullable: true
        currency:
          type: string
          nullable: true
        approval_date:
          type: string
          format: date-time
          nullable: true
        vat:
          type: string
          nullable: true
        price_group:
          type: string
        employment:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
        rights:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
        department_id:
          type: integer
        language:
          type: object
          nullable: true
          properties:
            locale:
              type: string
            isoCode:
              type: string
            name:
              type: string
            dateFormat:
              type: string
            dateTimeFormat:
              type: string
            numberFormat:
              type: object
              properties:
                decimalSeparator:
                  type: string
                thousandsSeparator:
                  type: string
        personio_id:
          type: string
          nullable: true
        cost_bearer:
          type: string
          nullable: true
        tax_id:
          type: string
          nullable: true
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
        creditor_number:
          type: string
          nullable: true
        categories:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              description:
                type: object
                properties:
                  de:
                    type: string
          nullable: true
        dynamicAttributes:
          type: array
          items:
            type: object
          nullable: true
    EmployeesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Employee'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    EmployeeResponse:
      type: object
      properties:
        data:
          allOf:
          - $ref: '#/components/schemas/Employee'
          - type: object
            properties:
              absences_count:
                type: integer
    EmployeeAbsence:
      type: object
      properties:
        id:
          type: integer
        employee_id:
          type: string
        type:
          type: integer
          description: 0 = ganztägig, 1 = halbtägig, 2 = stundenweise (z. B.)
        start_date:
          type: string
          format: date-time
        end_date:
          type: string
          format: date-time
        hours:
          type: number
          nullable: true
        from:
          type: string
          format: time
          nullable: true
        to:
          type: string
          format: time
          nullable: true
        note:
          type: string
        approved:
          type: boolean
        timezone:
          type: string
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
    EmployeeAbsencesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/EmployeeAbsence'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    EmploymentPeriod:
      type: object
      properties:
        created_at:
          type: string
          format: date-time
          nullable: true
        updated_at:
          type: string
          format: date-time
          nullable: true
        id:
          type: integer
        employee_id:
          type: string
        start_date:
          type: string
          format: date-time
        end_date:
          type: string
          format: date-time
        note:
          type: string
          nullable: true
        beginning_of_year:
          type: string
          format: date-time
          nullable: true
        annual_leave_entitlement:
          type: number
        period_holiday_entitlement:
          type: number
        is_holiday_per_year:
          type: boolean
          nullable: true
        day_absent_in_hours:
          type: number
          nullable: true
        created:
          type: string
          format: date-time
        modified:
          type: string
          format: date-time
    EmploymentPeriodsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/EmploymentPeriod'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    EmploymentPeriodResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/EmploymentPeriod'
    InternalRate:
      type: object
      properties:
        id:
          type: integer
        employee_id:
          type: string
        start_date:
          type: string
          format: date-time
        internal_rate:
          type: number
          nullable: true
        note:
          type: string
          nullable: true
        monthly_rate:
          type: number
          nullable: true
        internal_rate_resets:
          type: boolean
          nullable: true
        rate_type:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
    InternalRatesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/InternalRate'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    InternalRateResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/InternalRate'
    RegularWorkingTime:
      type: object
      properties:
        monday_workday:
          type: boolean
          nullable: true
        tuesday_workday:
          type: boolean
          nullable: true
        wednesday_workday:
          type: boolean
          nullable: true
        thursday_workday:
          type: boolean
          nullable: true
        friday_workday:
          type: boolean
          nullable: true
        saturday_workday:
          type: boolean
          nullable: true
        sunday_workday:
          type: boolean
          nullable: true
        id:
          type: integer
        employee_id:
          type: string
        start_date:
          type: string
          format: date-time
          nullable: true
        monday:
          type: number
          nullable: true
        tuesday:
          type: number
          nullable: true
        wednesday:
          type: number
          nullable: true
        thursday:
          type: number
          nullable: true
        friday:
          type: number
          nullable: true
        saturday:
          type: number
          nullable: true
        sunday:
          type: number
          nullable: true
        is_monthly:
          type: boolean
          nullable: true
        monthly_hours:
          type: number
          nullable: true
        max_hours_in_month:
          type: number
          nullable: true
        max_hours_in_week:
          type: number
          nullable: true
        holidayCalendar:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
            note:
              type: string
            country:
              type: string
            region:
              type: string
            created:
              type: string
              format: date-time
            modified:
              type: string
              format: date-time
        breakRegulationType:
          type: string
          nullable: true
    RegularWorkingTimesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/RegularWorkingTime'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    RegularWorkingTimeResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/RegularWorkingTime'
    Customer:
      type: object
      properties:
        customer_number:
          type: string
        name:
          type: string
        additional_name:
          type: string
          nullable: true
        website:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        phone:
          type: string
          nullable: true
        fax:
          type: string
          nullable: true
        currency:
          type: string
        comments:
          type: string
          nullable: true
        industry:
          type: string
          nullable: true
        vat:
          type: string
          nullable: true
        tax_number:
          type: string
          nullable: true
        iban:
          type: string
          nullable: true
        bic:
          type: string
          nullable: true
        payment_target:
          type: integer
          nullable: true
        payment_target_discount:
          type: number
          nullable: true
        inactive:
          type: boolean
          description: Whether the customer is inactive. false = active, true = inactive.
        addresses:
          type: array
          description: Customer addresses (when loaded)
          items:
            type: object
        managers:
          type: array
          description: Customer managers (when loaded)
          items:
            type: object
        price_tables:
          type: array
          description: Price tables (when appended)
          items:
            type: object
        dynamic_attributes:
          type: array
          description: Dynamic attributes (when loaded)
          items:
            $ref: '#/components/schemas/DynamicAttributeValue'
            type: object
        dynamic_attributes_count:
          type: integer
          description: Count of dynamic attributes (when counted)
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
        billing_procedure:
          type: boolean
          nullable: true
        automated_invoicing:
          type: boolean
          nullable: true
        debit_payment:
          type: boolean
          nullable: true
        department_id:
          type: integer
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
          nullable: true
        dynamicAttributes:
          type: array
          items:
            type: object
          nullable: true
        addresses_count:
          type: integer
        managers_count:
          type: integer
        categories_count:
          type: integer
        dynamicAttributes_count:
          type: integer
        contacts_count:
          type: integer
        status:
          type: object
          deprecated: true
          description: 'Deprecated mirror of `inactive` with inverted polarity. Note that before the SQ2-174
            fix

            `value` was emitted straight from the underlying column, so an inactive customer was

            reported as `{ "value": 1, "label": "Active" }`; it is now correctly inverted and labelled.

            Use `inactive` instead.


            Legacy consumers may still see the older `{ id, name }` shape instead of `{ label, value }`
            depending on API version.'
          properties:
            value:
              type: integer
              enum:
              - 0
              - 1
              description: Status value (1 = Active, 0 = Inactive)
            label:
              type: string
              description: Human-readable, translated status label
            id:
              type: integer
            name:
              type: string
          nullable: true
    CustomersListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Customer'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    CustomerDetailResponse:
      type: object
      properties:
        data:
          allOf:
          - $ref: '#/components/schemas/Customer'
          - type: object
            properties:
              addresses:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    name:
                      type: string
                    address:
                      type: string
                    address_line_2:
                      type: string
                      nullable: true
                    address_line_3:
                      type: string
                      nullable: true
                    zip_code:
                      type: string
                    city:
                      type: string
                    country:
                      type: string
                      nullable: true
                    is_default:
                      type: boolean
                    is_billing_address:
                      type: boolean
                    is_shipping_address:
                      type: boolean
                      nullable: true
                    email:
                      type: string
                      nullable: true
                    email_cc:
                      type: string
                      nullable: true
                    email_bcc:
                      type: string
                      nullable: true
                    country_code:
                      type: string
                      nullable: true
                    inactive:
                      type: boolean
                      nullable: true
                    machine_readable_invoice_version:
                      type: string
                      nullable: true
              managers:
                type: array
                items:
                  type: object
                  properties:
                    username:
                      type: string
                    has_edit_customer_data_permission:
                      type: boolean
                      nullable: true
                    has_budget_responsibility_permission:
                      type: boolean
                    is_primary_employee:
                      type: boolean
              priceTables:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    start_date:
                      type: string
                    customer_number:
                      type: string
                    type:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                    prices:
                      type: array
                      items:
                        type: object
                        properties:
                          id:
                            type: integer
                          price_group:
                            type: string
                          price:
                            type: string
                          price_table_id:
                            type: integer
                          type:
                            type: object
                            properties:
                              id:
                                type: string
                              name:
                                type: string
                    factors:
                      type: array
                      items:
                        $ref: '#/components/schemas/PriceFactor'
                      nullable: true
    CustomerContact:
      type: object
      properties:
        id:
          type: integer
        first_name:
          type: string
        last_name:
          type: string
        salutation:
          type: string
          nullable: true
        title:
          type: string
          nullable: true
        phone:
          type: string
          nullable: true
        mobile:
          type: string
          nullable: true
        fax:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        primary:
          type: boolean
          nullable: true
        job_title:
          type: string
          nullable: true
        department:
          type: string
          nullable: true
          description: Added in v7.12.49.
        language:
          type: string
          nullable: true
        inactive:
          type: boolean
        categories:
          type: array
          description: Contact categories. Added in v7.12.49; only present when the relation is loaded.
          items:
            $ref: '#/components/schemas/Category'
    CustomerContactsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/CustomerContact'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    AbsenceReason:
      type: object
      properties:
        created_at:
          type: string
          format: date-time
          nullable: true
        updated_at:
          type: string
          format: date-time
          nullable: true
        name:
          type: string
        comment:
          type: string
          nullable: true
        approve:
          type: boolean
          nullable: true
        allow_self_entry:
          type: boolean
        allow_half_day_holiday:
          type: boolean
        allow_hours_of_vacation:
          type: boolean
        anyone_can_see_name:
          type: boolean
          nullable: true
        color:
          type: string
        type:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
        client_calendar_category:
          type: string
          nullable: true
        inform_employee_upon_approval_or_revocation:
          type: boolean
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
    Absence:
      type: object
      properties:
        id:
          type: integer
        employee_id:
          type: string
        type:
          type: integer
          description: 0 = holiday, 1 = absence
        start_date:
          type: string
          format: date-time
        end_date:
          type: string
          format: date-time
        hours:
          type: string
          nullable: true
        from:
          type: string
          nullable: true
        to:
          type: string
          nullable: true
        note:
          type: string
          nullable: true
        approved:
          type: boolean
        timezone:
          type: string
          nullable: true
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
        absenceReason:
          $ref: '#/components/schemas/AbsenceReason'
        leaveApprovalApplication:
          type: object
          nullable: true
    AbsencesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Absence'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    AbsenceDetailResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Absence'
    DepartmentListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Department'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    Department:
      type: object
      properties:
        id:
          type: integer
        parent_id:
          type: integer
          nullable: true
        name:
          type: string
        description:
          type: string
          nullable: true
        comments:
          type: string
          nullable: true
        status:
          type: integer
          nullable: true
        manager_count:
          type: integer
        children_count:
          type: integer
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
        children:
          type: array
          items:
            type: object
        manager:
          type: array
          items:
            type: object
            properties:
              username:
                type: string
              firstname:
                type: string
              lastname:
                type: string
              personal_number:
                type: string
              email:
                type: string
                nullable: true
    DepartmentResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/DepartmentDetail'
    DepartmentDetail:
      type: object
      properties:
        id:
          type: integer
        parent_id:
          type: integer
          nullable: true
        name:
          type: string
        description:
          type: string
          nullable: true
        comments:
          type: string
          nullable: true
        status:
          type: integer
          nullable: true
        manager:
          type: array
          items:
            $ref: '#/components/schemas/ManagerShort'
            type: object
        children_count:
          type: integer
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
        children:
          type: array
          items:
            type: object
        manager_count:
          type: integer
    ManagerShort:
      type: object
      properties:
        username:
          type: string
        firstname:
          type: string
        lastname:
          type: string
        personal_number:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
    DeviceListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Device'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    Device:
      type: object
      properties:
        id:
          type: integer
          example: 1
        type:
          type: integer
          example: 2
          nullable: true
        status:
          type: integer
          example: 0
          nullable: true
        name:
          type: string
          example: App Beispielgerät
        password:
          type: string
          nullable: true
        min_time:
          type: string
          format: time
          nullable: true
        max_time:
          type: string
          format: time
          nullable: true
        track:
          type: integer
          example: 0
          nullable: true
        display_config:
          type: object
          nullable: true
        employees_count:
          type: integer
          example: 1
        categories_count:
          type: integer
          example: 0
    DeviceDetailResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/DeviceDetail'
    DeviceDetail:
      type: object
      properties:
        id:
          type: integer
          example: 2
        type:
          type: integer
          example: 2
          nullable: true
        status:
          type: integer
          example: 0
          nullable: true
        name:
          type: string
          example: App Beispielgerät
        password:
          type: string
          nullable: true
        min_time:
          type: string
          format: time
          nullable: true
        max_time:
          type: string
          format: time
          nullable: true
        track:
          type: integer
          example: 0
          nullable: true
        display_config:
          type: object
          nullable: true
        employees:
          type: array
          items:
            $ref: '#/components/schemas/DeviceEmployee'
            type: object
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
            type: object
    DeviceEmployee:
      type: object
      properties:
        employee_id:
          type: string
          example: username123
    Receipt:
      type: object
      properties:
        id:
          type: integer
        employee_id:
          type: string
        date:
          type: string
          format: date
        receipt_type_id:
          type: string
        currency:
          type: string
        invoice_amount_currency:
          type: string
          nullable: true
        note:
          type: string
          nullable: true
        payment_method:
          type: string
        breakfast:
          type: integer
          nullable: true
        lunch_or_dinner:
          type: integer
          nullable: true
        location:
          type: string
          nullable: true
        is_amount_net:
          type: boolean
        is_invoice_amount_net:
          type: boolean
          nullable: true
        billing_status:
          type: string
          nullable: true
        performance_date:
          type: string
          format: date
          nullable: true
        client_id:
          type: integer
          nullable: true
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
        invoice_item_id:
          type: integer
          nullable: true
        project_id:
          type: integer
        project_task_id:
          type: integer
          nullable: true
        ticket_id:
          type: integer
          nullable: true
        subtask_id:
          type: integer
          nullable: true
        filename:
          type: string
          nullable: true
    ReceiptsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Receipt'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ReceiptDetailResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Receipt'
    ReceiptAmount:
      type: object
      properties:
        id:
          type: integer
          example: 1
        receipt_id:
          type: integer
          example: 2
        tax:
          type: string
          example: '19.0000'
          format: float
        quantity:
          type: string
          example: '1.0000'
          format: float
        amount:
          type: string
          example: '70.00'
          format: float
        invoicing_share:
          type: string
          example: '70.00'
          format: float
        private_share:
          type: string
          example: '0.00'
          format: float
        is_amount_net:
          type: boolean
        is_invoice_amount_net:
          type: boolean
        employee_id:
          type: string
          nullable: true
    ReceiptAmountsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReceiptAmount'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ReceiptAmountResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/ReceiptAmount'
    Ticket:
      type: object
      properties:
        categories:
          type: array
          description: Associated categories
          items:
            $ref: '#/components/schemas/Category'
        id:
          type: integer
        subject:
          type: string
        priority:
          type: integer
        status:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
        creator_username:
          type: string
          nullable: true
        processor_username:
          type: string
          nullable: true
        date:
          type: string
          format: date-time
          nullable: true
        receipt_date:
          type: string
          format: date-time
          nullable: true
        start_date:
          type: string
          format: date-time
          nullable: true
        deadline:
          type: string
          format: date-time
          nullable: true
        processing_date:
          type: string
          format: date-time
          nullable: true
        done_date:
          type: string
          format: date-time
          nullable: true
        approved_date:
          type: string
          format: date-time
          nullable: true
        rejected_date:
          type: string
          format: date-time
          nullable: true
        billed_date:
          type: string
          format: date-time
          nullable: true
        planned_hours:
          type: number
          nullable: true
          format: float
        prevent_overbooking:
          type: boolean
          nullable: true
        history_modified:
          type: string
          format: date-time
          nullable: true
        project_id:
          type: integer
        project_task_id:
          type: integer
        notify_of_completion:
          type: boolean
          nullable: true
        customer_contact_person_id:
          type: integer
          nullable: true
        history_creator_username:
          type: string
          nullable: true
        customer_reference:
          type: string
          nullable: true
        external_ticket_number:
          type: string
          nullable: true
        from_mail:
          type: string
          nullable: true
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
        keywords:
          type: array
          items:
            type: string
          nullable: true
    TicketsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Ticket'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    TicketDetailResponse:
      type: object
      properties:
        data:
          allOf:
          - $ref: '#/components/schemas/Ticket'
          - type: object
            properties:
              keywords:
                type: array
                items:
                  type: string
              categories:
                type: array
                items:
                  type: object
                  properties:
                    name:
                      type: string
                    description:
                      type: array
                      items:
                        type: string
    TicketSubtask:
      type: object
      properties:
        customer_reference:
          type: string
          nullable: true
          description: Customer reference number
        id:
          type: integer
        name:
          type: string
        ticket_id:
          type: integer
        date:
          type: string
          format: date-time
          nullable: true
        creator_username:
          type: string
        processor_username:
          type: string
          nullable: true
        subject:
          type: string
        status:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
        receipt_date:
          type: string
          format: date-time
          nullable: true
        start_date:
          type: string
          format: date
          nullable: true
        deadline:
          type: string
          format: date
          nullable: true
        processing_date:
          type: string
          format: date-time
          nullable: true
        done_date:
          type: string
          format: date-time
          nullable: true
        planned_hours:
          type: number
          nullable: true
          format: float
        prevent_overbooking:
          type: integer
          nullable: true
        history_modified:
          type: string
          format: date-time
          nullable: true
        keywords:
          type: array
          items:
            type: string
          nullable: true
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
        customer_contact_person_id:
          type: integer
          nullable: true
        history_creator_username:
          type: string
          nullable: true
    TicketSubtasksListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/TicketSubtask'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    TicketSubtaskResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/TicketSubtask'
    Invoice:
      type: object
      properties:
        id:
          type: integer
        invoice_number:
          type: string
        customer_number:
          type: string
        date:
          type: string
          format: date
        due_date:
          type: string
          format: date
          nullable: true
        status:
          type: string
        total_amount:
          type: number
        net_amount:
          type: number
        tax_amount:
          type: number
        currency:
          type: string
        payment_status:
          type: string
          nullable: true
        payment_date:
          type: string
          format: date
          nullable: true
        project_id:
          type: integer
          nullable: true
        created:
          type: string
          format: date-time
        modified:
          type: string
          format: date-time
    InvoicesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Invoice'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    InvoiceDetailResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Invoice'
    InvoiceItem:
      type: object
      properties:
        customer_number:
          type: string
          nullable: true
          description: Customer number
        from:
          type: string
          format: date
          nullable: true
          description: Start of the service period (Leistungszeitraum von)
        to:
          type: string
          format: date
          nullable: true
          description: End of the service period (Leistungszeitraum bis)
        repetition:
          type: integer
          nullable: true
          description: Repetition interval
        currency:
          type: string
          nullable: true
          description: Currency code (e.g. EUR)
        language:
          type: string
          nullable: true
          description: Language code
        status:
          type: object
          nullable: true
          description: 'Item status. id values: 0=PLANNED, 1=APPROVED, 2=BILLED, 3=CANCELED

            '
        kind:
          type: object
          nullable: true
          description: Item kind (Abrechnungsart)
        invoice_number:
          type: string
          nullable: true
          description: Parent invoice number
        invoice_text:
          type: string
          nullable: true
          description: Invoice text / description
        sorting:
          type: integer
          nullable: true
          description: Sort order within the invoice
        contains_working_hours:
          type: boolean
          nullable: true
          description: Whether this item includes working hours
        contains_receipts:
          type: boolean
          nullable: true
          description: Whether this item includes receipts
        contains_travel_expenses:
          type: boolean
          nullable: true
          description: Whether this item includes travel expenses
        planned_amount:
          type: number
          format: float
          nullable: true
          description: Planned amount (Geplanter Betrag)
        planned_date:
          type: string
          format: date
          nullable: true
          description: Planned invoice date (Geplantes Rechnungsdatum)
        billed_amount:
          type: number
          format: float
          nullable: true
          description: Billed amount (Abgerechneter Betrag)
        billed_date:
          type: string
          format: date
          nullable: true
          description: Billed date (Abrechnungsdatum)
        vat:
          type: number
          format: float
          nullable: true
          description: VAT rate in percent
        ticket_id:
          type: integer
          nullable: true
          description: Ticket id
        article_id:
          type: integer
          nullable: true
          description: Article id
        revenue_accounts:
          type: array
          description: Erlöskonten (revenue accounts) assigned to this invoice item
          items:
            type: object
            properties:
              vat:
                type: number
                format: float
                description: VAT rate for this revenue account entry
              revenue_account:
                type: string
                description: Revenue account number (Erlöskonto)
        id:
          type: integer
        invoice_id:
          type: integer
        position:
          type: integer
        description:
          type: string
        quantity:
          type: number
          format: float
          nullable: true
        unit:
          type: string
          nullable: true
        unit_price:
          type: number
          format: float
          nullable: true
        total_price:
          type: number
        tax_rate:
          type: number
        project_id:
          type: integer
          nullable: true
        project_task_id:
          type: integer
          nullable: true
    InvoiceItemsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/InvoiceItem'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    Offer:
      type: object
      properties:
        name:
          type: string
          description: Offer number / name
        customer_id:
          type: integer
          nullable: true
        customer_contact_id:
          type: integer
          nullable: true
        department_id:
          type: integer
          nullable: true
        ticket_id:
          type: integer
          nullable: true
        title:
          type: string
          nullable: true
        note:
          type: string
          nullable: true
        version:
          type: string
          nullable: true
        status_since:
          type: string
          format: date-time
          nullable: true
        responsible_username:
          type: string
          nullable: true
        processor_username:
          type: string
          nullable: true
        is_net:
          type: boolean
        default_validity:
          type: integer
          nullable: true
        order_date:
          type: string
          format: date-time
          nullable: true
        address:
          type: string
          nullable: true
        keywords:
          type: string
          nullable: true
        language:
          type: string
          nullable: true
        realization_from:
          type: string
          format: date
          nullable: true
        realization_until:
          type: string
          format: date
          nullable: true
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
            type: object
        offer_items_count:
          type: integer
          nullable: true
        order_probability_percent:
          type: integer
          nullable: true
        id:
          type: integer
        offer_number:
          type: string
        customer_number:
          type: string
        date:
          type: string
          format: date
        valid_until:
          type: string
          format: date
          nullable: true
        status:
          type: string
          nullable: true
        total_amount:
          type: number
        net_amount:
          type: number
        tax_amount:
          type: number
        currency:
          type: string
          nullable: true
        project_id:
          type: integer
          nullable: true
        accepted_date:
          type: string
          format: date
          nullable: true
        rejected_date:
          type: string
          format: date
          nullable: true
        created:
          type: string
          format: date-time
        modified:
          type: string
          format: date-time
    OffersListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Offer'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    OfferDetailResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Offer'
    EmployeeMeal:
      type: object
      properties:
        id:
          type: integer
        employee_id:
          type: string
        date:
          type: string
          format: date
        meal_type:
          type: string
          description: breakfast, lunch, or dinner
        location:
          type: string
          nullable: true
        amount:
          type: number
        currency:
          type: string
        project_id:
          type: integer
          nullable: true
        receipt_id:
          type: integer
          nullable: true
        note:
          type: string
          nullable: true
        created:
          type: string
          format: date-time
        modified:
          type: string
          format: date-time
        breakfast:
          type: boolean
          nullable: true
        lunch:
          type: boolean
          nullable: true
        dinner:
          type: boolean
          nullable: true
    EmployeeMealsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/EmployeeMeal'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    EmployeeMealResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/EmployeeMeal'
    EmployeeProject:
      type: object
      properties:
        project_id:
          type: integer
        project_name:
          type: string
        project_status:
          type: string
        role:
          type: string
          nullable: true
        start_date:
          type: string
          format: date
          nullable: true
        end_date:
          type: string
          format: date
          nullable: true
        is_active:
          type: boolean
        department_id:
          type: integer
        customer_name:
          type: string
          nullable: true
    EmployeeProjectsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/EmployeeProject'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    DepartmentChild:
      type: object
      properties:
        id:
          type: integer
        parent_id:
          type: integer
        name:
          type: string
        description:
          type: string
          nullable: true
        status:
          type: integer
          nullable: true
        children_count:
          type: integer
        employees_count:
          type: integer
    DepartmentChildrenListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/DepartmentChild'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    DepartmentEmployee:
      type: object
      properties:
        username:
          type: string
        firstname:
          type: string
        lastname:
          type: string
        email:
          type: string
        personal_number:
          type: string
          nullable: true
        position:
          type: string
          nullable: true
        employment_type:
          type: string
        is_active:
          type: boolean
    DepartmentEmployeesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/DepartmentEmployee'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ReceiptAttachment:
      type: object
      properties:
        id:
          type: integer
        receipt_id:
          type: integer
        filename:
          type: string
        file_size:
          type: integer
        mime_type:
          type: string
        uploaded_date:
          type: string
          format: date-time
        uploaded_by:
          type: string
    ReceiptAttachmentsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReceiptAttachment'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    Article:
      type: object
      properties:
        id:
          type: integer
        article_number:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        unit:
          type: string
          nullable: true
        unit_price:
          type: number
          nullable: true
          format: float
        currency:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        inactive:
          type: boolean
        description_en:
          type: string
          nullable: true
        description_fr:
          type: string
          nullable: true
        description_es:
          type: string
          nullable: true
        description_pl:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
          nullable: true
        updated_at:
          type: string
          format: date-time
          nullable: true
    ArticlesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Article'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ArticleDetailResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Article'
    WorkHourBalance:
      type: object
      properties:
        id:
          type: integer
          description: Record id
        employee_id:
          type: string
          description: Employee username
        balance:
          type: number
          format: float
          description: Overtime / work-hour balance in hours (previous-day snapshot)
        calculated_at:
          type: string
          format: date-time
          description: Timestamp of the snapshot this record is based on
        vacation:
          type: array
          description: Vacation entitlements grouped by period
          items:
            type: object
            properties:
              year:
                type: integer
                description: Calendar year this period refers to
              approved:
                type: number
                format: float
                description: Approved vacation days
              planned:
                type: number
                format: float
                description: Planned vacation days
              remaining:
                type: number
                format: float
                description: Remaining vacation days
              annual_entitlement:
                type: number
                format: float
                description: Total annual vacation entitlement in days
    WorkHourBalancesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/WorkHourBalance'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    WorkHourBalanceDetailResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/WorkHourBalance'
    InvoiceItemDetailResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/InvoiceItem'
    Transponder:
      type: object
      properties:
        rfid:
          type: string
        employee_id:
          type: string
        created:
          type: string
          format: date-time
          nullable: true
        modified:
          type: string
          format: date-time
          nullable: true
    TranspondersListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Transponder'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    PriceTablesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PriceTable'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    PriceTableDetailResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/PriceTable'
    ProjectLocation:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        project_id:
          type: integer
          nullable: true
    ProjectLocationsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ProjectLocation'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ProjectTaskEmployee:
      type: object
      properties:
        id:
          type: integer
        project_id:
          type: integer
        project_task_id:
          type: integer
        employee_id:
          type: string
        from:
          type: string
          format: date
          nullable: true
        to:
          type: string
          format: date
          nullable: true
        note:
          type: string
          nullable: true
        price_group:
          nullable: true
          allOf:
          - $ref: '#/components/schemas/PriceGroup'
    ProjectTaskEmployeesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ProjectTaskEmployee'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ProjectTaskEmployeeResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/ProjectTaskEmployee'
    OfferItem:
      type: object
      properties:
        id:
          type: integer
        offer_id:
          type: integer
        position:
          type: string
          nullable: true
        label:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        type:
          type: object
          nullable: true
        quantity:
          type: number
          format: float
          nullable: true
        unit:
          type: string
          nullable: true
        single_price:
          type: number
          format: float
          nullable: true
        receipts_mileage_money:
          type: number
          format: float
          nullable: true
        additional_meal_expenses:
          type: number
          format: float
          nullable: true
        amount_deviating_net:
          type: number
          format: float
          nullable: true
        display_calculation:
          type: boolean
        display_total:
          type: boolean
        is_alternative:
          type: boolean
        sort_order:
          type: integer
          nullable: true
        article_id:
          type: integer
          nullable: true
        expenditure_billing_type:
          type: object
          nullable: true
        vat:
          type: number
          format: float
          nullable: true
    OfferItemsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/OfferItem'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    OfferItemResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/OfferItem'
    DocumentFolder:
      type: object
      properties:
        id:
          type: integer
        folder_name:
          type: string
        parent_id:
          type: integer
          nullable: true
        type:
          type: object
          nullable: true
          description: DocumentFolderType enum
        project_id:
          type: integer
          nullable: true
          description: Present when linked to a project
        customer_number:
          type: string
          nullable: true
          description: Present when linked to a customer
        employee_username:
          type: string
          nullable: true
          description: Present when linked to an employee
        invoice_number:
          type: string
          nullable: true
          description: Present when linked to an invoice
        offer_id:
          type: integer
          nullable: true
          description: Present when linked to an offer
        subfolders:
          type: array
          items:
            $ref: '#/components/schemas/DocumentFolder'
    DocumentFoldersListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/DocumentFolder'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    DocumentFolderResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/DocumentFolder'
    Document:
      type: object
      properties:
        id:
          type: integer
        filename:
          type: string
        file_type:
          type: string
          nullable: true
        file_contents:
          type: string
          nullable: true
          description: Base64-encoded file contents
    DocumentsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Document'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    DocumentResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Document'
    PriceGroup:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        number:
          type: string
        status:
          type: boolean
        description:
          type: object
          nullable: true
    PriceGroupsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PriceGroup'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    PriceGroupResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/PriceGroup'
    MasterDataActivity:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        is_travel:
          type: boolean
        is_goodwill:
          type: boolean
        note:
          type: string
          nullable: true
        travel_type:
          type: object
          nullable: true
    MasterDataActivitiesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/MasterDataActivity'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    MasterDataActivityResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/MasterDataActivity'
    MasterDataAbsenceReason:
      type: object
      properties:
        name:
          type: string
        comment:
          type: string
          nullable: true
        approve:
          type: boolean
        allow_self_entry:
          type: boolean
        allow_half_day_holiday:
          type: boolean
        allow_hours_of_vacation:
          type: boolean
        anyone_can_see_name:
          type: boolean
        color:
          type: string
          nullable: true
        type:
          type: object
          nullable: true
        client_calendar_category:
          type: string
          nullable: true
        inform_employee_upon_approval_or_revocation:
          type: boolean
        created_at:
          type: string
          format: date-time
          nullable: true
        updated_at:
          type: string
          format: date-time
          nullable: true
    MasterDataAbsenceReasonsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/MasterDataAbsenceReason'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    MasterDataAbsenceReasonResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/MasterDataAbsenceReason'
    Category:
      type: object
      properties:
        name:
          type: string
          description: Category name/identifier
        description:
          type: object
          nullable: true
          description: Category description
        type:
          description: Category type
          nullable: true
          type: object
          properties:
            id:
              description: Type identifier
              type: string
            name:
              description: Type name
              type: string
    CategoriesListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Category'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    CategoryResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Category'
    Location:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        location_list_id:
          type: integer
          nullable: true
        daily_rate_workday:
          type: number
          format: float
          nullable: true
        daily_rate_workday_taxed:
          type: number
          format: float
          nullable: true
        daily_rate_partial:
          type: number
          format: float
          nullable: true
        daily_rate_fullday:
          type: number
          format: float
          nullable: true
        daily_rate_fullday_taxed:
          type: number
          format: float
          nullable: true
        rate_meal_flat:
          type: number
          format: float
          nullable: true
        rate_breakfast_percent:
          type: number
          format: float
          nullable: true
        rate_lunch_percent:
          type: number
          format: float
          nullable: true
        rate_dinner_percent:
          type: number
          format: float
          nullable: true
        currency:
          type: string
          nullable: true
        type:
          type: object
          nullable: true
        inland:
          type: boolean
        home_work_location:
          type: boolean
    LocationsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Location'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    LocationDetailResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Location'
    LocationList:
      type: object
      properties:
        id:
          type: integer
        startdate:
          type: string
          format: date
          nullable: true
        enddate:
          type: string
          format: date
          nullable: true
        comments:
          type: string
          nullable: true
        meal_allowance:
          type: object
          nullable: true
        locations:
          type: array
          items:
            $ref: '#/components/schemas/Location'
    LocationListsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/LocationList'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    LocationListResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/LocationList'
    DynamicAttributeDefinition:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: object
          nullable: true
        note:
          type: string
          nullable: true
        placeholder:
          type: string
          nullable: true
        position:
          type: integer
        is_active:
          type: boolean
        constraints:
          type: object
          nullable: true
        type:
          type: object
          nullable: true
        kind:
          type: object
          nullable: true
        options:
          type: object
          nullable: true
    DynamicAttributeDefinitionsListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/DynamicAttributeDefinition'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    DynamicAttributeDefinitionResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/DynamicAttributeDefinition'
security:
- bearerAuth: []
