> ## 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 Attribute Values

> Writes up to **2,000** location/attribute values per call. This is the endpoint an HRIS or store-master system calls on a schedule to keep Xenia's location profile in sync.

**Addressing the location:** exactly one of `locationExternalId` or `locationId`.

**Addressing the attribute:** at least one of `attributeExternalId`, `attributeId`, or `attributeName` (resolved in that order).

**The value** must match the attribute's declared type, and for select types every option id must exist on the definition — otherwise the call fails with `400`.

The whole batch is applied in a **single version-guarded write**: if any row fails, nothing is written. Setting a value replaces any previous value for that location/attribute pair. There is no "clear" variant on this endpoint — an attribute simply has no entry for a location until you set one.

Requires the **Public API** and **Location Attributes** workspace features plus `CAN_MANAGE_LOCATIONS`.



## OpenAPI

````yaml POST /api/v1/mgt/enterprise/workspaces/{workspaceId}/location-attribute-values/bulk-upsert
openapi: 3.1.0
info:
  title: Xenia Team API - Bulk Upsert Location Attribute Values
  description: >-
    Sets each location's value for an attribute, in bulk, addressing both the
    location and the attribute by your own `external_id` where you have one.
    Idempotent: re-sending the same payload leaves the same state.
  version: 1.0.0
servers:
  - url: https://api.xenia.team
security: []
paths:
  /api/v1/mgt/enterprise/workspaces/{workspaceId}/location-attribute-values/bulk-upsert:
    post:
      tags:
        - Enterprise Locations
      summary: Bulk Upsert Attribute Values
      description: >-
        Writes up to **2,000** location/attribute values per call. This is the
        endpoint an HRIS or store-master system calls on a schedule to keep
        Xenia's location profile in sync.


        **Addressing the location:** exactly one of `locationExternalId` or
        `locationId`.


        **Addressing the attribute:** at least one of `attributeExternalId`,
        `attributeId`, or `attributeName` (resolved in that order).


        **The value** must match the attribute's declared type, and for select
        types every option id must exist on the definition — otherwise the call
        fails with `400`.


        The whole batch is applied in a **single version-guarded write**: if any
        row fails, nothing is written. Setting a value replaces any previous
        value for that location/attribute pair. There is no "clear" variant on
        this endpoint — an attribute simply has no entry for a location until
        you set one.


        Requires the **Public API** and **Location Attributes** workspace
        features plus `CAN_MANAGE_LOCATIONS`.
      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:
                values:
                  type: array
                  minItems: 1
                  maxItems: 2000
                  items:
                    type: object
                    properties:
                      locationExternalId:
                        type: string
                        maxLength: 255
                        description: >-
                          Your own key for the location. Mutually exclusive with
                          `locationId`; one of the two is required.
                      locationId:
                        type: string
                        format: uuid
                        description: Xenia location UUID. Must belong to this workspace.
                      attributeExternalId:
                        type: string
                        maxLength: 255
                        description: Your own key for the attribute.
                      attributeId:
                        type: string
                        format: uuid
                        description: Xenia attribute UUID.
                      attributeName:
                        type: string
                        maxLength: 255
                        description: Attribute display name — the last-resort match key.
                      value:
                        description: >-
                          Typed value body — the variant must match the
                          attribute's declared type. For select types every
                          option id must exist on the definition.
                        oneOf:
                          - type: object
                            title: single_select
                            description: One selected option.
                            properties:
                              type:
                                type: string
                                const: single_select
                              selected:
                                type: string
                                description: Option id from the attribute definition.
                            required:
                              - type
                              - selected
                            additionalProperties: false
                          - type: object
                            title: multi_select
                            description: One or more selected options.
                            properties:
                              type:
                                type: string
                                const: multi_select
                              selected:
                                type: array
                                minItems: 1
                                items:
                                  type: string
                                description: Option ids from the attribute definition.
                            required:
                              - type
                              - selected
                            additionalProperties: false
                          - type: object
                            title: number
                            description: Numeric value.
                            properties:
                              type:
                                type: string
                                const: number
                              value:
                                type: number
                            required:
                              - type
                              - value
                            additionalProperties: false
                          - type: object
                            title: boolean
                            description: Boolean value.
                            properties:
                              type:
                                type: string
                                const: boolean
                              value:
                                type: boolean
                            required:
                              - type
                              - value
                            additionalProperties: false
                          - type: object
                            title: text
                            description: Free text.
                            properties:
                              type:
                                type: string
                                const: text
                              value:
                                type: string
                                minLength: 1
                            required:
                              - type
                              - value
                            additionalProperties: false
                          - type: object
                            title: date
                            description: Calendar date, `YYYY-MM-DD` (no time component).
                            properties:
                              type:
                                type: string
                                const: date
                              value:
                                type: string
                                pattern: ^\d{4}-\d{2}-\d{2}$
                            required:
                              - type
                              - value
                            additionalProperties: false
                    required:
                      - value
              required:
                - values
            example:
              values:
                - locationExternalId: STORE-1042
                  attributeExternalId: REGION
                  value:
                    type: single_select
                    selected: b0a1c2d3-4e5f-4a6b-8c9d-0e1f2a3b4c5d
                - locationExternalId: STORE-1042
                  attributeName: Drive Thru Lanes
                  value:
                    type: number
                    value: 2
                - locationId: 46715d09-1628-4b1a-a12d-f9e0bbcdbc3c
                  attributeExternalId: REMODEL_DATE
                  value:
                    type: date
                    value: '2026-09-01'
      responses:
        '200':
          description: One row per input row, with the resolved Xenia ids.
          content:
            application/json:
              example:
                data:
                  - locationId: 46715d09-1628-4b1a-a12d-f9e0bbcdbc3c
                    attributeId: 1f6c9e0a-2b7d-4d5e-9a11-8c3f5b6d7e88
                  - locationId: 46715d09-1628-4b1a-a12d-f9e0bbcdbc3c
                    attributeId: 2a7d0f1b-3c8e-4e6f-9b22-9d4a6c7e8f99
                extra_meta:
                  message: Values upserted
        '400':
          description: >-
            Bad Request - a location or attribute reference could not be
            resolved, a `locationId` does not belong to this workspace, the
            value's `type` does not match the attribute's type, or a select
            value references an option that is not on the definition. Nothing in
            the batch is written.
        '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 - route not allow-listed for API keys, missing
            `CAN_MANAGE_LOCATIONS`, or the **Public API** / **Location
            Attributes** feature is not enabled for the workspace.
        '409':
          description: Conflict - a concurrent write won the race. Retry the call.
        '422':
          description: >-
            Unprocessable Entity - body failed validation (both/neither location
            reference, no attribute reference, malformed `value`, more than
            2,000 rows).
        '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

````