Skip to content

Data Model

Understanding a handful of core entities makes every Ditio API easier to work with. This page explains what they are and how they reference each other.

Company
└── Project
├── Work order (task) — the unit registrations book against
├── Registrations — time, absence, items, machine usage,
│ mass transport trips, checklists,
│ incidents, feed posts
├── People & machines — the employees and resources on the project
└── Attachments — images, documents, generated PDFs

Most registrations reference a project, a work order (task), the person who made them, and often a machine/resource — a field check-in establishes that context before the data is submitted.

An organization using Ditio, identified by a companyId. Large contractor groups may have several companies in Ditio (parent and subsidiaries), and a project can involve project companies — the company context a subcontractor’s people work under on someone else’s project. Several extraction endpoints accept OwnCompanyDataOnly and ExcludeDataFromSubsidiaries to control which slice of a company structure you get.

The top-level job (e.g. “Prosjekt Fjellhall”), identified by a Ditio id and a human-readable projectNumber that is unique within the company. Everything else — work orders, registrations, documents, plans — belongs to a project. Managed via the Projects API.

A project’s personnel list says who works on it, and each person has a role there. The API returns a stable code in role and the Norwegian label Ditio shows in roleName:

roleroleName
ProjectManagerAnleggsleder
HseHms
ForemanFormann
BasBas
UserBruker

Read them with Get project personnel and roles.

The unit of work inside a project that employees register time against — the API calls it a task. Work orders can be hierarchical (parentActivityId) and carry cost codes for ERP mapping (externalDim01, externalId). Managed via the Work Orders API.

A person. Three identifiers show up in the APIs:

IdentifierWhat it is
Identity idThe person’s login identity, a GUID. The same value is called identityId in the Users API, userId on registrations and project personnel, and identityUserId in User Metadata. The login username is the phone number
companyProfileIdThe person’s profile within one company. User Metadata returns it as id
employeeNumberYour payroll number for the person — unique within the company, and the recommended matching key between systems

A profile has one or more employments (with start/end dates, department, payroll type). The Employees API v5 models employments explicitly; the older Users API v4 flattens them into the user object.

Machines (excavators, dumpers, trucks) and equipment (attachments mounted on a machine, such as a hammer on an excavator) are resources identified by a machineNumber / resourceNumber. Machines have a company-configured type (typeId). Managed via the Machines API; usage records come from Machine Registrations. See the Machine Data guide.

The records produced by field work. Each registration type has its own extraction endpoint on the reporting base unless noted:

RegistrationWhat it isWhere to pull it
Time registrationsHours logged by a person on a project/work orderTime Registrations
Absence registrationsSick leave, vacation, and other time offAbsence Registrations
Item registrationsConsumed materials and items booked to a project/task (from the app’s item cart)Power Query Examples — Power BI export
Machine registrationsCompleted machine usageMachine Registrations
Mass transport tripsHaul cycles (load → dump) with mass type, quantity, distance, and GPSMass Transport Registrations
Checklist submissionsFilled QA and safety checklist instancesSafety Reporting
Incident reportsHSE deviations and safety incidents (RUH)Safety Reporting
Feed postsFree-text updates and tickets posted to the project feedsee Feed and posts below
Payroll linesThe processed result of time and absence data after payroll rules runPayroll Lines

Registrations flow through an approval pipeline: field entry → approval → (for payroll data) locking and export. Extraction endpoints let you filter on approval state where relevant.

Every project has a feed — the chronological stream field workers and office staff see in the app. Time registrations, incidents, and checklists all surface in the feed, and a feed post is a free-text entry (an update, question, or ticket) a user writes directly to it, optionally with photos.

Feed posts are not currently exposed as a standalone extraction endpoint. The photos attached to them are available through Image Extraction with Sources=feed.

Photos and files live throughout Ditio — attached to feed posts, incidents, and checklists, and uploaded as project or work-order documents. They are all backed by the same file-reference model and reachable several ways:

  • Image Extraction — one paginated stream of every image in a project (feed posts, incidents, checklists), each with GPS coordinates, uploader, and project/task context.
  • Checklist and incident attachments — files uploaded inside a submission are on the record’s sections[].attachments[] / sections[].images[].
  • Documents — files attached to projects and work orders through the integration API.
  • Generated PDFs — each submitted checklist, incident, or absence record carries a pdfUrl linking to the PDF Ditio generated; fetch it with your bearer token. See the Safety Reporting guide.
  • IDs are strings. Projects, work orders and machines use MongoDB ObjectIds, e.g. 65f1a2b3c4d5e6f7a8b9c0d1. Person ids (identityId, userId, identityUserId) are identity GUIDs, e.g. 3f2b8c1e-7a4d-4e9b-9c2a-1d5e6f7a8b9c
  • Dates are ISO 8601: 2026-01-15T00:00:00Z
  • JSON bodies use camelCase property names, except on the older reference-data endpoints; see Overview
  • companyId is your Ditio company ID. Projects and machines fall back to your API client’s company when you leave it out on create
  • PATCH merges: an omitted field is left unchanged. Several PUT endpoints (projects, machines, and employees v5 except email) also leave omitted fields unchanged, so check the endpoint’s reference page before relying on PUT to clear a field
  • Deleting a project is refused while the project has registrations (time registrations, load lists or terminal transactions); otherwise it deletes the project with its work orders and plans. A delete on a project another company shared with you only removes the share. A refused delete currently returns 500; see Error Handling. Prefer deactivating (active: false / disable endpoints)

Most extraction responses include IDs that reference other entities. Resolve them with the metadata endpoints:

ID fieldResolve withJoin on
userId (driverId on machine registrations)User Metadata (/v1/user)identityUserId, not id
projectIdProject Metadata (/v1/project)id
resourceId (machineId on machine registrations)Resource Metadata (/v1/resource)id

User Metadata returns one row per company profile, so the same identityUserId can appear more than once when a person has profiles in several companies of your structure.