Connected Workers Work Orders

A work order is planned work: a job with a status, a schedule, a place, and someone who owns it. It is the doing half of Connected Workers — the complement of the work request, which is how a problem gets reported in the first place.

  • Anchored by business key — like every other public CW endpoint, you send your codes (a functional-location code, an asset's primary-key value, a department name), never Treedis row ids.
  • Two kinds of rownative work orders are planned through this API or in the app. Mirror rows are synced read-only from an external CMMS (HxGN EAM, SAP, IBM Maximo). A mirror row cannot be edited here.
  • Promote a request into a job — one call turns a work request into a work order, carrying its context over.

Base URL & auth

https://api.treedis.com/v2/api/workspaces/{workspaceId}/workOrders

/work-orders works too. Both spellings mount the same router, matching the work request aliases. The examples below use workOrders.

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.

Reads need workspace membership. Every write additionally needs the ManageProjectAccess workspace permission — the same gate the in-app planning board uses.

Authentication How to obtain and send an OAuth2 access token.

Endpoints

Method Path (under /v2/api/workspaces/{workspaceId}/workOrders) Purpose
GET `` (collection) List work orders + the status vocabulary
POST `` (collection) Plan a work order
GET /{workOrderId} Full detail (checklists, time, messages)
PATCH /{workOrderId} Update a native work order
DELETE /{workOrderId} Delete a native work order
PATCH /schedule Batch schedule — place many at once
POST /from-work-request/{workRequestId} Promote a work request
GET /export Export every work order as portable JSON
POST /import Import portable JSON into this workspace

This is the integration surface: plan, read, schedule, promote, and move work between workspaces. The per-job interaction surface — ticking checklist items, logging time, posting messages, the worker's own "my work" view — stays inside the app, where it belongs to a signed-in person doing the job.

Listing work orders

curl "https://api.treedis.com/v2/api/workspaces/7/workOrders" \
  -H "Authorization: Bearer your-access-token"
{
  "success": true,
  "code": 200,
  "message": "Success",
  "data": {
    "workOrders": [
      {
        "id": 4101,
        "number": 118,
        "provider": "native",
        "externalId": null,
        "title": "Replace pump seal",
        "status": null,
        "statusId": "inProgress",
        "priority": "high",
        "assignee": null,
        "assigneeUserId": 512,
        "teamId": 8,
        "departmentId": 33,
        "cwLocationId": 9001,
        "cwAssetId": 4402,
        "scheduledDate": "2026-06-24T00:00:00.000Z",
        "startDate": "2026-06-24T08:00:00.000Z",
        "dueDate": "2026-06-25T17:00:00.000Z",
        "estimatedDurationMinutes": 180,
        "tagId": 7781,
        "tourSlug": "north-plant"
      }
    ],
    "statuses": [
      { "id": "open", "label": "Open", "color": "#667085", "order": 0, "schedulingBehavior": "pending", "isDefault": true },
      { "id": "inProgress", "label": "In progress", "color": "#2055FF", "order": 1, "schedulingBehavior": "active" },
      { "id": "onHold", "label": "On hold", "color": "#F79009", "order": 2, "schedulingBehavior": "pending" },
      { "id": "complete", "label": "Complete", "color": "#12B76A", "order": 3, "schedulingBehavior": "completed" }
    ]
  }
}

statuses is the workspace's own status vocabulary — read statusId against it. A workspace can rename, recolour and reorder these, so resolve labels from this list rather than hardcoding them. schedulingBehavior (pending · active · completed) is the stable part: it is what "open work" and "done" mean, whatever a workspace calls its statuses.

tagId and tourSlug are resolved for you from the linked asset — they are what a client needs to jump to the job in the 3D tour.

Planning a work order

title is the only required field. Anchors are optional and, like everywhere else in the public API, are your keys:

Field What it is
location The location row's primary-key value (e.g. its functional-location code).
assetKey The asset table slug the asset value lives in (e.g. assets). Required when asset is sent.
asset The asset row's primary-key value — the thing being worked on.
department The department's title (its human name).
curl -X POST "https://api.treedis.com/v2/api/workspaces/7/workOrders" \
  -H "Authorization: Bearer your-access-token" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Replace pump seal",
    "description": "Seal is weeping; replace and monitor for 24h.",
    "priority": "high",
    "statusId": "inProgress",
    "location": "R400-20-FL-1001",
    "assetKey": "assets",
    "asset": "R400-20-FL-1001-EQ",
    "department": "Maintenance",
    "startDate": "2026-06-24T08:00:00Z",
    "dueDate": "2026-06-25T17:00:00Z",
    "estimatedDurationMinutes": 180
  }'

Returns 201 with { "workOrder": { … } }.

Content fields

Field Type Notes
title string Required.
description string Job details.
priority string e.g. high.
statusId string A status id from the workspace vocabulary. Unknown or omitted → the workspace default.
startDate / dueDate date-time ISO 8601. dueDate earlier than startDate is rejected with 400.
scheduledDate date-time Board placement — the day the job is due to run.
estimatedDurationMinutes number Planned duration.
assignee string Free-text assignee label (an external system's name for the owner).
assigneeUserId number A Treedis user id, when you have one. Sets the person who owns the job.
teamId number The team row the job sits on.
reporter string Who raised it.
closeoutNotes string What was actually done.
customFieldValues object Form answers, keyed by the work order form template's field ids.
parentWorkOrderId number Makes this row a sub-work-order — one department's step of a cross-department job.

Two invariants worth knowing before you plan in bulk:

  • Department follows the team. Send teamId without departmentId and the department is derived from it (a team belongs to exactly one department). With no team but an assigneeUserId, the person's department is used instead.
  • The sub-work-order tree is one level deep. A work order that already has children cannot itself become a child, and a child cannot be a parent.

Updating and deleting

PATCH sends only the fields you want to change. An anchor you do not mention is left alone; send it as null to clear it.

curl -X PATCH "https://api.treedis.com/v2/api/workspaces/7/workOrders/4101" \
  -H "Authorization: Bearer your-access-token" \
  -H "Content-Type: application/json" \
  -d '{ "statusId": "complete", "closeoutNotes": "Seal replaced, no further weeping." }'

Mirror rows are read-only. A work order synced from an external CMMS carries provider other than native, and PATCH / DELETE on it return 400"This work order is mirrored from an external system and cannot be edited". Change it in the source system and let the sync carry it over. See the HxGN EAM, SAP and IBM Maximo sync pages.

Batch scheduling

One call places many work orders on the board — the bulk operation a planner or a scheduling integration actually needs.

curl -X PATCH "https://api.treedis.com/v2/api/workspaces/7/workOrders/schedule" \
  -H "Authorization: Bearer your-access-token" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "workOrderId": 4101, "scheduledDate": "2026-06-24", "teamId": 8, "estimatedDurationMinutes": 180 },
      { "workOrderId": 4102, "scheduledDate": "2026-06-25", "assignee": "Dana Levi" }
    ]
  }'

Each item takes workOrderId plus any of scheduledDate, teamId, assignee and estimatedDurationMinutes. Returns the updated rows as { "workOrders": [ … ] }. A work order in a status whose schedulingBehavior is completed is not re-scheduled — finished work does not go back on the board.

Promoting a work request

The reporting-to-doing handoff, in one call. Pass the work request id; the work order inherits its title, description, priority, due date, location, asset and reporter.

curl -X POST "https://api.treedis.com/v2/api/workspaces/7/workOrders/from-work-request/9001" \
  -H "Authorization: Bearer your-access-token"

Idempotent. One work order per work request is enforced by a unique index on the source id, so a repeated call returns the work order that already exists rather than creating a duplicate — safe to retry.

Export & import

Both endpoints move work orders 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.

curl "https://api.treedis.com/v2/api/workspaces/7/workOrders/export" \
  -H "Authorization: Bearer your-access-token"
{
  "success": true,
  "code": 200,
  "message": "Success",
  "data": {
    "kind": "cw-work-orders",
    "version": 1,
    "workOrders": [
      {
        "provider": "native",
        "externalId": "WO-118",
        "title": "Replace pump seal",
        "status": "inProgress",
        "priority": "high",
        "assignee": null,
        "reporter": null,
        "department": "Maintenance",
        "scheduledDate": "2026-06-24T00:00:00.000Z",
        "dueDate": "2026-06-25T17:00:00.000Z",
        "location": "R400-20-FL-1001",
        "assetKey": "assets",
        "asset": "R400-20-FL-1001-EQ",
        "customFieldValues": null
      }
    ]
  }
}

Post the same payload back to import it; the response is { "imported": n, "skipped": n }. Ids, workspace and timestamps are dropped on export — what travels is the work, not the row. A work order whose location or asset cannot be resolved in the destination is skipped, not guessed at.

Import the target tables before the work orders: push Locations, Assets and Departments first, or every anchor will fail to resolve.

How work orders get into Treedis

There are three ways, and they coexist in one board:

  1. This API — plan them directly, or import them.
  2. Promoted from a work request — someone in the field reported it, a planner turned it into a job.
  3. Synced from an external CMMS — HxGN EAM, SAP or IBM Maximo. Those rows are mirrors: read-only here, owned by the source system.

Errors

Status When
400 title missing, dueDate before startDate, an invalid sub-work-order parent, a mirror row edited, an unresolvable anchor, or asset without assetKey
401 Missing or invalid credentials
403 No workspace access, an API key addressing another workspace, or a write without ManageProjectAccess
404 The work order (or work request) is not in this workspace, or no location / asset row matches the given value

See the Connected Workers Work Orders tag in the API Reference for the full request and response schemas.