openapi: 3.0.3
info:
  title: Zebra Kernel APIs
  description: |
    OpenAPI specification for the Zebra Kernel public APIs. Covers:

    - **Authentication** — `/auth/details/authtokenbased.rest`
    - **External gateway** (token-authenticated CRUD) — `/v1/api/users`, `/v1/api/units`, `/v1/api/scim/users`
    - **Kernel NextGen read APIs** (`/v1/*`) — `user-details`, `domain-details`, `departments`, `profiles`,
      `units`, `users`, `unit-attributes`, `units-by-attributes`

    All request and response keys use `snake_case`. List endpoints under `/v1/api/*` return a list envelope;
    NextGen `/v1/*` endpoints return a single-resource or list envelope as documented per operation.
  version: 1.0.0
  contact:
    name: API Support
    email: noreply@zebra.com

servers:
  - url: http://localhost:8888/kernel
    description: Local Kernel server (port 8888) — use when Swagger UI is served from the Kernel app
  - url: /kernel
    description: Current server (uses same origin as this page)
  - url: https://fs3.reflexisinc.com/kernel
    description: Development server (fs3)
  - url: http://localhost:3001
    description: CORS proxy (only when using standalone Swagger UI server on port 3000)

tags:
  - name: Auth
    description: Authentication and token-based operations
  - name: Users
    description: External user management APIs (requires kernel authorization)
  - name: Units
    description: External unit management APIs (requires kernel authorization)
  - name: SCIM Users
    description: SCIM-oriented user APIs — OIDC `id_token` query parameter; token is validated server-side
  - name: Kernel NextGen APIs
    description: |
      Read-oriented JSON APIs under `/v1/*` (user/domain details, departments, profiles, units, users, attributes).
      See each operation for required headers, pagination behavior, and error response shapes.

paths:
  /auth/details/authtokenbased.rest:
    get:
      tags:
        - Auth
      summary: Get details based on auth token
      description: |
        Retrieves user, domain, and optionally user-image details for a valid authentication token.

        - Use `request_type` to control which sections are fetched.
        - Use `projections` to limit fields returned in `user_details`.
        - When an individual section fails to fetch, the API may return **HTTP 200** with `status: "ER"`
          and that section set to `null` in the response; the `message` field carries the error description.
      operationId: getDetailsBasedOnAuthToken
      parameters:
        - name: auth_token
          in: query
          required: true
          description: The authentication token.
          schema:
            type: string
        - name: request_type
          in: query
          required: false
          description: |
            Comma-separated list of detail types to fetch (case-insensitive).
            Multiple values may be combined, for example `request_type=user_details,domain_details`.
          schema:
            type: string
            default: all
            enum: [all, user_details, domain_details, user_image_details]
        - name: projections
          in: query
          required: false
          description: |
            Comma-separated list of `snake_case` field names to limit the `user_details` response
            (only applies when `user_details` or `all` is requested). When omitted, all user fields are returned.
            `user_id` is always included in the response. Common fields: `user_id`, `user_name`, `unit_id`,
            `unit_name`, `email_id`, `telephone_no`, `locale_code`.
          schema:
            type: string
      responses:
        '200':
          description: 'Successfully retrieved details (may also be returned with `status: "ER"` when individual sections fail).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DetailsResponse'
        '400':
          description: Missing or malformed required parameter (for example `auth_token`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                missingAuthToken:
                  value:
                    STATUS: ER
                    RESPONSE: "Required request parameter 'auth_token' is not present"
        '401':
          description: Invalid or expired token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalidToken:
                  value:
                    STATUS: ER
                    RESPONSE: "Error while fetching details based on authToken. Here is the error : Invalid or expired token"
        '500':
          description: Internal server error while fetching details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/api/users.json:
    get:
      summary: List external users
      description: |
        Lists users for the given domain (LIST^USER).
        Route consumes `application/json` for matching; send `Content-Type: application/json` if required by the gateway.
      operationId: listExternalUsers
      tags:
        - Users
      parameters:
        - $ref: '#/components/parameters/XReflexisAuthTokenHeader'
        - name: include_inactive_users
          in: query
          required: false
          description: Include inactive users in the response.
          schema:
            type: boolean
            default: false
        - name: page_number
          in: query
          required: false
          description: 1-based page number.
          schema:
            type: integer
            default: 1
      responses:
        '200':
          description: List of users
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSummaryArrayResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      summary: Save external users
      description: |
        Creates or updates users for the domain (EDIT^USER). Multipart body; provide `user_details` and/or `data_load_details`.

        **Validation rule:** at least one save input must be provided — `user_details` or `data_load_details`.
        Send `idempotency-key` to make retries safe.
      operationId: saveExternalUsers
      tags:
        - Users
      parameters:
        - $ref: '#/components/parameters/XReflexisAuthTokenHeader'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                data_load_details:
                  type: string
                  format: binary
                user_details:
                  type: array
                  description: JSON array of user objects.
                  items:
                    $ref: '#/components/schemas/UserDetail'
      responses:
        '200':
          description: List of transaction statuses
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArrayResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      summary: Delete external users
      description: |
        Deletes users for the domain (DELETE^USER). Multipart body; provide `user_ids_to_delete` and/or `data_load_details`.
        Send `idempotency-key` to make retries safe.
      operationId: deleteExternalUsers
      tags:
        - Users
      parameters:
        - $ref: '#/components/parameters/XReflexisAuthTokenHeader'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                data_load_details:
                  type: string
                  format: binary
                user_ids_to_delete:
                  type: string
                  description: Comma-separated user IDs to delete.
      responses:
        '200':
          description: List of transaction statuses
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArrayResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v1/api/units.json:
    get:
      summary: List external units
      description: |
        Lists units for the given domain (LIST^UNITS).
        Route consumes `application/json` for matching; send `Content-Type: application/json` if required by the gateway.
      operationId: listExternalUnits
      tags:
        - Units
      parameters:
        - $ref: '#/components/parameters/XReflexisAuthTokenHeader'
        - name: include_closed_units
          in: query
          required: false
          description: Include closed units in the response.
          schema:
            type: boolean
            default: false
        - name: page_number
          in: query
          required: false
          description: 1-based page number.
          schema:
            type: integer
            default: 1
      responses:
        '200':
          description: List of units
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnitSummaryArrayResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      summary: Save external units
      description: |
        Creates or updates units for the domain (EDIT^UNITS). Multipart body; provide `unit_details` and/or `data_load_details`.

        **Validation rule:** at least one save input must be provided — `unit_details` or `data_load_details`.
        Send `idempotency-key` to make retries safe.
      operationId: saveExternalUnits
      tags:
        - Units
      parameters:
        - $ref: '#/components/parameters/XReflexisAuthTokenHeader'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                data_load_details:
                  type: string
                  format: binary
                unit_details:
                  type: array
                  description: JSON array of unit objects.
                  items:
                    $ref: '#/components/schemas/UnitDetail'
      responses:
        '200':
          description: List of transaction statuses
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArrayResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
#    delete:
#      summary: Delete external units
#      description: |
#        Deletes units for the domain (DELETE^UNITS). Multipart body; provide `unit_ids_to_delete` and/or `data_load_details`.
#      operationId: deleteExternalUnits
#      tags:
#        - Units
#      parameters:
#        - $ref: '#/components/parameters/XReflexisAuthTokenHeader'
#      requestBody:
#        required: true
#        content:
#          multipart/form-data:
#            schema:
#              type: object
#              properties:
#                data_load_details:
#                  type: string
#                  format: binary
#                unit_ids_to_delete:
#                  type: string
#                  description: Comma-separated unit IDs to delete.
#      responses:
#        '200':
#          description: List of transaction statuses
#          content:
#            application/json:
#              schema:
#                $ref: '#/components/schemas/ArrayResponse'

  /v1/api/scim/users/{domain_id}.json:
    get:
      summary: List SCIM users
      description: |
        Lists users for the domain via SCIM flow. Requires OIDC `id_token` query parameter; token is validated server-side (USER_LIST).
        Authentication is primarily the `id_token`; the standard gateway auth header may not apply depending on deployment.
      operationId: listSCIMUsers
      tags:
        - SCIM Users
      parameters:
        - name: domain_id
          in: path
          required: true
          description: External domain identifier
          schema:
            type: string
        - name: id_token
          in: query
          required: true
          description: OIDC identity token (id_token)
          schema:
            type: string
        - name: include_inactive_users
          in: query
          required: false
          schema:
            type: boolean
            default: false
        - name: page_number
          in: query
          required: false
          description: 1-based page number.
          schema:
            type: integer
            default: 1
      responses:
        '200':
          description: List of users (same shape as list external users)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSummaryArrayResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      summary: Save SCIM users
      description: |
        Creates or updates users after `id_token` validation (USER_EDIT). Multipart body; same fields as save external users.
        Send `idempotency-key` to make retries safe.
      operationId: saveSCIMUsers
      tags:
        - SCIM Users
      parameters:
        - name: domain_id
          in: path
          required: true
          description: External domain identifier
          schema:
            type: string
        - name: id_token
          in: query
          required: true
          description: OIDC identity token (id_token)
          schema:
            type: string
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                data_load_details:
                  type: string
                  format: binary
                user_details:
                  type: array
                  description: JSON array of user objects.
                  items:
                    $ref: '#/components/schemas/UserDetail'
      responses:
        '200':
          description: List of transaction statuses
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArrayResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      summary: Delete SCIM users
      description: |
        Deletes users after `id_token` validation (USER_DELETE). Multipart body; same fields as delete external users.
        Send `idempotency-key` to make retries safe.
      operationId: deleteSCIMUsers
      tags:
        - SCIM Users
      parameters:
        - name: domain_id
          in: path
          required: true
          description: External domain identifier
          schema:
            type: string
        - name: id_token
          in: query
          required: true
          description: OIDC identity token (id_token)
          schema:
            type: string
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                data_load_details:
                  type: string
                  format: binary
                user_ids_to_delete:
                  type: string
                  description: Comma-separated user IDs to delete.
      responses:
        '200':
          description: List of transaction statuses
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArrayResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/user-details:
    get:
      tags:
        - Kernel NextGen APIs
      summary: User details from token
      description: |
        Domain header note: if `x-reflexis-domain-x` is provided it **must match** the token's domain,
        otherwise 401. This is stricter than other `/v1` endpoints
        which allow cross-domain queries.
      operationId: v1UserDetails
      parameters:
        - $ref: '#/components/parameters/ReflexisAuthToken'
        - $ref: '#/components/parameters/ReflexisDomain'
        - name: auth_token
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: >-
            OK — envelope `object: user_details`; `data` includes the authenticated user's detail fields plus
            `currentUnit`: a full organization unit object for the user's current unit (all fields as stored in the system),
            or `null` if not resolved or empty. This is not a fixed minimal unit shape.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1EnvelopeObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v1/domain-details:
    get:
      tags:
        - Kernel NextGen APIs
      summary: Domain configuration — Import Domain JSON subset
      description: |
        Domain header note: `x-reflexis-domain-x` can specify a **different** domain than the token's — no
        domain-match assertion (unlike user-details and profiles). Omit to default to token domain.
      operationId: v1DomainDetails
      parameters:
        - $ref: '#/components/parameters/ReflexisAuthToken'
        - $ref: '#/components/parameters/ReflexisDomain'
        - name: auth_token
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: |
            OK — `data` is a filtered map: only keys allowed for Import / Export > Import Domain
            (domain configuration schema, org levels, security questions, etc.); secrets such as
            ldapServerPassword and pulsePassword are omitted. Additional `*ProductBaseUrl` keys are included when present.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1EnvelopeObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v1/departments:
    get:
      tags:
        - Kernel NextGen APIs
      summary: Departments / associations
      operationId: v1Departments
      parameters:
        - $ref: '#/components/parameters/ReflexisAuthToken'
        - $ref: '#/components/parameters/ReflexisDomain'
        - name: dept_id
          in: query
          required: false
          schema:
            type: string
        - name: org_level
          in: query
          required: false
          description: Filter by org level; applied only when >= 0. Default -1 means no org-level filter.
          schema:
            type: integer
            default: -1
        - name: associated_org_level
          in: query
          required: false
          description: |
            Accepted for compatibility (default -1). Not used for filtering; responses do not include
            expanded associated-department mappings.
          schema:
            type: integer
            default: -1
        - name: auth_token
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: >-
            OK — list envelope; `data` is an array of department maps matching the filter,
            after optional `org_level` (≥ 0) and `dept_id` filters. Rows are not a custom nested associated-department shape.
            `has_more` is always `false` (no pagination).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1EnvelopeList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v1/profiles:
    get:
      tags:
        - Kernel NextGen APIs
      summary: Security profiles in domain (requires LIST^PROFILE)
      description: |
        Domain header note: if `x-reflexis-domain-x` is provided it **must match** the token's domain,
        otherwise 401. Same restriction as user-details.
      operationId: v1Profiles
      parameters:
        - $ref: '#/components/parameters/ReflexisAuthToken'
        - $ref: '#/components/parameters/ReflexisDomain'
        - name: org_level
          in: query
          required: false
          schema:
            type: integer
        - name: product_id
          in: query
          required: false
          description: Optional — return only profiles licensed for this product id
          schema:
            type: string
        - name: auth_token
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: >-
            OK — list envelope; data is profile detail objects (sorted by seq / name).
            `has_more` is always `false` (no pagination).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1ProfilesListEnvelope'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v1/units:
    get:
      tags:
        - Kernel NextGen APIs
      summary: Units list
      description: |
        Paged list of units in the resolved domain. All filters are optional and combinable; when multiple
        filters are supplied, only units matching **all** conditions are returned.

        **Sort order:** ascending by `unitId` or `unitName`, depending on the domain's unit label format
        (name first or id first in its primary segment).
      operationId: v1Units
      parameters:
        - $ref: '#/components/parameters/ReflexisAuthToken'
        - $ref: '#/components/parameters/ReflexisDomain'
        - name: unit_id
          in: query
          required: false
          description: Comma-separated unit identifiers; a unit matches when its `unitId` is in the list.
          schema:
            type: string
        - name: parent_unit_id
          in: query
          required: false
          description: Comma-separated parent unit identifiers; a unit matches when its `parentUnitId` is in the list (direct children).
          schema:
            type: string
        - name: org_level
          in: query
          required: false
          description: When present and ≥ 0, returns only units at that org level.
          schema:
            type: integer
        - name: status
          in: query
          required: false
          description: |
            Single character only — **`O`** (open) or **`C`** (closed). Case-insensitive.
            Any other value yields **400** with `invalid_status`.
          schema:
            type: string
            enum: [O, C, o, c]
        - name: limit
          in: query
          required: false
          description: Page size; values below 1 are treated as 1. No upper cap.
          schema:
            type: integer
            default: 10
            minimum: 0
        - name: page
          in: query
          required: false
          description: Zero-based page index.
          schema:
            type: integer
            default: 0
        - name: auth_token
          in: query
          required: false
          description: Authentication token (alternative to `x-reflexis-auth-token-x` header).
          schema:
            type: string
      responses:
        '200':
          description: >-
            OK — list envelope; each unit object includes at least `unitId`, `orgLevel`, `deptId`,
            `unitName`, and `unitLevel` (other fields may be present as stored). Paged at the data source;
            `has_more` is true when another row exists after this page.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1EnvelopeList'
        '400':
          description: Invalid `status` value — flat error body (not list envelope).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1NextGenClientError'
              examples:
                invalidStatus:
                  value:
                    type: validation_error
                    code: invalid_status
                    message: status must be 'O' or 'C'.
                    param: status
        '401':
          $ref: '#/components/responses/Unauthorized'
  /v1/users:
    get:
      tags:
        - Kernel NextGen APIs
      summary: Users list
      description: |
        Paged list of users in the resolved domain. At least one of `unit_id` (from query or the token's
        current unit), `profile_id`, or `dept_id` must resolve to a value — otherwise **400**.

        Closed units are excluded from results. Record order follows the domain's `userSortOrder` configuration.
      operationId: v1Users
      parameters:
        - $ref: '#/components/parameters/ReflexisAuthToken'
        - $ref: '#/components/parameters/ReflexisDomain'
        - name: unit_id
          in: query
          required: false
          description: >-
            Restrict results to this unit. When omitted, the authenticated caller's current unit is used if
            available.
          schema:
            type: string
        - name: include_line_of_sight
          in: query
          required: false
          description: |
            When **on** and `unit_id` is supplied, includes users in the unit's line-of-sight hierarchy
            (the unit and all its descendants). When **off**, only users whose primary unit equals `unit_id`
            are included.

            Accepted **on** values (case-insensitive): `true`, `1`, `y`, `yes`, `enabled`. Any other non-empty
            value is treated as **off**.
          schema:
            type: string
        - name: profile_id
          in: query
          required: false
          description: Comma-separated profile identifiers; a user matches when at least one of its profiles is in the list.
          schema:
            type: string
        - name: dept_id
          in: query
          required: false
          description: Comma-separated department identifiers; a user matches when at least one of its departments is in the list.
          schema:
            type: string
        - name: user_name
          in: query
          required: false
          description: Case-insensitive substring / regex match on `userName`.
          schema:
            type: string
        - name: limit
          in: query
          required: false
          description: Page size; values below 1 are treated as 1. No upper cap.
          schema:
            type: integer
            default: 10
            minimum: 0
        - name: page
          in: query
          required: false
          description: Zero-based page index.
          schema:
            type: integer
            default: 0
        - name: auth_token
          in: query
          required: false
          description: Authentication token (alternative to `x-reflexis-auth-token-x` header).
          schema:
            type: string
      responses:
        '200':
          description: >-
            OK — list envelope; user rows matching the filter. Paged at the data source;
            `has_more` is true when another row exists after this page.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1EnvelopeList'
        '400':
          description: Neither `unit_id` (from query or token), `profile_id`, nor `dept_id` resolves to a value — flat error body (not list envelope).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1NextGenClientError'
              examples:
                unitIdRequired:
                  value:
                    type: invalid_request
                    code: unit_id_required
                    message: Provide unit_id, profile_id, or dept_id
                    param: null
        '401':
          $ref: '#/components/responses/Unauthorized'
  /v1/unit-attributes:
    get:
      tags:
        - Kernel NextGen APIs
      summary: Unit attributes with distinct values
      operationId: v1UnitAttributes
      parameters:
        - $ref: '#/components/parameters/ReflexisAuthToken'
        - $ref: '#/components/parameters/ReflexisDomain'
        - name: los_unit_id
          in: query
          required: false
          description: >-
            Optional. Line-of-sight unit id used when resolving which units' attributes to include; combined with
            other filters, the server resolves the effective unit set for attribute discovery.
          schema:
            type: string
        - name: unit_ids
          in: query
          required: false
          description: >-
            Optional, repeatable. Restrict results to these unit ids (filter).
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
        - name: entity_type
          in: query
          required: false
          description: >-
            Optional. Entity type filter; defaults to `U` when omitted.
          schema:
            type: string
        - name: auth_token
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: >-
            OK — list envelope; `data` is the list of attribute value objects built from the server's map of
            attribute names to distinct values (attribute-name keys are not repeated on each item — each value
            object carries its own identity). `has_more` is always `false` (no pagination).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1EnvelopeList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v1/units-by-attributes:
    post:
      tags:
        - Kernel NextGen APIs
      summary: Units by attribute values
      operationId: v1UnitsByAttributes
      parameters:
        - $ref: '#/components/parameters/ReflexisAuthToken'
        - $ref: '#/components/parameters/ReflexisDomain'
        - name: auth_token
          in: query
          required: false
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V1UnitsByAttributesRequest'
            examples:
              scalarAttributes:
                summary: Scalar values
                value:
                  org_level: 2
                  attributes:
                    store_type: Flagship
                    region: Northeast
              multiValueAttributes:
                summary: Multi-value per attribute (JSON arrays)
                value:
                  org_level: 2
                  attributes:
                    store_type:
                      - Flagship
                      - Outlet
                    region:
                      - Northeast
                      - Midwest
      responses:
        '200':
          description: >-
            OK — list envelope; `data` is an array of organization unit objects matching the given attributes.
            `has_more` is always `false` (no pagination).
            An empty or missing JSON body yields `400` (validation_error).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1EnvelopeList'
        '400':
          description: Missing org_level or attributes — flat error body (not list envelope)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1NextGenClientError'
              examples:
                attributesRequired:
                  value:
                    type: validation_error
                    code: invalid_parameter
                    message: org_level and attributes (or attributes_map) are required.
                    param: null
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'

components:
  parameters:
    XReflexisAuthTokenHeader:
      name: X-reflexis-auth-token-X
      in: header
      required: true
      description: Mandatory auth token header value provided by the user.
      schema:
        type: string
    ReflexisAuthToken:
      name: x-reflexis-auth-token-x
      in: header
      required: false
      description: Authentication token (or use auth_token query param)
      schema:
        type: string
    ReflexisDomain:
      name: x-reflexis-domain-x
      in: header
      required: false
      description: Domain id string; optional — defaults to token domain
      schema:
        type: string
    IdempotencyKey:
      name: idempotency-key
      in: header
      required: false
      description: |
        Optional but recommended client-supplied unique identifier for a write request.
        Used by save / delete endpoints to make retries idempotent. Use a UUID v4 or similar.
      schema:
        type: string
  responses:
    Unauthorized:
      description: |
        Authentication failed. The request is missing a token, the token is invalid, or the token has expired.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiGatewayError'
          examples:
            missingToken:
              value:
                error:
                  type: unauthorized
                  code: unauthorized
                  message: Authentication token is missing from the request header.
                  param: null
            invalidToken:
              value:
                error:
                  type: invalid_token
                  code: invalid_token
                  message: Authentication token is invalid or expired. Please login to get a new token.
                  param: null
    BadRequest:
      description: One or more request parameters are invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiGatewayError'
          examples:
            invalidParameter:
              value:
                error:
                  type: invalid_parameter
                  code: invalid_parameter
                  message: One or more request parameters are invalid.
                  param: null
    Forbidden:
      description: User lacks the required permission for this operation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiGatewayError'
          examples:
            accessDenied:
              value:
                error:
                  type: access_denied
                  code: access_denied
                  message: User lacks required permissions.
                  param: null
    NotFound:
      description: The requested resource was not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiGatewayError'
          examples:
            notFound:
              value:
                error:
                  type: not_found
                  code: not_found
                  message: The requested resource was not found.
                  param: null
    InternalServerError:
      description: An unexpected error occurred while processing the request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiGatewayError'
          examples:
            internalError:
              value:
                error:
                  type: internal_error
                  code: internal_error
                  message: An unexpected error occurred while processing the request.
                  param: null
  schemas:
    DetailsResponse:
      type: object
      description: |
        Response containing user, domain, and optionally user-image details based on the auth token.
        Sections requested but failing to fetch are set to `null`; the `message` field carries any error description.
      properties:
        STATUS:
          type: string
          enum: [OK, ER]
          description: '`OK` for success, `ER` for error.'
          example: OK
        MESSAGE:
          type: string
          description: Human-readable status or error message.
          example: Fetch Successful
        RESPONSE:
          type: object
          description: Holds the requested data; section presence depends on `request_type`.
          properties:
            user_details:
              type: object
              description: User details (when `request_type` includes `user_details` or `all`). `null` when not requested or fetch failed.
              additionalProperties: true
              nullable: true
              properties:
                user_id:
                  type: string
                  description: Unique identifier for the user.
                user_name:
                  type: string
                  description: User display name (URL-encoded).
                unit_id:
                  type: string
                  description: Primary unit identifier.
                unit_name:
                  type: string
                  description: Unit display name.
                email_id:
                  type: string
                  format: email
                telephone_no:
                  type: string
                locale_code:
                  type: string
                lang_code:
                  type: string
                time_zone:
                  type: string
                org_lvl:
                  type: string
                parent_unit_id:
                  type: string
                unit_category:
                  type: string
            domain_details:
              type: object
              description: Domain details (when `request_type` includes `domain_details` or `all`). `null` when not requested or fetch failed.
              nullable: true
              properties:
                domain_no:
                  type: integer
                  description: Integer domain identifier.
                domain_id:
                  type: string
                  description: String domain identifier.
            user_image_details:
              type: object
              description: User image data (when `request_type` includes `user_image_details` or `all`). `null` when not requested or fetch failed.
              additionalProperties: true
              nullable: true

    ErrorResponse:
      type: object
      properties:
        STATUS:
          type: string
          example: "ER"
        RESPONSE:
          type: string
          example: "Error message"

    ApiGatewayError:
      type: object
      description: |
        Structured error envelope returned by external gateway endpoints (`/v1/api/*`).
        Wraps a single `error` object with `type`, `code`, human-readable `message`, the offending
        `param` (when applicable), and an optional documentation URL.
      properties:
        error:
          type: object
          properties:
            type:
              type: string
              description: High-level error category (for example `unauthorized`, `invalid_parameter`, `validation_error`).
              example: invalid_parameter
            code:
              type: string
              description: Machine-readable error code; clients should branch on this rather than `message`.
              example: invalid_parameter
            message:
              type: string
              description: Human-readable description of the error.
              example: One or more request parameters are invalid.
            param:
              type: string
              nullable: true
              description: Name of the request parameter or field that caused the error, when applicable.
              example: page_number
            doc_url:
              type: string
              nullable: true
              description: Optional URL to documentation describing the error.
              example: "https://{APP_URL}/kernel/errors/invalid_parameter"

    UserSummaryArrayResponse:
      type: array
      items:
        $ref: '#/components/schemas/UserSummary'

    UnitSummaryArrayResponse:
      type: array
      items:
        $ref: '#/components/schemas/UnitSummary'

    ArrayResponse:
      type: array
      items:
        $ref: '#/components/schemas/APIResponse'

    UserSummary:
      type: object
      properties:
        object:
          type: string
          example: user
        user_id:
          type: string
        user_name:
          type: string
        username:
          type: string
        first_name:
          type: string
        middle_name:
          type: string
        last_name:
          type: string
        email_id:
          type: string
          format: email
        recovery_email_id:
          type: string
          format: email
        phone_no:
          type: string
        tel_no:
          type: string
        mobile_no:
          type: string
        mobile_phone:
          type: string
        fax_no:
          type: string
        tel_carrier:
          type: string
        mobile_carrier:
          type: string
        status:
          type: string
        redirect_to_login:
          type: boolean
        unit_id:
          type: string
        works_in:
          type: string
        primary_profile:
          type: string
        profile_ids:
          type: array
          items:
            type: string
        dept_ids:
          type: array
          items:
            type: string
        time_zone:
          type: string
        locale:
          type: string
        user_no:
          type: integer
          format: int64
        user_skey:
          type: integer
          format: int64
        domain_no:
          type: integer
          format: int64
        created_by:
          type: integer
          format: int64
        updated_by:
          type: integer
          format: int64
        created_on:
          type: integer
          format: int64
          description: Epoch time in milliseconds.
        updated_on:
          type: integer
          format: int64
          description: Epoch time in milliseconds.

    UnitSummary:
      type: object
      properties:
        object:
          type: string
          example: unit
        unit_id:
          type: string
        unit_name:
          type: string
        parent_unit_id:
          type: string
        parent_unit_name:
          type: string
        status:
          type: string
        store_status:
          type: string
        org_level:
          type: integer
        level_id:
          type: string
        unit_level:
          type: string
        max_child_level:
          type: integer
        time_zone:
          type: string
        timezone_short:
          type: string
        timezone_long:
          type: string
        unit_category:
          type: string
        currency:
          type: string
        language:
          type: string
        email_id:
          type: string
          format: email
        tel_no:
          type: string
        contact_person:
          type: string
        job_title:
          type: string
        street:
          type: string
        city:
          type: string
        county:
          type: string
        state:
          type: string
        country:
          type: string
        zip_code:
          type: string
        domain_id:
          type: string
        domain_no:
          type: integer
          format: int64
        created_by:
          type: integer
          format: int64
        updated_by:
          type: integer
          format: int64
        created_on:
          type: integer
          format: int64
          description: Epoch time in milliseconds.
        updated_on:
          type: integer
          format: int64
          description: Epoch time in milliseconds.
        close_date:
          type: integer
          format: int64
        closed_eff_date_skey:
          type: integer
        closed_end_date_skey:
          type: integer
        eff_date_skey:
          oneOf:
            - type: integer
            - type: string
        end_date_skey:
          oneOf:
            - type: integer
            - type: string
        dept_ids:
          type: array
          items:
            type: string
        store_groups:
          type: array
          items:
            type: object
            additionalProperties: true
        unit_skey:
          type: integer
          format: int64
        location:
          type: object
          properties:
            coordinates:
              type: array
              items:
                type: number
            type:
              type: string
        unit_attr_0304:
          type: object
          additionalProperties: true
        unit_attr_attribute05:
          type: object
          additionalProperties: true

    APIResponse:
      type: object
      properties:
        status_code:
          type: integer
        meta_info:
          type: object
        message:
          type: string

    UserDetail:
      type: object
      additionalProperties: true
      properties:
        user_id:
          type: string
        user_name:
          type: string
        email_id:
          type: string
        phone_no:
          type: string
        recovery_email_id:
          type: string
        locale:
          type: string
        mobile_no:
          type: string
        unit_id:
          type: string
        profile_ids:
          oneOf:
            - type: string
            - type: array
              items:
                type: string
        dept_ids:
          oneOf:
            - type: string
            - type: array
              items:
                type: string
        password:
          type: string
        status:
          type: string
        fax:
          type: string
        mobile_carrier:
          type: string
        works_in:
          type: string
        primaryDeptId:
          type: string
        user_units:
          type: array
          items:
            type: object
            additionalProperties: true
            properties:
              unit_id:
                type: string
              profile_id:
                type: array
                items:
                  type: string
              dept_id:
                type: array
                items:
                  type: string
              unit_name:
                type: string
        delete_user_units:
          type: boolean

    UnitDetail:
      type: object
      additionalProperties: true
      properties:
        unit_id:
          type: string
        unit_name:
          type: string
        parent_unit_id:
          type: string
        status:
          type: string
        org_level:
          oneOf:
            - type: string
            - type: integer
        unit_category:
          type: string
        time_zone:
          type: string
        unit_radius:
          type: number
          nullable: true
        language:
          type: string
        currency:
          type: string
        latitude:
          type: number
          nullable: true
        longitude:
          type: number
          nullable: true
        street:
          type: string
          nullable: true
        zip_code:
          type: string
          nullable: true
        county:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        email_id:
          type: string
        tel_no:
          type: string
          nullable: true
        fax_no:
          type: string
          nullable: true
        functional_parent_id:
          type: string
          nullable: true
        status_of_date:
          type: string
          nullable: true
        unit_logo:
          type: object
          additionalProperties: true
        description_lang_map:
          type: object
          additionalProperties:
            type: string
        dept_id:
          type: string

    V1EnvelopeObject:
      type: object
      description: Single-resource envelope — `object`, `url`, `data`, `fetched_at`
      properties:
        object:
          type: string
        url:
          type: string
        data:
          description: Payload from kernel services (additionalProperties vary)
          type: object
          additionalProperties: true
        fetched_at:
          type: string
          format: date-time

    V1NextGenClientError:
      type: object
      description: |
        Validation / client error returned for some 400 responses (not wrapped in the list/single envelope).
      properties:
        type:
          type: string
          example: invalid_request
        code:
          type: string
          example: unit_id_required
        message:
          type: string
        param:
          type: string
          nullable: true

    V1EnvelopeList:
      type: object
      description: List envelope — `object` list, `url`, `data` array, `has_more`, optional `next_cursor`, `fetched_at`
      properties:
        object:
          type: string
          example: list
        url:
          type: string
        data:
          type: array
          items: {}
        has_more:
          type: boolean
        next_cursor:
          type: string
          nullable: true
        fetched_at:
          type: string
          format: date-time

    V1SecurityProfile:
      type: object
      description: |
        Security profile for the domain. Additional fields may be present; shape follows server-defined profile maps.
      additionalProperties: true
      properties:
        profileId:
          type: string
        profileName:
          type: string
        domainNo:
          type: integer
        orgLevel:
          type: integer
        organizationLevel:
          type: string
        seqNo:
          type: integer
        sequenceNo:
          type: integer

    V1ProfilesListEnvelope:
      type: object
      description: List envelope whose data entries are domain security profile details
      properties:
        object:
          type: string
          example: list
        url:
          type: string
        data:
          type: array
          items:
            $ref: '#/components/schemas/V1SecurityProfile'
        has_more:
          type: boolean
        next_cursor:
          type: string
          nullable: true
        fetched_at:
          type: string
          format: date-time

    V1UnitsByAttributesAttributeValue:
      description: |
        One filter value or a JSON array of values for that attribute. Arrays mean multiple allowed values
        for that attribute (OR within the attribute). Scalars are a single value (strings may be parsed as
        delimited lists per server rules).
      oneOf:
        - type: string
        - type: number
        - type: boolean
        - type: array
          items:
            oneOf:
              - type: string
              - type: number
              - type: boolean

    V1UnitsByAttributesRequest:
      type: object
      description: |
        Request body uses `org_level` plus `attributes`.
        Legacy key `attributes_map` is accepted when `attributes` is omitted (same semantics).
        Each attribute value may be a scalar or an array of scalars for multi-value match.
      required:
        - org_level
      properties:
        org_level:
          type: integer
        attributes:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/V1UnitsByAttributesAttributeValue'
          description: Attribute name → single value or array of values
        attributes_map:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/V1UnitsByAttributesAttributeValue'
          description: Legacy alias (same shape as attributes); merged when attributes is absent
        is_and_operation:
          type: boolean
        exclude_store_org_attribute_units:
          type: boolean
        status:
          type: string
        los_unit_id:
          type: string