Skip to content

Machine Data

Machines are money on a construction site — knowing where each excavator is registered, how many hours it ran, and on whose project, is what makes fleet cost tracking work. This guide covers the two halves of machine data in Ditio: maintaining the machine catalogue (write) and extracting usage records (read).

  • Your fleet management system is the master record and Ditio should mirror it
  • You bill customers for machine hours and need completed usage records — including when your machines work on other companies’ projects
  • You’re building utilization dashboards per machine, project, or department

Examples use the environment variables from Environments and default to the test environment.

Use the Machines API on $DITIO_API_BASE to create and maintain machines. The short version:

  1. Fetch valid machine types — GET /api/MachineType returns your company’s configured types; the typeId you send on create must match one type’s TypeId
  2. Create machines with your fleet numbers as machineNumber
  3. Keep them fresh — PATCH hour meters and service dates on a schedule
  4. Deactivate, don’t delete — retired machines get active: false

The create request, full field reference, bulk endpoints, and how machines differ from equipment (attachments mounted on a machine) are in the Machines API reference.

The Machine Registrations endpoint streams completed usage records for the machines your company owns — including registrations made on other companies’ projects (e.g. when your machine is rented out).

Terminal window
# Everything created or edited since your last sync
curl -s -G "$DITIO_REPORTING_BASE/v1/machine-registrations" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode "ModifiedSince=2026-07-01T00:00:00Z"

Key behaviors:

  • Incremental sync (ModifiedSince) catches new and edited registrations — including edits to old records that a date-window query would miss. Deleted records arrive as tombstones with isDeleted: true.
  • Cross-company privacy: when your machine ran on another company’s project, that company’s personal identifiers (driverName, driverId) are returned as null — you still get the machine, project, times, quantity, and the operator’s company name.

Python example — utilization per machine

Section titled “Python example — utilization per machine”
import os
from collections import defaultdict
# Paste get_token (/getting-started/authentication/#getting-a-token-in-your-scripts) and fetch_all (/getting-started/pagination/#fetching-all-pages-in-code) above this.
REPORTING_BASE = os.environ.get(
"DITIO_REPORTING_BASE", "https://core-api.ditio.dev/reporting"
)
headers = {"Authorization": f"Bearer {get_token('reportingapiv1')}"}
params = {
"FromDateTime": "2026-06-01T00:00:00Z",
"ToDateTime": "2026-07-01T00:00:00Z",
}
hours_by_machine = defaultdict(float)
for registration in fetch_all(f"{REPORTING_BASE}/v1/machine-registrations", headers, params):
hours_by_machine[registration["machineName"]] += registration["qty"]
for machine_name, hours in sorted(hours_by_machine.items(), key=lambda x: -x[1]):
print(f"{machine_name}: {hours:.1f}")
using System.Net.Http.Headers;
var reportingBase = Environment.GetEnvironmentVariable("DITIO_REPORTING_BASE")
?? "https://core-api.ditio.dev/reporting";
using var http = new HttpClient();
// DitioAuth.GetTokenAsync: see /getting-started/authentication/#token-expiry
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", await DitioAuth.GetTokenAsync(http, "reportingapiv1"));
var url = $"{reportingBase}/v1/machine-registrations" +
"?FromDateTime=2026-06-01T00:00:00Z&ToDateTime=2026-07-01T00:00:00Z";
var hoursByMachine = new Dictionary<string, double>();
// DitioPaging.FetchAllAsync: see /getting-started/pagination/#fetching-all-pages-in-code
await foreach (var registration in DitioPaging.FetchAllAsync<MachineRegistration>(http, url))
{
var machineName = registration.MachineName ?? registration.MachineId ?? "(unknown)";
hoursByMachine[machineName] = hoursByMachine.GetValueOrDefault(machineName) + registration.Qty;
}
foreach (var (machineName, hours) in hoursByMachine.OrderByDescending(entry => entry.Value))
Console.WriteLine($"{machineName}: {hours:F1}");
// Only the fields this example reads; driverName and driverId can be null.
record MachineRegistration(string? MachineId, string? MachineName, double Qty);

To resolve machine IDs appearing in other exports (time registrations, payroll lines) into names and numbers, use the resource metadata endpoint (GET /v1/resource on the reporting base), which lists the machine catalogue — see the Data Extraction reference.

IssueCauseFix
MachineService.machineTypeInvalid on createtypeId doesn’t match a configured typeFetch GET /api/MachineType first and map your categories to valid TypeId values
Machine type ids come back as TypeId, not typeIdGET /api/MachineType answers in PascalCaseRead TypeId, or send the header case: camel-case
driverName / driverId are null in extractionThe registration involves another company’s employeeExpected — cross-company personal data is redacted by design
Edits missing from date-window pullsFull sync only sees the stop-time windowUse incremental sync (ModifiedSince) for ongoing updates