Connected Workers Locations
The Connected Workers Locations API lets you build the structured, table‑like location data sets your workers navigate — typically a functional‑location hierarchy. A location table models any set of places as rows, with your own columns.
- Location table — a table. Has a
name, akey, and rows. Can be nested into a hierarchy. - Column — a field definition on the table (name, key, data type, ordering, display behavior).
- Item — a row: an object mapping each column's
keyto its value ({ "tplnr": "FL-1001", "name": "Pump Station A" }). Rows belong to the table.
Workspace 7
└── Location table 15 "Functional Locations" (key: functional-locations)
├── Columns: TPLNR (key: tplnr, text, title) · Name (key: name, text)
└── Items (rows):
{ "id": 1001, "tplnr": "FL-1001", "name": "Pump Station A" }
{ "id": 1002, "tplnr": "FL-1002", "name": "Pump Station B" }
Locations are the entity worker features attach to — work requests, forms, checklists, and flows are filed against a location row. Assets can link to a location, and tours/spaces can be tagged to one. See the Assets guide and the Lists guide for the other two CW table entities.
Base URL & auth
Every endpoint is scoped to a workspace and served under:
https://api.treedis.com/v2/api/workspaces/{workspaceId}/cw/locations
All endpoints require authentication (OAuth2 Bearer token or API key), and the caller must have access to the workspace. workspaceId is always a numeric ID. An API key is bound to a single workspace and can only address its own.
Keys — address tables and columns by id or slug
Tables and columns each have a key — a URL‑safe slug (lowercase, no spaces), generated automatically from the name on create (or passed). Keys are unique within their scope and never all‑numeric.
- Anywhere a path takes
{columnId}, pass either the numeric id or the key (e.g.…/cw/locations/columns/tplnr). A purely numeric value is an id; anything else is a key. The Locations table itself is not addressed by id — it is the single per-workspace table reached directly under…/cw/locations. - Rows reference columns by key — the property names in a row object are column keys.
- Items (rows) have no key — address them by their numeric
id.
Endpoints
Locations is a single per-workspace table. Unlike assets and lists (where you manage many tables), every workspace has exactly one Locations table — it is record-native. There is no table-id segment:
GETon the collection returns that one table with itscolumnsanditemsnested, and every sub-resource hangs directly off…/cw/locations(no{tableId}). There is noGET/PUT/DELETE /{tableId}and no/{tableId}/bulk; create and upsert records through the collectionPOSTandPOST /bulk.
| Method | Path (under /v2/api/workspaces/{workspaceId}/cw/locations) |
Purpose |
|---|---|---|
GET |
`` (collection) | Get the Locations table (columns + items) |
POST |
`` (collection) | Create / upsert the table |
POST |
/bulk |
Batch insert columns + rows |
GET / POST |
/columns |
List columns / create a column |
GET / PUT / DELETE |
/columns/{columnId} |
Get / update / delete a column |
GET / POST |
/items |
List rows / insert a row |
GET / PUT / DELETE |
/items/{itemId} |
Get / update / delete a row |
POST |
/items/truncate |
Truncate items (delete all rows) |
GETon the collection returns the table with itscolumnsanditemsnested. The/columnsand/itemssub-resources return those slices on their own.
Location tables
Create takes no table id — the id and key are assigned and returned.
GET/POST/v2/api/workspaces/{workspaceId}/cw/locations
| Field | Type | Notes |
|---|---|---|
name |
string | Required. Table name. |
key |
string | URL‑safe slug. Auto‑generated from name if omitted; unique within the workspace; never all‑numeric. |
status |
active | inactive |
Required. |
parentId |
number | string | null | Parent table — id or key. Tables themselves can be nested into a hierarchy. |
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/cw/locations" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-d '{ "name": "Functional Locations", "status": "active" }'
GET on the collection returns the single Locations table with its columns and items nested:
{
"success": true,
"code": 200,
"message": "Success",
"data": {
"id": 15,
"key": "functional-locations",
"name": "Functional Locations",
"status": "active",
"parentId": null,
"itemsCount": 2,
"columns": [
{
"id": 8,
"key": "tplnr",
"name": "TPLNR",
"type": "text",
"isTitle": true
},
{ "id": 9, "key": "name", "name": "Name", "type": "text" }
],
"items": [
{ "id": 1001, "tplnr": "FL-1001", "name": "Pump Station A" },
{ "id": 1002, "tplnr": "FL-1002", "name": "Pump Station B" }
]
}
}
Columns
Define the fields of the table. Create takes no column id; the key is derived from the name (or pass your own, unique within the table).
GET/POST/v2/api/workspaces/{workspaceId}/cw/locations/columnsGET/PUT/DELETE…/columns/{columnId}
| Field | Type | Notes |
|---|---|---|
name |
string | Required. Column name — unique within the table. |
key |
string | URL‑safe slug; auto‑generated from name if omitted. Used as the property name in rows. |
type |
enum | Required. See the column types below. |
order |
number | Display order. |
isRequired |
boolean | Whether a value is required. |
settings |
object | Type‑specific settings (e.g. maxLength, pattern). |
status |
active | inactive |
Column status. |
isTitle |
boolean | Marks the column shown as the row's display title in the worker view (e.g. the human-readable name). Display only. |
isPrimaryKey |
boolean | Marks the table's primary key — the column whose value uniquely identifies a row across the workspace (e.g. a plant-prefixed TPLNR like R400-20-FL-1001). Used to address a row when filing a work request by business key. |
isVisible |
boolean | Whether the column shows in the UI. |
Column types (type): text · number · date · checkbox · hierarchyParent (links a row to a parent row — used to build the location tree) · reference (links to another table/entity) · locationTag (ties the value to a tour location/tag) · space (a space/environment) · tagStatus (a status tag).
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/cw/locations/columns" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-d '{ "name": "TPLNR", "type": "text", "isRequired": true, "status": "active", "isVisible": true }'
Hierarchy
Build a parent/child tree of location rows with a hierarchyParent column — its value on a row points at the parent row (by the parent's primary‑key value). Treedis rejects a parent assignment that would create a circular reference (400).
Items (rows)
An item is a row — an object mapping each column's key to its value. Responses add the row id. Rows belong to the table.
GET/POST/v2/api/workspaces/{workspaceId}/cw/locations/itemsGET/PUT/DELETE…/items/{itemId}
# insert a row
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/cw/locations/items" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-d '{ "tplnr": "FL-1001", "name": "Pump Station A" }'
{
"success": true,
"code": 200,
"message": "Item created successfully",
"data": { "id": 1001, "tplnr": "FL-1001", "name": "Pump Station A" }
}
A PUT on …/items/{itemId} updates the row's values; send only the columns you want to change. List rows with ?filter[swerk]=R400-20, ?page / ?limit, and ?sortBy / ?sortOrder.
Batch insert
Columns are matched by name/key within the table — an existing column is reused, only a new name creates a new column. A key is optional on the table and columns (omit to auto‑generate from the name).
Batch insert (columns + rows)
POST /v2/api/workspaces/{workspaceId}/cw/locations/bulk — define columns and insert rows into the Locations table in one call, under the locations envelope. This is the call an integrator uses to push a whole functional‑location export in one request.
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/cw/locations/bulk" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-d '{
"locations": [
{
"name": "Functional Locations", "key": "functional-locations", "status": "active",
"columns": [ { "name": "TPLNR", "key": "tplnr", "type": "text", "isPrimaryKey": true }, { "name": "Name", "type": "text" } ],
"items": [
{ "tplnr": "FL-1001", "name": "Pump Station A" },
{ "tplnr": "FL-1002", "name": "Pump Station B" }
]
}
]
}'
Each surface uses its own batch envelope key —
locationshere,assetsfor the Assets surface,listsfor the Lists surface.
For data sets above a few thousand rows, upload a CSV and import it asynchronously instead of sending one large /bulk payload.
Batch insert by type
One endpoint for every surface: if a single integration pushes to more than one surface, you can send everything in one call instead of fanning out across paths. POST /v2/api/workspaces/{workspaceId}/cw/bulk takes a tables array where each table carries its own type — location, asset, list, department, or user — alongside its columns and rows. One request can mix all of them. It is equivalent to posting each table to its surface's own /bulk.
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/cw/bulk" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-d '{
"tables": [
{
"type": "location",
"name": "Functional Locations", "key": "functional-locations", "status": "active",
"columns": [ { "name": "TPLNR", "key": "tplnr", "type": "text", "isPrimaryKey": true }, { "name": "Name", "type": "text" } ],
"items": [
{ "tplnr": "FL-1001", "name": "Pump Station A" },
{ "tplnr": "FL-1002", "name": "Pump Station B" }
]
},
{
"type": "asset",
"name": "Assets", "key": "assets", "status": "active",
"columns": [ { "name": "EQUNR", "key": "equnr", "type": "text", "isPrimaryKey": true }, { "name": "Name", "type": "text" } ],
"items": [
{ "equnr": "EQ-5001", "name": "Centrifugal Pump" }
]
},
{
"type": "list",
"name": "Priorities", "key": "priorities", "status": "active",
"columns": [ { "name": "PRIOK", "key": "priok", "type": "text", "isPrimaryKey": true }, { "name": "Name", "type": "text" } ],
"items": [
{ "priok": "1", "name": "Emergency" },
{ "priok": "2", "name": "High" }
]
},
{
"type": "department",
"name": "Departments", "key": "departments", "status": "active",
"columns": [ { "name": "Name", "type": "text", "isTitle": true } ],
"items": [
{ "name": "Maintenance" },
{ "name": "Operations" }
]
}
]
}'
Each table is routed to its surface by its type, so you can create locations, assets, lists, and departments together — or send a single table when that's all you need.
Filing work requests against a location
Locations are the anchor for worker features. Create a work request at the workspace and address the location by location — the location's primary‑key value (its name / code). Treedis finds that location row and files the work request against it. Optionally link an asset with assetKey (the asset table) + asset (that asset row's primary‑key value), and/or a department with department (the department's title). The work request is sent as application/json; attachments go under files as base64 objects.
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/work-requests" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-d '{
"location": "R400-20-FL-1001",
"assetKey": "assets",
"asset": "R400-20-FL-1001-EQ",
"title": "Pump leak",
"status": "open",
"priority": "high",
"files": [
{ "filename": "photo.jpg", "contentType": "image/jpeg", "data": "/9j/4AAQSkZJRgABAQ..." }
]
}'
See the Work Requests guide for the full workflow, and Work Orders for turning a request into planned work.
Delete & truncate
- Delete a single record —
DELETE …/locations/columns/{columnId}or…/locations/items/{itemId}. - Truncate items —
POST …/locations/items/truncateremoves all rows, keeping the table and its columns.
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/cw/locations/items/truncate" \
-H "Authorization: Bearer your-access-token"
Truncate responses report how many rows were removed (data.deleted).
Errors
Errors use the same envelope with success: false and an optional details object:
{
"success": false,
"code": 400,
"message": "Cannot create a hierarchical loop",
"details": {
"error": "A table cannot have a parent that would create a circular reference"
}
}
| Status | When |
|---|---|
400 |
Validation failed, circular hierarchy, duplicate single‑use column type, or a key/column that can't be resolved |
404 |
Table, column, or item not found |
See the Connected Workers Locations tag in the API Reference for the full request and response schemas.

