Export Time Data
This guide shows you how to pull time registration data from Ditio into your own systems. Common use cases include feeding a BI dashboard, syncing with a payroll provider, or archiving records in a data warehouse.
When to use this
Section titled “When to use this”- You want to export hours logged by field workers for payroll processing
- You’re building a BI dashboard that shows labor hours across projects
- You need to sync Ditio time data with an ERP system (SAP, Visma, etc.)
- You want to archive approved time registrations in your own database
Prerequisites
Section titled “Prerequisites”- API credentials with the
reportingapiv1scope — see Authentication - Understanding of Pagination (responses are paginated)
Examples use the environment variables from Environments and default to the test environment.
How it works
Section titled “How it works”Ditio stores time registrations when field workers log their hours via the mobile app. These records go through an approval workflow (field entry → foreman approval → payroll). The Data Extraction API lets you pull these records with a paginated, incremental-sync-friendly contract.
Step-by-step
Section titled “Step-by-step”1. Authenticate
Section titled “1. Authenticate”Get a token with scope=reportingapiv1 into $TOKEN (set DITIO_SCOPE=reportingapiv1), as shown in
Getting a token in your scripts.
2. Fetch time registrations
Section titled “2. Fetch time registrations”Query for a date range:
curl -H "Authorization: Bearer $TOKEN" \ "$DITIO_REPORTING_BASE/v1/time-registrations?FromDateTime=2026-01-01&ToDateTime=2026-01-31"3. Page through all results
Section titled “3. Page through all results”Follow continuationToken until all records are retrieved. See
Pagination.
4. Process the data
Section titled “4. Process the data”Each record includes the worker, project, work order, date and hours, and approval state — plus the IDs you can resolve against the user, project and resource metadata endpoints. All of them are in the Data Extraction reference.
Complete example (Python)
Section titled “Complete example (Python)”import os# 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')}"}
records = list(fetch_all( f"{REPORTING_BASE}/v1/time-registrations", headers, {"FromDateTime": "2026-01-01", "ToDateTime": "2026-01-31"},))
print(f"Exported {len(records)} time registrations")C# example
Section titled “C# example”using System.Net.Http.Headers;using System.Text.Json;
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-expiryhttp.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await DitioAuth.GetTokenAsync(http, "reportingapiv1"));
var allRecords = new List<JsonElement>();// DitioPaging.FetchAllAsync: see /getting-started/pagination/#fetching-all-pages-in-codeawait foreach (var record in DitioPaging.FetchAllAsync<JsonElement>(http, $"{reportingBase}/v1/time-registrations?FromDateTime=2026-01-01&ToDateTime=2026-01-31")){ allRecords.Add(record);}Incremental syncs
Section titled “Incremental syncs”For recurring exports, pass ModifiedSince = <last successful sync timestamp> instead of a work-date window. Incremental mode returns records
created and edited since that instant, so late corrections are picked up
without re-processing the entire history. See
Full vs incremental sync.
Common issues
Section titled “Common issues”| Issue | Cause | Fix |
|---|---|---|
400 / invalid_scope at the token endpoint | Your client isn’t granted reportingapiv1 at all | Contact [email protected] — it isn’t listed in the admin UI, so an administrator can’t add it themselves |
401 Unauthorized on a token that works elsewhere, and a refresh doesn’t fix it | Token was issued for another scope (typically ditioapiv3) — this API needs reportingapiv1 | Re-request the token with scope=reportingapiv1; see 401 — wrong scope |
403 Forbidden on metadata or payroll extraction | The user your API client acts as is not an administrator | Have the client’s user given administrator access in Ditio Web |
| Edits missing from exports | Full sync only sees the date window | Use ModifiedSince incremental sync for recurring pulls |
| Slow unbounded pulls | No window on a large tenant | Chunk backfills month-by-month; keep ModifiedSince tight |
Related endpoints
Section titled “Related endpoints”- Payroll Export — processed payroll data (post-approval)
- Data Extraction reference — every extraction endpoint, including absence registrations and the user and project metadata for matching IDs