Work Orders (Tasks)
Work orders (called “tasks” in the API) represent the individual pieces of work within a project. Employees register their time against work orders, so a correct work-order structure is what makes hours land on the right cost codes in your ERP. A project must exist before you can create work orders in it.
Base URL: api/v4/integration/tasks · Scope: ditioapiv3
Examples use the environment variables from Environments and default to the test environment.
Create a work order
Section titled “Create a work order”POST /api/v4/integration/taskscurl -X POST "$DITIO_API_BASE/api/v4/integration/tasks" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "companyId": "YOUR_COMPANY_ID", "projectId": "65f1a2b3c4d5e6f7a8b9c0d1", "externalId": "WO-100", "name": "Grunnarbeid", "active": true, "startDate": "2026-03-15T00:00:00Z", "estimatedHourQty": 500 }'Response: the created work order with its generated id.
Required fields
Section titled “Required fields”| Field | Type | Description |
|---|---|---|
companyId | string | Your Ditio company ID |
projectId | string | The Ditio project ID this work order belongs to |
externalId | string | Your external work order number/ID (unique within the project) |
Optional fields
Section titled “Optional fields”| Field | Type | Description |
|---|---|---|
name | string | Work order name |
active | bool | Whether the work order is active (default: false) |
externalProjectNumber | string | External project number (for reference) |
externalProjectName | string | External project name (for reference) |
externalSubProjectNumber | string | External sub project number. Required, and checked against a list, on some projects — see Sub project number validation. Omitting it keeps the stored value |
externalDim01 | string | Production code / external dimension 1 |
workDescriptionShort | string | Short description of the work |
workDescription | string | Detailed description |
startDate | datetime | Start date |
finishedDate | datetime | Actual completion date |
estimatedHourQty | double | Estimated hours for this work order |
fixedResourcePrice | double | Fixed resource price |
unitId | string | Unit of measurement ID |
costPrice | double | Cost price |
price | double | Sales price |
measureUnitQty | bool | Whether to measure unit quantity |
parentActivityId | string | Parent work order ID (for hierarchical structure) |
chapterId | string | Chapter ID |
taskLocationLatitude | double | GPS latitude |
taskLocationLongitude | double | GPS longitude |
safeJobAnalysisApprovalRequired | bool | Require SJA approval before work starts |
safeJobAnalysisUserPromptText | string | SJA text shown to users |
isParent | bool | Mark as a parent work order (container for sub-orders) |
Sub project number validation
Section titled “Sub project number validation”Some companies have a configured list of valid sub project numbers for a
project. Where that applies, Ditio requires every work order in the project to
carry one of those values, and rejects the write otherwise with
400 Bad Request:
Delprosjektnummer <value> er ikke en gyldig. Velg fra listen(“Sub project number <value> is not valid. Choose from the list.”)
The valid set is the one configured for the project’s externalProjectNumber
— the value on the project record, set through the
Projects API and listed via
Project External References.
The externalProjectNumber you send on the work order itself is a reference
field and does not affect which sub project numbers are accepted.
Template work orders
Section titled “Template work orders”A project can contain one template work order — a work order marked as a template in the Ditio backoffice (planning view). When a new work order is created in that project through this API and a settings field is omitted, the value is copied from the template. Fields the integration provides always take precedence (“payload wins, template fills the gaps”).
Settings inherited from the template include: text-required, SJA approval
requirement and prompt text, unit and unit-quantity measurement, summation
type, prices, double-registration, mass-haul defaults and availability in the
mass-haul app, the work description (workDescription,
workDescriptionShort), the unit-quantity report level, the work-order type
and externalDim02. Your company’s users planned on the template work order
are planned on the new work order too (other companies’ users as well when
the project auto-plans work orders across companies), and your company’s checklists attached to the
template work order are attached to it. Identity and scope fields
(externalId, name, chapterId, dates, parentActivityId, quantities)
always come from your request.
Work orders the PowerOffice Go integration creates for new PowerOffice sub-projects start from the template work order in the same way.
A work order created through the API is never itself marked as a template — the template flag is managed only in the Ditio backoffice.
Projects have a separate, complementary mechanism: a template project is used as the starting point — work orders included — when a new project is created through the Integration API. Copied work orders keep their work description and SJA requirement, but their dates and quantities are reset. See Template projects.
Hierarchical work orders
Section titled “Hierarchical work orders”Work orders can be nested. Set parentActivityId to the ID of the parent
work order and mark the parent with isParent: true.
# Create parent work ordercurl -X POST "$DITIO_API_BASE/api/v4/integration/tasks" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "companyId": "YOUR_COMPANY_ID", "projectId": "65f1a2b3c4d5e6f7a8b9c0d1", "externalId": "WO-200", "name": "Masseflytting", "isParent": true, "active": true }'
# Create child work order under itcurl -X POST "$DITIO_API_BASE/api/v4/integration/tasks" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "companyId": "YOUR_COMPANY_ID", "projectId": "65f1a2b3c4d5e6f7a8b9c0d1", "externalId": "WO-201", "name": "Graving", "parentActivityId": "PARENT_TASK_ID", "active": true }'Get work orders
Section titled “Get work orders”| What | Endpoint |
|---|---|
| All in a project (by Ditio project ID) | GET /api/v4/integration/tasks/project/{projectId} |
| All in a project (by project number) | GET /api/v4/integration/tasks/by-project-number/{projectNumber} |
| All in a project (by external project number) | GET /api/v4/integration/tasks/by-external-project-number/{externalProjectNumber} |
| Single by ID | GET /api/v4/integration/tasks/{id} |
| By project number + task number | GET /api/v4/integration/tasks/by-project-number/{projectNumber}/by-task-number/{taskNumber} |
| All matches for project number + task number | GET /api/v4/integration/tasks/by-project-number/{projectNumber}/by-task-number/{taskNumber}/list |
| By external project number + external ID | GET /api/v4/integration/tasks/by-external-project-number/{externalProjectNumber}/by-external-id/{externalId} |
| All with a production code | GET /api/v4/integration/tasks/by-production-code/{externalDim01} |
curl "$DITIO_API_BASE/api/v4/integration/tasks/by-project-number/P-2026-001/by-task-number/WO-100" \ -H "Authorization: Bearer $TOKEN"- The two “all in a project” lookups by
projectNumberand byexternalProjectNumberreturn a JSON array of work orders, although the interactive reference describes the response as a single object. They look the project up among the projects owned by your token’s company. - A lookup by number that finds no project or work order returns
200with the bodynull, not404. - A project or task number that matches more than one record returns
400 Bad Request. A single-result lookup by task number or external ID that matches several work orders returns the one created through the Integration API, if exactly one was. GET /api/v4/integration/tasks/{id}with an unknown id returns500 Internal Server Error.
Update a work order (full)
Section titled “Update a work order (full)”PUT /api/v4/integration/tasks/{id}Replaces all fields — send the complete work order object. Any field you omit
is reset to its default (e.g. an omitted costPrice becomes 0, an omitted
safeJobAnalysisApprovalRequired becomes false); the template is not
consulted on update. To change only some fields without resetting the rest,
use PATCH.
Update a work order (partial)
Section titled “Update a work order (partial)”PATCH /api/v4/integration/tasks/{id}curl -X PATCH "$DITIO_API_BASE/api/v4/integration/tasks/66a1b2c3d4e5f6a7b8c9d0e2" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Grunnarbeid - fase 2", "estimatedHourQty": 750 }'Delete a work order
Section titled “Delete a work order”DELETE /api/v4/integration/tasks/{id}Related
Section titled “Related”- Projects — the container work orders live in
- Documents — attach method statements and drawings to a work order
- Project Data guide — bulk export of the full work-order catalogue