Locations

Lists and gets locations for the current tenant; create, update, delete. Locations support a typed hierarchy: region, site, building, floor, room, zone. Each location has a required location_type (default site), and optional code, address_line, and external_id. Parent-type rules apply: e.g. room/zone under floor, floor under building, building under site, site under region. Set tenant context before calling these methods.

List locations

List all locations for the current tenant (from v_locations). Rows include location_type, code, address_line, external_id.

client.locations.list()

const locations = await client.locations.list()
// Returns LocationRow[]

Get by ID

Fetch a single location by ID.

client.locations.getById(id)

const location = await client.locations.getById('uuid-of-location')
// Returns LocationRow | null

Create location

Create a new location. Returns the new location UUID.

client.locations.create(params)

const locationId = await client.locations.create({
  tenantId: 'uuid-of-tenant',
  name: 'Building A',
  description: 'Main building',
  parentLocationId: null,
  locationType: 'building', // 'region' | 'site' | 'building' | 'floor' | 'room' | 'zone'; default 'site'
  code: 'BLD-A',
  addressLine: '123 Main St',
  externalId: null,
})
// Returns string (UUID)
  • Name
    tenantId
    Description

    Required. Tenant UUID.

  • Name
    name
    Description

    Required. Location display name.

  • Name
    description
    Description

    Optional. Description.

  • Name
    parentLocationId
    Description

    Optional. Parent location UUID.

  • Name
    locationType
    Description

    Optional. One of: region, site, building, floor, room, zone. Default site.

  • Name
    code
    Description

    Optional. Short code (unique per tenant).

  • Name
    addressLine
    Description

    Optional. Single-line address.

  • Name
    externalId
    Description

    Optional. External system id (e.g. CAFM).

Update location

Update an existing location. All fields except tenantId and locationId are optional.

client.locations.update(params)

await client.locations.update({
  tenantId: 'uuid-of-tenant',
  locationId: 'uuid-of-location',
  name: 'Building A (North)',
  description: null,
  parentLocationId: null,
  locationType: null,
  code: null,
  addressLine: null,
  externalId: null,
})

Bulk import

Import many locations in one call. Each row must have name; optional fields: description, parent_location_id, location_type (default site), code, address_line, external_id.

client.locations.bulkImport(params)

const result = await client.locations.bulkImport({
  tenantId: 'uuid-of-tenant',
  rows: [
    { name: 'Site Alpha', location_type: 'site', code: 'SITE-A' },
    { name: 'Building 1', parent_location_id: siteId, location_type: 'building', code: 'BLD-1' },
    { name: 'Floor 2', parent_location_id: buildingId, location_type: 'floor', code: 'FL-2' },
  ],
})
// result.created_ids, result.errors

Hierarchy and portfolio views

With tenant context set, query these views via the raw Supabase client for tree UIs, breadcrumbs, and multi-site dashboards.

v_location_hierarchy: each location with path_ids, path_names, depth (0 = root).

Hierarchy (tree / breadcrumbs)

const { data } = await client.supabase.from('v_location_hierarchy').select('*')
// Filter by depth, or build tree from path_ids

v_site_rollup: one row per site with aggregated counts (buildings, floors, rooms, zones, assets, work orders).

Site rollup (multi-site KPIs)

const { data } = await client.supabase.from('v_site_rollup').select('*')
// site_id, site_name, building_count, floor_count, room_count, asset_count, work_order_count, ...

v_portfolio_overview: tenant-level summary plus one row per site (tenant metrics plus site breakdown).

Portfolio overview

const { data } = await client.supabase.from('v_portfolio_overview').select('*')
// tenant_id, tenant_name, member_count, location_count, asset_count, work_order_count, plus per-site: site_id, site_name, site_asset_count, site_work_order_count, ...

Map zones

Saved GeoJSON shapes on the locations map (optional link to a location) are managed with client.mapZones. See Map zones.

Delete location

Delete a location by tenant and location ID.

client.locations.delete(tenantId, locationId)

await client.locations.delete('uuid-of-tenant', 'uuid-of-location')

Was this page helpful?