Connected Workers Work Requests
A work request (a note in the product's earlier vocabulary, and still in the API's alias paths) is what a person in the field raises: something here needs attention. It is the reporting half of Connected Workers. Its complement is the work order — the planned, scheduled job that answers a request.
A work request carries content (title, description, status, priority, dates, assignee, form values, attachments) and, crucially, where it is: it anchors to a location, and optionally to an asset and a department.
- Anchored by business key — you send your codes (a functional-location code, an asset's primary-key value, a department name), not Treedis ids. Nothing to configure per work request, nothing to look up first.
- Create or update in one endpoint — omit
idto create, include it to update. - Attachments inline — up to 10 files, 20 MB each, as
multipart/form-dataor base64 in JSON.
Base URL & auth
The workspace-level endpoint is the one to integrate against:
https://api.treedis.com/v2/api/workspaces/{workspaceId}/workRequests
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.
Three spellings, one endpoint. Every path below answers on
/workRequests,/work-requestsand/notesalike (…/exportand…/importincluded)./notesis the original name and/work-requestsits first rename; both are kept so integrations do not have to switch in lockstep with a deploy. New work should use/workRequests— the camelCase form is the house convention for URL paths.
Endpoints
| Method | Path | Purpose |
|---|---|---|
POST |
/v2/api/workspaces/{workspaceId}/workRequests |
Create or update a work request |
GET |
/v2/api/workspaces/{workspaceId}/workRequests/export |
Export every work request as portable JSON |
POST |
/v2/api/workspaces/{workspaceId}/workRequests/import |
Import portable JSON into this workspace |
There is also a project/tour-level pair under /v1/api for integrations that anchor to a Treedis tag rather than a CW location — see Tour-level work requests below.
Creating a work request
location is the only required field: the location row's primary-key value — the code your own system uses. Treedis finds that row and files the request against it.
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/workRequests" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-d '{
"location": "R400-20-FL-1001",
"title": "Pump leak",
"description": "There is a leak in the pump, needs immediate attention.",
"status": "open",
"priority": "high"
}'
{
"success": true,
"code": 200,
"message": "Success",
"data": {
"note": { "id": 9001, "title": "Pump leak", "status": "open", "priority": "high" }
}
}
Anchors
| Field | Required | What it is |
|---|---|---|
location |
Yes | The location row's primary-key value (e.g. its functional-location code). |
assetKey |
No | The asset table slug the asset value lives in (e.g. assets). Required when asset is sent. |
asset |
No | The asset row's primary-key value — links the request to that physical asset. |
department |
No | The department's title (its human name) — files the request against that department. |
All three can be combined on one request. A value that matches no row returns 404; asset without assetKey returns 400.
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/workRequests" \
-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",
"department": "Maintenance",
"title": "Pump leak",
"status": "open",
"priority": "high"
}'
See the Locations, Assets and Departments guides for how those rows and their primary keys are defined.
Content fields
| Field | Type | Notes |
|---|---|---|
id |
integer | Omit to create. Include to update — it must be a work request in this workspace, otherwise 404. |
title |
string | Work request title. |
description |
string | Body / details. |
status |
string | e.g. open, in_progress. |
priority |
string | e.g. high. |
assignee |
string | Identifier of the user it is assigned to. |
reporter |
string | Identifier of the user reporting it. |
scheduledDate |
date-time | ISO 8601. |
dueDate |
date-time | ISO 8601. |
customFields |
object | Form field values, keyed by field — captured through the work request's form template. |
Attachments
Up to 10 files, 20 MB each, image / audio / video / PDF only. Two transports, identical result:
multipart/form-data — best for large files:
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/workRequests" \
-H "Authorization: Bearer your-access-token" \
-F 'location=R400-20-FL-1001' \
-F 'title=Pump leak' \
-F 'status=open' \
-F 'files=@photo.jpg'
application/json with base64 — best when your integration already produces JSON. Each file goes under files as { filename, contentType, data }:
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/workRequests" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-d '{
"location": "R400-20-FL-1001",
"title": "Pump leak",
"files": [
{ "filename": "photo.jpg", "contentType": "image/jpeg", "data": "/9j/4AAQSkZJRgABAQ..." }
]
}'
data may be raw base64 or a full data URI (data:image/jpeg;base64,/9j/4AAQ...); with a data URI, contentType is inferred when omitted. Omit files for a work request with no attachments. The whole JSON body must fit the 20 MB request limit, so prefer multipart/form-data for large attachments.
Export & import
Both endpoints move work requests between workspaces as portable JSON. Anchors travel as business keys, not ids — a location by its name, an asset by table key + primary-key value — so the same payload re-resolves in the destination workspace.
curl "https://api.treedis.com/v2/api/workspaces/7/workRequests/export" \
-H "Authorization: Bearer your-access-token"
{
"success": true,
"code": 200,
"message": "Success",
"data": {
"kind": "cw-notes",
"version": 1,
"notes": [
{
"title": "Pump leak",
"status": "open",
"priority": "high",
"assignee": null,
"reporter": null,
"location": "R400-20-FL-1001",
"assetKey": "assets",
"asset": "R400-20-FL-1001-EQ",
"dueDate": "2026-06-25T17:00:00.000Z",
"scheduledDate": null,
"customFieldValues": null
}
]
}
}
Post that same payload back to import it:
curl -X POST "https://api.treedis.com/v2/api/workspaces/9/workRequests/import" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-d @export.json
{ "success": true, "code": 200, "message": "Success", "data": { "imported": 1, "skipped": 0 } }
Runtime state is deliberately dropped on export — ids, tour and tag, 3D position, form template id, messages and timestamps. What travels is the request itself, not where it happened to be pinned. A request whose location or asset cannot be resolved in the destination is skipped, not guessed at, and counted in skipped.
Import the target tables before the work requests: push Locations, Assets and Departments first, or every anchor will fail to resolve.
Tour-level work requests
For integrations anchored to a Treedis tag rather than a CW location, /v1/api carries the original pair:
| Operation | Endpoint |
|---|---|
| Create / update a work request | POST /v1/api/workRequests |
| Add a message to a work request | POST /v1/api/workRequests/messages |
curl -X POST "https://api.treedis.com/v1/api/workRequests" \
-H "Authorization: Bearer your-access-token" \
-F 'title=Pump leak' \
-F 'tagId=456' \
-F 'status=in_progress' \
-F 'files=@photo.jpg'
curl -X POST "https://api.treedis.com/v1/api/workRequests/messages" \
-H "Authorization: Bearer your-access-token" \
-F 'threadId=789' \
-F 'description=Replaced the seal; monitoring.' \
-F 'files=@after.jpg'
Attach to a project (projectId) and/or a tag (tagId) — tourId is not used and should be dropped from your payload; the tour is resolved from the tag when needed. Both endpoints accept multipart/form-data and application/json with base64 files, exactly like the workspace endpoint above.
If you are still calling the unauthenticated POST /v1/public/saveThread or POST /v1/public/saveThreadMessage, move to these: the request body is unchanged — add an Authorization header and change the path.
Errors
| Status | When |
|---|---|
400 |
location missing, or asset sent without assetKey |
401 |
Missing or invalid credentials |
403 |
The caller has no access to the workspace, or an API key addressing another workspace |
404 |
No location (or asset row) matches the given value, or id is not a work request in this workspace |
See the Work Requests tag in the API Reference for the full request and response schemas.

