openapi: 3.0.0
info:
  title: ActionSubscription
  version: 2.0.0
  description: >
    An **ActionSubscription** is a compliance schedule entry: it records that a
    resource (person, equipment,

    work environment, substance, role, work group, office, PPE, or supplier) is
    subscribed to a preventive

    action and must fulfill that requirement.


    This is the API to use to enrol a person in a training course, schedule a
    medical examination for a

    worker, assign PPE to someone, plan the maintenance of a piece of equipment,
    or require a check

    procedure: in 4HSE all of these are preventive actions, and enrolling means
    creating an

    ActionSubscription that links the resource to the action.


    Use this API to:

    - Check the compliance schedule for an office (filter by `subtenant_id` with
    the `office_id`)

    - Verify compliance: filter by `status: EXPIRED` or `EXPIRING` to find
    non-conformities

    - Find all requirements for a person (filter by `subscriber_id` with the
    `person_id`)

    - Subscribe a person or resource to a preventive action


    The `status` is automatically calculated based on linked certificates:

    - `NEW`: no certificate exists for this subscription, or the certificate is
    in `draft`

    - `VALID`: a valid (not yet expired) certificate exists

    - `EXPIRING`: the certificate is about to expire (within the days defined by
    `expire_interval` on the action)

    - `EXPIRED`: the certificate has expired

    - `REVOKED`: the linked certificate has been revoked

    - `REJECTED`: the linked certificate has been rejected


    The status is automatically updated when a CertificateAction is created or
    modified that links

    a certificate to the action of this subscription.


    ActionSubscription supports historicization: when a subscription or any of
    its parent entities

    (action, office, person) is historicized, the subscription is automatically
    excluded from normal queries.

    The `parent_active` field in responses reflects this state.

    Use the `history: true` parameter in the index to include inactive
    subscriptions.
servers:
  - url: http://service.4hse.com/
security:
  - OAuth2: []
  - AccessToken: []
webhooks:
  ACTION_SUBSCRIPTION::CREATE:
    post:
      summary: Action subscription created
      security: []
      description: |
        Triggered when a new compliance schedule entry is created.
      requestBody:
        description: The newly created subscription
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ActionSubscription"
            example:
              action_subscription_id: d5e6f7a8-b9c0-1d2e-3f4a-5b6c7d8e9f0a
              action_id: c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f
              subscriber_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
              subscriber_type: PERSON
              subtenant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
              tenant_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
      responses:
        "200":
          description: Acknowledgment of the webhook event
  ACTION_SUBSCRIPTION::DELETE:
    post:
      summary: Action subscription deleted
      security: []
      description: |
        Triggered when a compliance schedule entry is deleted.
      requestBody:
        description: The deleted subscription
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ActionSubscription"
            example:
              action_subscription_id: d5e6f7a8-b9c0-1d2e-3f4a-5b6c7d8e9f0a
              action_id: c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f
              subscriber_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
              subscriber_type: PERSON
              subtenant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
              tenant_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
      responses:
        "200":
          description: Acknowledgment of the webhook event
paths:
  /v2/action-subscription/index:
    post:
      summary: index
      operationId: indexActionSubscription
      tags:
        - ActionSubscriptions
      description: >
        Returns a paginated list of the compliance schedule.


        Most useful filters:

        - `subtenant_id` (office_id) + `status` (`EXPIRED` or `EXPIRING`): find
        non-conformities in an office

        - `subscriber_id` (person_id) + `action_type`: find all requirements for
        a person by type

        - `action_id`: find all resources subscribed to a specific action

        - `action_type` + `subtenant_id`: compliance schedule for a specific
        type in an office (e.g. all training at a construction site)


        The response includes action details, subscribed resource details, and
        the most recent certificate,

        providing a complete compliance view without additional calls.
      requestBody:
        description: Parameters for searching the compliance schedule
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ActionSubscriptionIndexParams"
            example:
              filter:
                subtenant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                action_type: TRAINING
                status: EXPIRED
              per-page: 20
              page: 1
              sort: certificate_date_expire
      responses:
        "200":
          description: List of compliance schedule entries
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ViewActionSubscription"
              example:
                - action_subscription_id: d5e6f7a8-b9c0-1d2e-3f4a-5b6c7d8e9f0a
                  action_id: c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f
                  action_type: TRAINING
                  action_code: FST-01
                  action_name: Fire Safety Training Medium Risk
                  subscriber_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
                  subscriber_type: PERSON
                  subscriber_code: JS001
                  subscriber_name: Smith John
                  status: EXPIRED
                  last_certificate_id: f6a7b8c9-d0e1-2f3a-4b5c-6d7e8f9a0b1c
                  certificate_date_release: 2020-01-15
                  certificate_date_expire: 2025-01-15
                  subtenant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                  tenant_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
                  office_name: Rome North Site
                  project_name: Acme Construction Ltd
                  project_type: safety
                  owned_active: true
                  parent_active: true
          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/action-subscription/create:
    post:
      summary: create
      operationId: createActionSubscription
      tags:
        - ActionSubscriptions
      description: >
        Creates a new compliance schedule entry.


        Requires `action_id`, `subscriber_id`, `subscriber_type`, `subtenant_id`
        (office_id), and `tenant_id` (project_id).

        The `action_subscription_id` is auto-generated if not provided.


        The `subscriber_type` must be compatible with the action's
        `action_type`:

        - For `TRAINING`, `HEALTH`, `PER` actions: subscriber_type must be
        `PERSON`

        - For `MAINTENANCE` actions: subscriber_type can be `EQUIPMENT`,
        `WORK_ENVIRONMENT`, `PPE`, `OFFICE`

        - For `CHECK` actions: any subscriber_type is allowed


        A new subscription starts with status `NEW`. The status will change to
        `VALID` only when

        a CertificateAction is created that links a certificate to the action of
        this subscription

        for the same resource.
      requestBody:
        description: Compliance schedule entry to create
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ActionSubscription"
            example:
              action_id: c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f
              subscriber_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
              subscriber_type: PERSON
              subtenant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
              tenant_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
      responses:
        "201":
          description: Compliance schedule entry created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActionSubscription"
              example:
                action_subscription_id: d5e6f7a8-b9c0-1d2e-3f4a-5b6c7d8e9f0a
                action_id: c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f
                subscriber_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
                subscriber_type: PERSON
                subtenant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                tenant_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
  /v2/action-subscription/view/{id}:
    get:
      summary: view
      operationId: viewActionSubscription
      tags:
        - ActionSubscriptions
      description: |
        Retrieves a single compliance schedule entry by its ID.
      parameters:
        - name: id
          in: path
          description: The action_subscription_id to retrieve.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Compliance schedule entry found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ViewActionSubscription"
              example:
                action_subscription_id: d5e6f7a8-b9c0-1d2e-3f4a-5b6c7d8e9f0a
                action_id: c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f
                action_type: TRAINING
                action_code: FST-01
                action_name: Fire Safety Training Medium Risk
                subscriber_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
                subscriber_type: PERSON
                subscriber_code: JS001
                subscriber_name: Smith John
                status: EXPIRED
                last_certificate_id: f6a7b8c9-d0e1-2f3a-4b5c-6d7e8f9a0b1c
                certificate_date_release: 2020-01-15
                certificate_date_expire: 2025-01-15
                subtenant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                tenant_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
                office_name: Rome North Site
                project_name: Acme Construction Ltd
                owned_active: true
                parent_active: true
        "404":
          description: Compliance schedule entry not found
  /v2/action-subscription/update/{id}:
    put:
      summary: update
      operationId: updateActionSubscription
      tags:
        - ActionSubscriptions
      description: |
        Updates an existing compliance schedule entry.
      parameters:
        - name: id
          in: path
          description: The action_subscription_id to update.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: Fields to update
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ActionSubscription"
            example:
              data:
                note: Needs urgent renewal
      responses:
        "200":
          description: Compliance schedule entry updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActionSubscription"
              example:
                action_subscription_id: d5e6f7a8-b9c0-1d2e-3f4a-5b6c7d8e9f0a
                action_id: c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f
                subscriber_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
                subscriber_type: PERSON
        "404":
          description: Compliance schedule entry not found
  /v2/action-subscription/delete/{id}:
    delete:
      summary: delete
      operationId: deleteActionSubscription
      tags:
        - ActionSubscriptions
      description: |
        Deletes a compliance schedule entry.

        If `force=false` (default), the response lists child entities.
        If `force=true`, the entry and all related entities are deleted.
      parameters:
        - name: id
          in: path
          description: The action_subscription_id to delete.
          required: true
          schema:
            type: string
            format: uuid
        - name: force
          in: query
          description: If true, deletes the entry and all child entities. If false,
            returns a preview of affected entities.
          schema:
            type: boolean
            default: false
      responses:
        "204":
          description: Compliance schedule entry deleted successfully
        "400":
          description: Preview of entities that would be deleted (returned when force=false)
components:
  schemas:
    ActionSubscription:
      type: object
      properties:
        action_subscription_id:
          type: string
          format: uuid
          description: Unique identifier of the subscription. Auto-generated if not
            provided on creation.
        action_id:
          type: string
          format: uuid
          description: The preventive action this resource is subscribed to. Pass the
            `action_id` obtained from the Action API. If unknown, search via the
            Action index filtering by `subtenant_id` and `name` or
            `action_type`.
        subscriber_id:
          type: string
          format: uuid
          description: >
            The ID of the subscribed resource. What to pass depends on
            `subscriber_type`:

            - `PERSON`: pass the `person_id`

            - `EQUIPMENT`: pass the `office_equipment_id`

            - `WORK_ENVIRONMENT`: pass the `office_work_environment_id`

            - `SUBSTANCE`: pass the `office_substance_id`

            - `ROLE`: pass the `office_role_id`

            - `WORK_GROUP`: pass the `work_group_id`

            - `OFFICE`: pass the `office_id`

            - `PPE`: pass the `material_item_id`

            - `UNIT`: pass the `unit_id` (supplier)
        subscriber_type:
          type: string
          enum:
            - PERSON
            - ROLE
            - WORK_GROUP
            - WORK_ENVIRONMENT
            - SUBSTANCE
            - EQUIPMENT
            - OFFICE
            - PPE
            - UNIT
          description: >
            The type of subscribed resource. Must be compatible with the
            action's `action_type`:

            - For `TRAINING`, `HEALTH`, `PER` actions: must be `PERSON`

            - For `MAINTENANCE` actions: can be `EQUIPMENT`, `WORK_ENVIRONMENT`,
            `PPE`, `OFFICE`

            - For `CHECK` actions: any type is allowed
        data:
          type: object
          description: Additional structured data in JSON format.
        subtenant_id:
          type: string
          format: uuid
          description: The office (work location) of this subscription. Pass the
            `office_id`.
        tenant_id:
          type: string
          format: uuid
          description: The project (company) of this subscription. Pass the `project_id`.
      required:
        - action_id
        - subscriber_id
        - subscriber_type
        - subtenant_id
        - tenant_id
    ViewActionSubscription:
      type: object
      properties:
        action_subscription_id:
          type: string
          format: uuid
          description: Unique identifier of the subscription.
        action_id:
          type: string
          format: uuid
          description: The preventive action this resource is subscribed to.
        action_type:
          type: string
          enum:
            - TRAINING
            - MAINTENANCE
            - HEALTH
            - CHECK
            - PER
          description: Type of the linked action.
        action_code:
          type: string
          description: Code of the linked action.
        action_name:
          type: string
          description: Name of the linked action.
        subscriber_id:
          type: string
          format: uuid
          description: The ID of the subscribed resource.
        subscriber_type:
          type: string
          enum:
            - PERSON
            - ROLE
            - WORK_GROUP
            - WORK_ENVIRONMENT
            - SUBSTANCE
            - EQUIPMENT
            - OFFICE
            - PPE
            - UNIT
          description: The type of subscribed resource.
        subscriber_code:
          type: string
          description: Code of the subscribed resource.
        subscriber_name:
          type: string
          description: Name of the subscribed resource.
        last_certificate_id:
          type: string
          format: uuid
          description: ID of the most recent certificate linked to this subscription.
        certificate_date_release:
          type: string
          format: date
          description: Issue date of the most recent certificate. Includes the time (UTC)
            when `time_precision` is 1.
        certificate_date_expire:
          type: string
          format: date
          description: Expiration date of the most recent certificate. Includes the time
            (UTC) when `time_precision` is 1.
        time_precision:
          type: integer
          enum:
            - 0
            - 1
          description: 1 when the linked certificate uses time precision (the date fields
            carry a meaningful UTC time); 0 for date-only certificates.
            Read-only.
        last_action_session_subscription_id:
          type: string
          format: uuid
          description: ID of the most recent session subscription.
        date_latest_session:
          type: string
          format: date
          description: Date of the most recent scheduled session.
        status:
          type: string
          enum:
            - NEW
            - VALID
            - EXPIRED
            - EXPIRING
            - REVOKED
            - REJECTED
          description: >
            Compliance status of the subscription (automatically calculated):

            - `NEW`: no certificate exists, or the certificate is in `draft`

            - `VALID`: a valid (not expired) certificate exists

            - `EXPIRING`: the certificate is about to expire (within
            `expire_interval` days)

            - `EXPIRED`: the certificate has expired

            - `REVOKED`: the linked certificate has been revoked

            - `REJECTED`: the linked certificate has been rejected
        office_name:
          type: string
          description: Name of the office.
        project_name:
          type: string
          description: Name of the project (company).
        project_type:
          type: string
          enum:
            - safety
            - template
          description: Type of the parent project.
        subtenant_id:
          type: string
          format: uuid
          description: The office (work location) of this subscription.
        tenant_id:
          type: string
          format: uuid
          description: The project (company) of this subscription.
        owned_active:
          type: boolean
          nullable: true
          description: Whether this subscription is currently active in its validity period.
        parent_active:
          type: boolean
          nullable: true
          description: Whether the parent entities (action, office) are currently active.
        project_status:
          type: string
          enum:
            - active
            - suspended
            - pending_delete
            - deleted
          description: Status of the parent project.
        subscription_status:
          type: string
          enum:
            - active
            - trial
            - refused
            - expiring
          description: Status of the project subscription (billing).
        certificate_action_approvals_count:
          type: integer
          description: Number of certificate-action approvals for this subscription.
        manager:
          type: string
          format: json
          description: Action managers (JSON).
        assignee:
          type: string
          format: json
          description: Action assignees (JSON).
        watcher:
          type: string
          format: json
          description: Action watchers (JSON).
    ActionSubscriptionIndexParams:
      type: object
      properties:
        filter:
          $ref: "#/components/schemas/ViewActionSubscription"
        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.
            "-certificate_date_expire").
          enum:
            - action_type
            - action_code
            - action_name
            - subscriber_type
            - subscriber_code
            - subscriber_name
            - certificate_date_expire
            - date_latest_session
            - status
            - office_name
            - project_name
        history:
          type: boolean
          description: If true, includes historicized (no longer active) entries in the
            results. By default only current entries are returned.
      example:
        filter:
          subtenant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
          action_type: TRAINING
          status: EXPIRED
        per-page: 50
        page: 1
        sort: certificate_date_expire
  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
