Machine Integration
This guide covers how to send machine state data (excavator idle/working/moving states) from an external system into Ditio. This is the primary integration point for telematics providers and fleet management systems.
When to Use This
Section titled “When to Use This”- You have a fleet management system that tracks excavator operating states
- You want machine utilization data to appear in Ditio’s production analytics
- You need to sync historical machine data (daily batch uploads)
- You’re a telematics provider integrating with Ditio on behalf of a customer
Prerequisites
Section titled “Prerequisites”- API credentials with the
masstransportapiv1scope — see Authentication - A company ID and project ID in Ditio, plus the Mass Transport API base URL
(
DITIO_MASSTRANSPORT_BASEin the examples below) — both provided by your Ditio contact during onboarding
How It Works
Section titled “How It Works”Ditio tracks excavator states to calculate machine utilization and production rates. External systems can push state data via the Machine Integration API. Each state record represents a time period where a machine was in a specific operating state (idle, working, moving, etc.).
The typical flow:
- Your system collects machine state data from telematics hardware
- You push state records to Ditio (individually or in bulk)
- Ditio processes the data and makes it available in reports and dashboards
- Your customer sees combined Ditio + external machine data in one place
Step-by-Step
Section titled “Step-by-Step”1. Push a Single Machine State
Section titled “1. Push a Single Machine State”curl -X POST $DITIO_MASSTRANSPORT_BASE/api/external-excavator-state \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "companyId": "company-123", "projectId": "project-456", "machineId": "EX-001", "state": "Working", "startTime": "2025-01-15T08:00:00Z", "endTime": "2025-01-15T08:45:00Z" }'2. Bulk Import (Recommended for Production)
Section titled “2. Bulk Import (Recommended for Production)”For production integrations, use the bulk import endpoint to send multiple records at once:
curl -X POST $DITIO_MASSTRANSPORT_BASE/api/external-excavator-state/import \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '[ { "companyId": "company-123", "projectId": "project-456", "machineId": "EX-001", "state": "Working", "startTime": "2025-01-15T08:00:00Z", "endTime": "2025-01-15T08:45:00Z" }, { "companyId": "company-123", "projectId": "project-456", "machineId": "EX-001", "state": "Idle", "startTime": "2025-01-15T08:45:00Z", "endTime": "2025-01-15T09:00:00Z" } ]'3. Sync Checkpoint
Section titled “3. Sync Checkpoint”Before sending data, check what you’ve already sent by getting the latest timestamp:
curl -H "Authorization: Bearer $TOKEN" \ "$DITIO_MASSTRANSPORT_BASE/api/external-excavator-state/latest-timestamp/company-123/project-456"This returns the timestamp of the most recent record Ditio has received. Only send data newer than this to avoid duplicates.
4. Query Aggregated Data
Section titled “4. Query Aggregated Data”Check machine utilization analytics:
curl -X POST $DITIO_MASSTRANSPORT_BASE/api/external-excavator-state/aggregated-data-per-state \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "companyId": "company-123", "projectId": "project-456", "fromDate": "2025-01-01", "toDate": "2025-01-31" }'Complete Example (Python)
Section titled “Complete Example (Python)”import requestsfrom datetime import datetime, timezone
import os
TOKEN = "your-access-token"BASE_URL = os.environ["DITIO_MASSTRANSPORT_BASE"] + "/api/external-excavator-state"HEADERS = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json",}
COMPANY_ID = "company-123"PROJECT_ID = "project-456"
# Step 1: Check sync checkpointlatest = requests.get( f"{BASE_URL}/latest-timestamp/{COMPANY_ID}/{PROJECT_ID}", headers=HEADERS,)last_sync = latest.json().get("latestTimestamp")print(f"Last synced: {last_sync}")
# Step 2: Collect new records from your systemnew_records = [ { "companyId": COMPANY_ID, "projectId": PROJECT_ID, "machineId": "CAT-336F", "state": "Working", "startTime": "2025-01-15T07:00:00Z", "endTime": "2025-01-15T09:30:00Z", }, { "companyId": COMPANY_ID, "projectId": PROJECT_ID, "machineId": "CAT-336F", "state": "Idle", "startTime": "2025-01-15T09:30:00Z", "endTime": "2025-01-15T10:00:00Z", },]
# Step 3: Bulk importresp = requests.post(f"{BASE_URL}/import", headers=HEADERS, json=new_records)if resp.status_code == 201: print(f"Imported {len(new_records)} state records")else: print(f"Error: {resp.status_code} - {resp.text}")Common Issues
Section titled “Common Issues”| Error | Cause | Fix |
|---|---|---|
400 ArgumentIsNull | Empty array sent to import | Include at least one record |
401 Unauthorized | Token expired, or issued for another scope — this API needs masstransportapiv1 | Refresh the token; if the refresh still returns 401, re-request it with scope=masstransportapiv1 |
400 Bad Request on a company or project you expect to exist | These endpoints don’t gate access with a 403 — an unknown or unreachable company/project surfaces as a validation error | Check the company and project IDs your Ditio contact issued for this client |
Related
Section titled “Related”- Weight Measures — Push weight/scale data to Ditio
- Equipment Data — Export equipment metadata