openapi: 3.0.0
info:
  title: Office
  version: 2.0.0
  description: >
    An **Office** represents a work location, construction site, or operational
    unit within a project (company).

    It is the middle level in the hierarchy: Project (company) → Office (work
    location) → Person (worker).


    Other APIs reference the office via the `subtenant_id` field — pass the
    `office_id`.


    Use this API to:

    - Find work locations within a company (filter by `project_id`)

    - Get the `office_id` needed before creating actions, checking the
    compliance schedule, or managing personnel

    - Look up work location details (address, type, associated personnel)


    Actions and the compliance schedule (ActionSubscription) are directly linked
    to an office.

    People are assigned to offices via PersonOffice.


    When an office is no longer active (historicized), all its child entities
    (person assignments,

    actions, compliance schedule entries, etc.) are automatically excluded from
    normal queries

    without any direct changes to their data. The `parent_active` field in child
    entity responses

    reflects this state. Use the `history: true` parameter in the index to
    include inactive offices.
servers:
  - url: http://service.4hse.com/
security:
  - OAuth2: []
  - AccessToken: []
paths:
  /v2/office/index:
    post:
      summary: index
      operationId: indexOffice
      tags:
        - Offices
      description: >
        Returns a paginated list of offices.


        Most useful filters:

        - `project_id`: find all offices within a company (most common use)

        - `name`: search an office by name within a project

        - `office_type_icon`: filter by type (e.g. `construction_site` for
        construction sites)
      requestBody:
        description: Parameters for searching offices
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OfficeIndexParams"
            example:
              filter:
                project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
                name: Rome North
              per-page: 20
              page: 1
              sort: name
      responses:
        "200":
          description: List of offices
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ViewOffice"
              example:
                - office_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                  name: Rome North Site
                  project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
                  code: RN-001
                  office_type_icon: construction_site
                  street: 123 Main Road
                  locality: Rome
                  postal_code: "00198"
                  region: RM
                  country: IT
                  project_name: Acme Construction Ltd
                  project_type: safety
                  project_status: active
                  owned_active: true
                  parent_active: true
                  created_at: 1700000000
                  updated_at: 1700000001
          headers:
            X-Pagination-Current-Page:
              schema:
                type: integer
              description: Current page
            X-Pagination-Page-Count:
              schema:
                type: integer
              description: Total number of pages
            X-Pagination-Per-Page:
              schema:
                type: integer
              description: Number of items per page
            X-Pagination-Total-Count:
              schema:
                type: integer
              description: Total number of items
  /v2/office/create:
    post:
      summary: create
      operationId: createOffice
      tags:
        - Offices
      description: >
        Creates a new office within a project.


        Requires `project_id` and `name`. The `office_id` is auto-generated if
        not provided.

        The name must be unique within the project.


        After creation, the folder structure for file storage is prepared
        automatically.

        The typical next step is to assign people to the office via the
        PersonOffice API.
      requestBody:
        description: Office object to be created
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Office"
            example:
              name: Rome North Site
              project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
              code: RN-001
              office_type_icon: construction_site
              street: 123 Main Road
              locality: Rome
              postal_code: "00198"
              region: RM
              country: IT
      responses:
        "201":
          description: Office created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Office"
              example:
                office_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                name: Rome North Site
                project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
                code: RN-001
                office_type_icon: construction_site
                street: 123 Main Road
                locality: Rome
                postal_code: "00198"
                region: RM
                country: IT
                created_at: 1700000000
                updated_at: 1700000000
  /v2/office/view/{id}:
    get:
      summary: view
      operationId: viewOffice
      tags:
        - Offices
      description: |
        Retrieves a single office by its ID.
      parameters:
        - name: id
          in: path
          description: The office_id to retrieve.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Office found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ViewOffice"
              example:
                office_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                name: Rome North Site
                project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
                code: RN-001
                office_type_icon: construction_site
                street: 123 Main Road
                locality: Rome
                postal_code: "00198"
                region: RM
                country: IT
                project_name: Acme Construction Ltd
                project_type: safety
                project_status: active
                owned_active: true
                parent_active: true
                created_at: 1700000000
                updated_at: 1700000001
        "404":
          description: Office not found
  /v2/office/update/{id}:
    put:
      summary: update
      operationId: updateOffice
      tags:
        - Offices
      description: >
        Updates an existing office.


        Common use cases: changing the name, updating the address, changing the
        office type.

        The name must remain unique within the project.
      parameters:
        - name: id
          in: path
          description: The office_id to update.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: Office fields to update
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Office"
            example:
              name: Rome South Site
              street: 456 New Road
      responses:
        "200":
          description: Office updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Office"
              example:
                office_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                name: Rome South Site
                street: 456 New Road
        "404":
          description: Office not found
  /v2/office/delete/{id}:
    delete:
      summary: delete
      operationId: deleteOffice
      tags:
        - Offices
      description: >
        Deletes an office.


        If `force=false` (default), the operation is interrupted and the
        response lists all

        child entities (person assignments, actions, compliance schedule
        entries, etc.) that would be deleted.

        If `force=true`, the office and all related entities are deleted.
      parameters:
        - name: id
          in: path
          description: The office_id to delete.
          required: true
          schema:
            type: string
            format: uuid
        - name: force
          in: query
          description: If true, deletes the office and all child entities. If false,
            returns a preview of the entities that would be affected.
          schema:
            type: boolean
            default: false
      responses:
        "204":
          description: Office deleted successfully
        "400":
          description: Preview of entities that would be deleted (returned when force=false)
components:
  schemas:
    Office:
      type: object
      properties:
        office_id:
          type: string
          format: uuid
          description: Unique identifier of the office. Auto-generated if not provided on
            creation. Other APIs reference the office via the `subtenant_id`
            field — pass this value. If unknown, use the index endpoint
            filtering by `project_id` and `name` to find it.
        project_id:
          type: string
          format: uuid
          description: The project (company) this office belongs to. Pass the `project_id`
            obtained from the Project API.
        name:
          type: string
          maxLength: 255
          description: Name of the office or work location. Must be unique within the
            project.
        description:
          type: string
          description: Optional free-text description.
        street:
          type: string
          maxLength: 255
          description: Street address.
        postal_code:
          type: string
          maxLength: 50
          description: Postal code.
        region:
          type: string
          maxLength: 10
          description: Region or province code.
        locality:
          type: string
          maxLength: 50
          description: City or locality.
        country:
          type: string
          maxLength: 20
          description: ISO 3166-1 alpha-2 country code.
        tax_code:
          type: string
          maxLength: 20
          description: Tax code of the work location.
        vat:
          type: string
          maxLength: 20
          description: VAT number of the work location.
        office_type_id:
          type: string
          format: uuid
          description: Custom office type identifier.
        created_at:
          type: integer
          description: Creation timestamp.
        updated_at:
          type: integer
          description: Last modification timestamp.
        code:
          type: string
          maxLength: 50
          description: Alternative identifier code for the office.
        office_type_icon:
          type: string
          maxLength: 150
          enum:
            - office_default
            - construction_site
          description: |
            Visual type of the office:
            - `office_default`: a standard office or headquarters
            - `construction_site`: a construction site
      required:
        - project_id
        - name
    ViewOffice:
      type: object
      properties:
        office_id:
          type: string
          format: uuid
          description: Unique identifier of the office. Other APIs reference the office
            via the `subtenant_id` field — pass this value.
        project_id:
          type: string
          format: uuid
          description: The project (company) this office belongs to.
        name:
          type: string
          description: Name of the office or work location.
        description:
          type: string
          description: Optional free-text description.
        street:
          type: string
          description: Street address.
        postal_code:
          type: string
          description: Postal code.
        region:
          type: string
          description: Region or province code.
        locality:
          type: string
          description: City or locality.
        country:
          type: string
          description: ISO 3166-1 alpha-2 country code.
        tax_code:
          type: string
          description: Tax code of the work location.
        vat:
          type: string
          description: VAT number of the work location.
        office_type_id:
          type: string
          format: uuid
          description: Custom office type identifier.
        created_at:
          type: integer
          description: Creation timestamp.
        updated_at:
          type: integer
          description: Last modification timestamp.
        code:
          type: string
          description: Alternative identifier code for the office.
        office_type_icon:
          type: string
          enum:
            - office_default
            - construction_site
          description: |
            Visual type of the office:
            - `office_default`: a standard office or headquarters
            - `construction_site`: a construction site
        project_name:
          type: string
          description: Name of the project (company) this office belongs to.
        project_type:
          type: string
          enum:
            - safety
            - template
          description: Type of the parent project.
        project_status:
          type: string
          enum:
            - active
            - suspended
            - pending_delete
            - deleted
          description: Status of the parent project.
        owned_active:
          type: boolean
          nullable: true
          description: Whether this office is currently active in its validity period.
        parent_active:
          type: boolean
          nullable: true
          description: Whether the parent project is currently active.
    OfficeIndexParams:
      type: object
      properties:
        filter:
          $ref: "#/components/schemas/ViewOffice"
        per-page:
          type: integer
          minimum: 1
          default: 100
        page:
          type: integer
          minimum: 1
          default: 1
        sort:
          type: string
          description: Field to sort by. Prefix with minus for descending order (e.g.
            "-name").
          enum:
            - name
            - code
        history:
          type: boolean
          description: If true, includes historized (no longer active) entries in the
            results. By default only current entries are returned.
      example:
        filter:
          project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
          name: Rome North
        per-page: 50
        page: 1
        sort: name
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        password:
          tokenUrl: https://auth.4hse.com/realms/4hse/protocol/openid-connect/token
          scopes: {}
    AccessToken:
      type: apiKey
      in: query
      name: access-token
