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

# Bulk Upsert Sub-Locations

> Idempotently creates or updates sub-locations (e.g. a specific fridge in a store), keyed by your own `externalId`. Safe to re-run.

Up to **2000** rows per call.

**Identity:** `externalId` → `id`. A new sub-location requires an `externalId`. The `externalId` is the same one shown and editable in the web app. Send both to change a sub-location's `externalId` (match by `id`); if they name two different sub-locations the row is rejected. Each sub-location can be matched by only one row per call.

**Type:** exactly one of `typeExternalId`, `typeId` or `typeName`. **Location:** exactly one of `locationExternalId` (as used by the Enterprise Locations endpoints) or `locationId`. The location must be a **site**: a location on a site level of its hierarchy, or a location with no child locations when the workspace has no levels.

An existing sub-location can be renamed, moved to another site, and have its `status` changed. Its type cannot change (`400`). Names are unique per site and type (case-insensitive).

Set attribute values with Bulk Upsert Sub-Location Attribute Values. The call is all-or-nothing; the error message names the failing row (e.g. `subLocations[3]`).

Requires the **Public API** workspace feature, `CAN_MANAGE_LOCATIONS`, and **Sub-Locations** enabled for the workspace (contact Xenia to enable it; until then every sub-location endpoint returns `404`).



## OpenAPI

````yaml POST /api/v1/mgt/enterprise/workspaces/{workspaceId}/sub-locations/bulk-upsert
openapi: 3.1.0
info:
  title: Xenia Team API - Bulk Upsert Sub-Locations
  description: >-
    Idempotently creates or updates sub-locations (e.g. a specific fridge in a
    store), keyed by your own `externalId`. Safe to re-run.
  version: 1.0.0
servers:
  - url: https://api.xenia.team
security: []
paths:
  /api/v1/mgt/enterprise/workspaces/{workspaceId}/sub-locations/bulk-upsert:
    post:
      tags:
        - Enterprise Sub-Locations
      summary: Bulk Upsert Sub-Locations
      description: >-
        Idempotently creates or updates sub-locations (e.g. a specific fridge in
        a store), keyed by your own `externalId`. Safe to re-run.


        Up to **2000** rows per call.


        **Identity:** `externalId` → `id`. A new sub-location requires an
        `externalId`. The `externalId` is the same one shown and editable in the
        web app. Send both to change a sub-location's `externalId` (match by
        `id`); if they name two different sub-locations the row is rejected.
        Each sub-location can be matched by only one row per call.


        **Type:** exactly one of `typeExternalId`, `typeId` or `typeName`.
        **Location:** exactly one of `locationExternalId` (as used by the
        Enterprise Locations endpoints) or `locationId`. The location must be a
        **site**: a location on a site level of its hierarchy, or a location
        with no child locations when the workspace has no levels.


        An existing sub-location can be renamed, moved to another site, and have
        its `status` changed. Its type cannot change (`400`). Names are unique
        per site and type (case-insensitive).


        Set attribute values with Bulk Upsert Sub-Location Attribute Values. The
        call is all-or-nothing; the error message names the failing row (e.g.
        `subLocations[3]`).


        Requires the **Public API** workspace feature, `CAN_MANAGE_LOCATIONS`,
        and **Sub-Locations** enabled for the workspace (contact Xenia to enable
        it; until then every sub-location endpoint returns `404`).
      parameters:
        - name: workspaceId
          in: path
          required: true
          description: >-
            UUID of the workspace. Must be the workspace your API key is bound
            to.
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                subLocations:
                  type: array
                  minItems: 1
                  maxItems: 2000
                  items:
                    type: object
                    properties:
                      externalId:
                        type: string
                        maxLength: 255
                        description: Your own stable key. Required to create.
                      id:
                        type: string
                        format: uuid
                        description: Xenia sub-location id.
                      name:
                        type: string
                        maxLength: 255
                      typeExternalId:
                        type: string
                        maxLength: 255
                      typeId:
                        type: string
                        format: uuid
                      typeName:
                        type: string
                        maxLength: 120
                      locationExternalId:
                        type: string
                        maxLength: 255
                      locationId:
                        type: string
                        format: uuid
                      status:
                        type: string
                        enum:
                          - active
                          - inactive
                          - out_of_service
                        description: >-
                          Defaults to `active` on create; unchanged when
                          omitted.
                    required:
                      - name
              required:
                - subLocations
            example:
              subLocations:
                - externalId: STORE-001-FRIDGE-1
                  name: Fridge 1
                  typeExternalId: FRIDGE
                  locationExternalId: STORE-001
                - externalId: STORE-001-FRIDGE-2
                  name: Fridge 2
                  typeName: Fridge
                  locationExternalId: STORE-001
                  status: out_of_service
      responses:
        '200':
          description: One result per input row, in request order.
          content:
            application/json:
              example:
                data:
                  - externalId: STORE-001-FRIDGE-1
                    id: 54fd6d64-4e76-4c9e-8171-f1a4f1c95bf9
                    name: Fridge 1
                    created: true
                extra_meta:
                  message: Sub-locations upserted
        '400':
          description: >-
            Bad Request - the row would change a sub-location's type, an `id`
            does not resolve, `id` and `externalId` name different
            sub-locations, or two rows match the same sub-location.
        '401':
          description: >-
            Unauthorized - invalid client credentials, or the `workspaceId` in
            the path is not the workspace your key is bound to (`Client does not
            belong to this workspace`).
        '403':
          description: >-
            Forbidden - missing `CAN_MANAGE_LOCATIONS`, or the **Public API**
            feature is not enabled for the workspace.
        '404':
          description: Not Found - Sub-Locations is not enabled for this workspace.
        '409':
          description: >-
            Conflict - another sub-location of this type at this site already
            has this name (`SUB_LOCATION_NAME_TAKEN`), or the `externalId` is
            used by another sub-location (`EXTERNAL_ID_TAKEN`).
        '422':
          description: >-
            Unprocessable Entity - body failed validation, the type or location
            does not resolve in this workspace, the type is archived (create
            only), or the location is not a site (`SITE_NOT_LEAF`).
        '500':
          description: Internal Server Error.
      security:
        - clientKey: []
          clientSecret: []
components:
  securitySchemes:
    clientKey:
      type: apiKey
      in: header
      name: x-client-key
    clientSecret:
      type: apiKey
      in: header
      name: x-client-secret

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.