Quickstart
This guide takes you from credentials to working API calls: first a token, then creating a project and a work order (the write surface), then pulling time registrations (the read surface).
Prerequisites
Section titled “Prerequisites”- API credentials (
client_idandclient_secret) — see Authentication - A tool for making HTTP requests (
curl, Postman, or your language of choice)
# Test (default for all examples)export DITIO_IDENTITY_BASE="https://identity.ditio.dev"export DITIO_API_BASE="https://core-api.ditio.dev/core"export DITIO_REPORTING_BASE="https://core-api.ditio.dev/reporting"Step 1: Get an access token
Section titled “Step 1: Get an access token”TOKEN=$(curl -s -X POST "$DITIO_IDENTITY_BASE/connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET" \ -d "scope=ditioapiv3 reportingapiv1" | jq -r '.access_token')This requests both scopes used below: ditioapiv3 for the Integration API
and reportingapiv1 for the Data Extraction API.
Step 2: Create a project
Section titled “Step 2: Create a project”curl -X POST "$DITIO_API_BASE/api/v4/integration/projects" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "companyId": "YOUR_COMPANY_ID", "projectNumber": "P-1001", "name": "Prosjekt Fjellhall", "active": true }'The response contains the project’s generated id — you need it in the next
step.
Step 3: Create a work order in that project
Section titled “Step 3: Create a work order in that project”curl -X POST "$DITIO_API_BASE/api/v4/integration/tasks" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "companyId": "YOUR_COMPANY_ID", "projectId": "PROJECT_ID_FROM_STEP_2", "externalId": "WO-001", "name": "Graving byggegrop", "active": true }'That’s the minimum working setup: a project with a work order that employees can register time against.
Step 4: Pull time registrations
Section titled “Step 4: Pull time registrations”Once time has been registered (in test there’s usually existing synced data), export it through the Data Extraction API:
curl -H "Authorization: Bearer $TOKEN" \ "$DITIO_REPORTING_BASE/v1/time-registrations?FromDateTime=2026-01-01&ToDateTime=2026-01-31"The response contains a data array and — when there is more data — a
continuationToken:
{ "data": [], "links": { "next": "..." }, "continuationToken": "eyJ..."}Pass the token back as ContinuationToken to get the next page, and repeat
until it’s empty. See Pagination.
Python example
Section titled “Python example”import osimport requests
IDENTITY_BASE = os.environ.get("DITIO_IDENTITY_BASE", "https://identity.ditio.dev")API_BASE = os.environ.get("DITIO_API_BASE", "https://core-api.ditio.dev/core")REPORTING_BASE = os.environ.get("DITIO_REPORTING_BASE", "https://core-api.ditio.dev/reporting")
# Step 1: authenticatetoken = requests.post( f"{IDENTITY_BASE}/connect/token", data={ "grant_type": "client_credentials", "client_id": "YOUR_CLIENT_ID", "client_secret": "YOUR_CLIENT_SECRET", "scope": "ditioapiv3 reportingapiv1", },).json()["access_token"]headers = {"Authorization": f"Bearer {token}"}
# Step 2: create a projectproject = requests.post( f"{API_BASE}/api/v4/integration/projects", headers=headers, json={ "companyId": "YOUR_COMPANY_ID", "projectNumber": "P-1001", "name": "Prosjekt Fjellhall", "active": True, },).json()
# Step 3: create a work order in itrequests.post( f"{API_BASE}/api/v4/integration/tasks", headers=headers, json={ "companyId": "YOUR_COMPANY_ID", "projectId": project["id"], "externalId": "WO-001", "name": "Graving byggegrop", "active": True, },).raise_for_status()
# Step 4: pull time registrations, following paginationall_records = []params = {"FromDateTime": "2026-01-01", "ToDateTime": "2026-01-31"}while True: page = requests.get( f"{REPORTING_BASE}/v1/time-registrations", headers=headers, params=params, ).json() all_records.extend(page["data"]) continuation = page.get("continuationToken") if not continuation: break params["ContinuationToken"] = continuation
print(f"Fetched {len(all_records)} time registrations")C# example
Section titled “C# example”using System.Net.Http.Headers;using System.Net.Http.Json;
var identityBase = Environment.GetEnvironmentVariable("DITIO_IDENTITY_BASE") ?? "https://identity.ditio.dev";var apiBase = Environment.GetEnvironmentVariable("DITIO_API_BASE") ?? "https://core-api.ditio.dev/core";
using var http = new HttpClient();
// Step 1: authenticatevar tokenResponse = await http.PostAsync( $"{identityBase}/connect/token", new FormUrlEncodedContent(new Dictionary<string, string> { ["grant_type"] = "client_credentials", ["client_id"] = "YOUR_CLIENT_ID", ["client_secret"] = "YOUR_CLIENT_SECRET", ["scope"] = "ditioapiv3 reportingapiv1", }));var token = (await tokenResponse.Content.ReadFromJsonAsync<TokenResponse>())!.access_token;http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
// Step 2: create a projectvar projectResponse = await http.PostAsJsonAsync( $"{apiBase}/api/v4/integration/projects", new { companyId = "YOUR_COMPANY_ID", projectNumber = "P-1001", name = "Prosjekt Fjellhall", active = true, });projectResponse.EnsureSuccessStatusCode();
record TokenResponse(string access_token, int expires_in, string token_type);Next steps
Section titled “Next steps”- Pagination — cursor-based paging and incremental sync
- Export Time Data — a complete export integration
- Projects & Work Orders — the full field reference