> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stampfactory.eu/llms.txt
> Use this file to discover all available pages before exploring further.

# Einstellungen aktualisieren

> Returns the full settings map after the update (same shape as GET).



## OpenAPI

````yaml PUT /settings
openapi: 3.1.0
info:
  title: Stampfactory API
  version: 1.0.0
  description: >-
    REST API für die Stampfactory Zeiterfassungs- und
    Personalverwaltungsplattform.


    ## Basis-URL


    Jeder Mandant hat eine eigene Subdomain: `https://{tenant}.stamp.eu/rest/…`.

    Custom Domains werden unterstützt; der Pfad-Präfix ist immer `/rest`.

    Authentifizierung über `POST /rest/login` (Bearer-Token, Laravel Sanctum).


    ## Datenformate (verbindlich, ADR 0005)


    | Typ | Format | Beispiel |

    |---|---|---|

    | Dauer (Anzeige) | String `HH:MM:SS.mmm`, Feldname ohne Suffix |
    `"08:00:00.000"` |

    | Dauer (Rohwert) | Integer Millisekunden, Feldname mit Suffix `_ms` |
    `28800000` |

    | Datum | ISO 8601 (`YYYY-MM-DD`) | `"2026-07-25"` |

    | Fachliche Zeitstempel (Stempelungen, Korrekturen) | ISO 8601 in
    Mandanten-Zeitzone | `"2026-07-25T08:00:00+02:00"` |

    | Technische Metadaten (`created_at`, `updated_at`) | ISO 8601 UTC |
    `"2026-07-25T06:00:00+00:00"` |

    | IDs | UUID bzw. TypeID-String | `"9d3f…"` |

    | Arbeitszeit-Flags | Integer-Bitmaske (`flags`), Bits siehe
    `WorkingTimeFlag` | `512` = Feiertag |

    | Monats-Perioden | `YYYY-MM` | `"2026-07"` |


    ## Responses


    Erfolgs-Responses liefern die fachliche Payload unter `data`

    (dokumentierte Ausnahmen: `POST /rest/terminal/{code}` und `/rest/mobile`).

    Listen sind, wo paginiert, im Laravel-Paginator-Format (`data` + `links` +
    `meta`).


    ## Fehlerformat


    Alle Fehler (4xx/5xx) folgen einem einheitlichen Envelope:


    ```json

    {
      "request_id": "…",
      "timestamp": "2026-07-25T06:00:00Z",
      "message": "Menschlich lesbare Meldung",
      "field_errors": { "feld": ["Meldung"] },
      "errors": [{ "title": "…", "detail": "…", "type": "https://docs.stampfactory.eu/errors#…", "_meta": { } }]
    }

    ```


    `field_errors` erscheint bei Validierungsfehlern (422). Endpoint-spezifische

    Zusatzdaten (z. B. `warnings`, `earliest`, `code`) stehen kanonisch in

    `errors[0]._meta`; Top-Level-Duplikate sind eine
    Übergangs-Kompatibilitätsschicht.

    Die `type`-URLs verlinken auf die Fehlerdokumentation.
servers:
  - url: https://{tenant}.stamp.eu/rest
    description: Production
    variables:
      tenant:
        default: demo
        description: Subdomain des Mandanten
security:
  - http: []
paths:
  /settings:
    put:
      tags:
        - Sonstiges
      summary: PUT /rest/settings — Bulk-update tenant settings
      description: Returns the full settings map after the update (same shape as GET).
      operationId: tenant.settings.update
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSettingsRequest'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    additionalProperties:
                      type: string
                required:
                  - data
        '401':
          $ref: '#/components/responses/AuthenticationException'
        '422':
          $ref: '#/components/responses/ValidationException'
components:
  schemas:
    UpdateSettingsRequest:
      type: object
      description: >-
        Validation for the bulk settings update.


        `export_format` is validated against {@see ExportFormat}, the single
        source of

        truth for export formats. The previous hardcoded list
        (`csv,lodas,zucchetti`)

        predates that enum: `lodas` was the C++/stamp.json spelling for DATEV
        LODAS,

        which the enum encodes as `datev` ({@see ExportFormat::DatevLodas}). The
        list

        was therefore both too narrow (no `csv_extended`, `datev_lug`, `agenda`,

        `projects`) and inconsistent with every other consumer of the format
        value

        (`ExportController` resolves `?format=` through the enum).


        Decision: accept the enum values, and keep the legacy spelling working
        by

        normalizing `lodas` to `datev` in {@see prepareForValidation()} instead
        of

        rejecting it. Old clients (and tenants whose value was imported from

        stamp.json as `lodas`) keep saving successfully, while every new write
        stores

        the canonical enum value. Stored legacy `lodas` values are read-only
        strings

        (`Tenant::exportFormat()`) and are intentionally left untouched — no
        data

        migration is performed here.


        `language` is a deliberate subset of {@see Locale}: only the two locales
        the

        tenant-wide default is offered for today. It references the enum cases
        so a

        renamed/removed locale breaks at compile time instead of silently
        drifting.
      properties:
        company_name:
          type: string
          maxLength: 255
        timezone:
          type: string
        language:
          type: string
          enum:
            - de
            - en
        terminal_message:
          type:
            - string
            - 'null'
          maxLength: 500
        card_format:
          $ref: '#/components/schemas/CardFormat'
        zucchetti_terminal_key:
          type:
            - string
            - 'null'
          maxLength: 255
        datev_berater_nr:
          type:
            - string
            - 'null'
          maxLength: 20
        datev_mandanten_nr:
          type:
            - string
            - 'null'
          maxLength: 20
        auto_clockout_time:
          type:
            - string
            - 'null'
          pattern: ^\d+$
        night_shift_boundary:
          type:
            - string
            - 'null'
          pattern: ^\d+$
        auto_approve_corrections_minutes:
          type:
            - integer
            - 'null'
          minimum: 1
          maximum: 120
        compliance_min_rest_hours:
          type: integer
          minimum: 10
          maximum: 11
        compliance_night_start:
          type: integer
          minimum: 22
          maximum: 24
        compliance_night_end:
          type: integer
          minimum: 5
          maximum: 7
        compliance_min_free_sundays:
          type: integer
          minimum: 6
          maximum: 15
        compliance_average_period_weeks:
          type: integer
          minimum: 4
          maximum: 52
        compliance_night_worker_avg_weeks:
          type: integer
          minimum: 4
          maximum: 8
        vacation_carryover_cutoff:
          type: string
          pattern: ^(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
        vacation_extra_expiry:
          type:
            - string
            - 'null'
          pattern: ^(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
        vacation_rounding_enabled:
          type: string
          enum:
            - '0'
            - '1'
        vacation_waiting_period_enabled:
          type: string
          enum:
            - '0'
            - '1'
        vacation_waiting_period_display_mode:
          type: string
          enum:
            - anteilig
            - voll_mit_hinweis
            - zurueckhalten
        vacation_reminder_channels:
          type: string
          pattern: ^(inbox|push|email)(,(inbox|push|email))*$
        pause_staged:
          type: string
          enum:
            - '0'
            - '1'
        export_format:
          $ref: '#/components/schemas/ExportFormat'
        roster.auto_pause_mode:
          $ref: '#/components/schemas/RosterAutoPauseMode'
        roster.no_show_detection:
          type: string
          enum:
            - '0'
            - '1'
        roster.clock_in_window_minutes:
          type:
            - integer
            - 'null'
          minimum: 1
          maximum: 1440
        roster.capture_capping:
          type: string
          enum:
            - 'off'
            - shift_start
            - shift_bounds
        roster.capture_rounding:
          type: string
          enum:
            - 'off'
            - '5'
            - '10'
            - '15'
        roster.capture_rounding_mode:
          type: string
          enum:
            - employer
            - nearest
        roster.flag_unplanned_capture:
          type: string
          enum:
            - '0'
            - '1'
        roster.unplanned_tolerance_minutes:
          type: integer
          minimum: 0
          maximum: 1440
        roster.enforce_work_areas:
          type: string
          enum:
            - '0'
            - '1'
        roster.fairness_window_weeks:
          type: integer
          minimum: 1
          maximum: 52
        roster.wish_budget_per_month:
          type: integer
          minimum: 1
          maximum: 100
        roster.auto_post_open_on_understaffing:
          type: string
          enum:
            - '0'
            - '1'
        roster.self_service_swap_auto_approve:
          type: string
          enum:
            - '0'
            - '1'
        roster.acknowledgement_window_hours:
          type: integer
          minimum: 1
          maximum: 336
        payroll.surcharge_source:
          type: string
          enum:
            - flags
            - rules
      title: UpdateSettingsRequest
    CardFormat:
      type: string
      enum:
        - dec_10
        - dec_6
        - hex_6
        - hex_14
      title: CardFormat
    ExportFormat:
      type: string
      description: >
        Registry of all file-based export formats. Adding a new export (e.g.
        Agenda Lohn und Gehalt) means: implement ExportProvider, add a case
        here, add the i18n label in the frontend.
      enum:
        - csv
        - csv_extended
        - datev
        - datev_lug
        - agenda
        - zucchetti
        - projects
      title: ExportFormat
    RosterAutoPauseMode:
      type: string
      description: >
        Automatic minimum-pause deduction mode for roster days (tenant setting
        `roster.auto_pause_mode`).
      enum:
        - 'off'
        - legal
        - planned
        - max_of_both
      title: RosterAutoPauseMode
  responses:
    AuthenticationException:
      description: Unauthenticated
      content:
        application/json:
          schema:
            type: object
            properties:
              message:
                type: string
                description: Error overview.
            required:
              - message
    ValidationException:
      description: Validation error
      content:
        application/json:
          schema:
            type: object
            properties:
              message:
                type: string
                description: Errors overview.
              errors:
                type: object
                description: A detailed description of each field that failed validation.
                additionalProperties:
                  type: array
                  items:
                    type: string
            required:
              - message
              - errors
  securitySchemes:
    http:
      type: http
      description: Bearer-Token, erhalten über den Login-Endpunkt (POST /rest/login).
      scheme: bearer

````