Skip to content

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).

  • API credentials (client_id and client_secret) — see Authentication
  • A tool for making HTTP requests (curl, Postman, or your language of choice)
Terminal window
# 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"
Terminal window
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.

Terminal window
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”
Terminal window
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.

Once time has been registered (in test there’s usually existing synced data), export it through the Data Extraction API:

Terminal window
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.

import os
import 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: authenticate
token = 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 project
project = 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 it
requests.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 pagination
all_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")
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: authenticate
var 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 project
var 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);