Reports
Reports provide aggregated views of time tracking data for analysis, payroll processing, and management oversight. Multiple report types are available, each offering different perspectives on your organization's data.
All report list endpoints (except the Absence Report) are paginated and return an envelope with count, next, previous, and results. Use the limit and offset query parameters to page through results (default limit 100, maximum 1000).
Monthly Report
Get a monthly summary of working hours per employee, including target hours, actual hours, and balance information. All durations are in seconds.
Query Parameters
- Name
year- Type
- integer
- Description
The year to report on. Defaults to the current year.
- Name
month- Type
- integer
- Description
The month to report on (1-12). Defaults to the current month.
- Name
ids- Type
- string
- Description
Filter by employee IDs, pipe-separated.
- Name
employees- Type
- string
- Description
Filter by employee IDs, pipe-separated.
- Name
employee_groups- Type
- string
- Description
Filter by employee group IDs, pipe-separated. Use the special value
nullto match employees without a group.
- Name
emails- Type
- string
- Description
Filter by employee email addresses, pipe-separated.
- Name
external_ids- Type
- string
- Description
Filter by external IDs, pipe-separated.
- Name
q- Type
- string
- Description
Search by employee name or RFID token.
- Name
incomplete_days- Type
- boolean
- Description
Set to
trueto only include employees with incomplete days in the selected month, orfalseto only include employees without incomplete days.
Archived employees are excluded automatically unless they were archived after the report month started and still have working times or an absence recorded in that month.
Response Fields
- Name
id- Type
- string (UUID)
- Description
Unique identifier for the employee.
- Name
archived_at- Type
- string (ISO 8601) or null
- Description
Timestamp when the employee was archived, or
nullif active.
- Name
created_at- Type
- string (ISO 8601)
- Description
Timestamp when the employee was created.
- Name
modified_at- Type
- string (ISO 8601)
- Description
Timestamp when the employee was last modified.
- Name
external_id- Type
- string or null
- Description
External identifier of the employee, e.g. from your HR system.
- Name
accounting_number- Type
- string or null
- Description
Accounting number of the employee.
- Name
is_male- Type
- boolean or null
- Description
Gender flag of the employee.
- Name
first_name- Type
- string
- Description
First name of the employee.
- Name
last_name- Type
- string
- Description
Last name of the employee.
- Name
email- Type
- string or null
- Description
Email address of the employee.
- Name
workmonth- Type
- object
- Description
The summary for the selected month:
id,year,month,workday_count,incomplete_days_count,worktime_count(seconds),target_worktime(seconds), andworktime_balance.
- Name
workmonth.worktime_balance- Type
- object
- Description
The working time balance:
worktime_countandtarget_worktimefor the selected month (seconds), andtotal, the overall balance in seconds including the carry-over from previous months.
- Name
settings- Type
- object
- Description
Relevant employee settings:
working_session.abscent_days,working_session.use_working_hour_balance,working_session.decimal_format,employee_app_access.edit_working_times, andemployee_app_access.edit_working_times_requires_comment.
Request
curl -X GET "https://api.zeitstrom.com/api/v2/reports/monthly/?year=2024&month=6" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Response
{
"count": 25,
"next": null,
"previous": null,
"results": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"archived_at": null,
"created_at": "2023-01-10T09:00:00",
"modified_at": "2024-05-02T11:30:00",
"external_id": "EMP-0042",
"accounting_number": "4711",
"is_male": true,
"first_name": "Max",
"last_name": "Mustermann",
"email": "max@example.com",
"workmonth": {
"id": "a7b8c9d0-e1f2-3456-abcd-789012345678",
"year": 2024,
"month": 6,
"workday_count": 20,
"incomplete_days_count": 0,
"worktime_count": 561600,
"target_worktime": 576000,
"worktime_balance": {
"worktime_count": 561600,
"target_worktime": 576000,
"total": -14400
}
},
"settings": {
"working_session": {
"abscent_days": "add_to_debit_hours",
"use_working_hour_balance": "active",
"decimal_format": "hours_and_minutes"
},
"employee_app_access": {
"edit_working_times": "edit_missing_days",
"edit_working_times_requires_comment": "disabled"
}
}
}
]
}
Additional Actions
GET /api/v2/reports/monthly/meta/ returns metadata for the selected period: the resolved year and month, the available_years for your account, and prefilled print_url and csv_url export links.
POST /api/v2/reports/monthly/print/ enqueues an asynchronous task that generates printable monthly reports. The year and month query parameters are required. The response contains the ID of the created task.
Get Report Metadata
curl -X GET "https://api.zeitstrom.com/api/v2/reports/monthly/meta/?year=2024&month=6" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Generate Print Report
curl -X POST "https://api.zeitstrom.com/api/v2/reports/monthly/print/?year=2024&month=6" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Print Report Response
{
"id": "b8c9d0e1-f2a3-4567-bcde-890123456789"
}
Employee Report
List the employees that are accessible for reporting. Each result contains only the employee's id — use it with the Employee Workdays endpoint to fetch the actual workday-level data.
Query Parameters
- Name
ids- Type
- string
- Description
Filter by employee IDs, pipe-separated.
- Name
employee_groups- Type
- string
- Description
Filter by employee group IDs, pipe-separated. Use the special value
nullto match employees without a group.
- Name
q- Type
- string
- Description
Search by employee name.
Request
curl -X GET "https://api.zeitstrom.com/api/v2/reports/employees/" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Response
{
"count": 25,
"next": null,
"previous": null,
"results": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
]
}
Employee Workdays
Get detailed workday-level data for a single employee, including timespans, breaks, and notes. Workdays are ordered by check-in time, most recent first. All durations are in seconds.
Query Parameters
- Name
daterange- Type
- string
- Description
Date range of workday check-ins:
YYYY-MM-DD|YYYY-MM-DD. Either side may be omitted (e.g.2024-06-01|or|2024-06-30). Defaults to the last 30 days. Note that a date-only upper bound is interpreted as midnight at the start of that day.
Response Fields
- Name
id- Type
- string (UUID)
- Description
Unique identifier for the workday.
- Name
break_duration- Type
- integer
- Description
Total break time in seconds.
- Name
checkin- Type
- string (ISO 8601)
- Description
Earliest check-in time of the day.
- Name
checkout- Type
- string (ISO 8601) or null
- Description
Latest check-out time of the day, or
nullif still open.
- Name
note- Type
- string or null
- Description
Administrative note for the workday.
- Name
short_break_policy- Type
- string
- Description
The break policy applied to this workday.
- Name
timespans- Type
- array
- Description
The timespans of the workday. Each timespan contains
id,checkinandcheckout(timestamp objects withid,local_id,time, andcreator— one ofadmin,online,device, orsystem),employee_comment,project_id, andtag_assignments(objects withtag_id,type—relativeorabsolute— andvalue).
Request
curl -X GET "https://api.zeitstrom.com/api/v2/reports/employees/a1b2c3d4-e5f6-7890-abcd-ef1234567890/?daterange=2024-06-01|2024-06-30" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Response
{
"count": 20,
"next": null,
"previous": null,
"results": [
{
"id": "f6a7b8c9-d0e1-2345-fabc-678901234567",
"break_duration": 2700,
"checkin": "2024-06-28T08:00:00",
"checkout": "2024-06-28T17:00:00",
"note": null,
"short_break_policy": "auto",
"timespans": [
{
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"checkin": {
"id": "d4e5f6a7-b8c9-0123-def1-234567890123",
"local_id": null,
"time": "2024-06-28T08:00:00",
"creator": "device"
},
"checkout": {
"id": "e5f6a7b8-c9d0-1234-ef12-345678901234",
"local_id": null,
"time": "2024-06-28T17:00:00",
"creator": "device"
},
"employee_comment": null,
"project_id": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
"tag_assignments": [
{
"tag_id": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
"type": "relative",
"value": "100.00000"
}
]
}
]
}
]
}
Employee Activity
Get the current activity status for all non-archived employees. Useful for building real-time dashboards. The state of an employee is one of working, absence, no-working-day, or null (checked out).
Query Parameters
- Name
states- Type
- string
- Description
Filter by state, pipe-separated:
working,absence,no-working-day, ornull.
- Name
employee_groups- Type
- string
- Description
Filter by employee group IDs, pipe-separated. Use the special value
nullto match employees without a group.
- Name
projects- Type
- string
- Description
Only include employees whose current timespan is assigned to one of the given project IDs, pipe-separated. Use the special value
nullto match timespans without a project.
- Name
q- Type
- string
- Description
Search by employee name.
- Name
verbosity- Type
- string
- Description
Use
detailto include the current timespan, employee name, and group. Defaults todefault, which returns onlyidandstate.
The response includes a meta.summary.states object counting employees per state across all matching employees (not just the current page).
Request
curl -X GET "https://api.zeitstrom.com/api/v2/reports/employees/active/?verbosity=detail" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Response
{
"count": 42,
"next": null,
"previous": null,
"results": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"state": "working",
"timespan": {
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"checkin": {
"id": "d4e5f6a7-b8c9-0123-def1-234567890123",
"local_id": null,
"time": "2024-06-20T08:00:00",
"creator": "device"
},
"checkout": null,
"employee_comment": null,
"project_id": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
"tag_assignments": [
{
"tag_id": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
"type": "relative",
"value": "100.00000"
}
]
},
"first_name": "Max",
"last_name": "Mustermann",
"employee_group_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"employee_group": "Engineering"
}
],
"meta": {
"summary": {
"states": {
"working": 12,
"absence": 3,
"no-working-day": 5,
"null": 22
}
}
}
}
Activity States
GET /api/v2/reports/employees/active/states/ returns the possible activity states with their labels. Labels are in German.
Request
curl -X GET "https://api.zeitstrom.com/api/v2/reports/employees/active/states/" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Response
{
"count": 4,
"next": null,
"previous": null,
"results": [
{ "id": null, "label": "Ausgestempelt" },
{ "id": "working", "label": "Eingestempelt" },
{ "id": "absence", "label": "Abwesenheit hinterlegt" },
{ "id": "no-working-day", "label": "Kein Arbeitstag" }
]
}
Project Report
Get time spent per project. duration is the total tracked time in seconds; daterange_from and daterange_to reflect the requested bounds, falling back to the first and last tracked check-in when a bound is omitted.
Query Parameters
- Name
daterange- Type
- string
- Description
Date range:
YYYY-MM-DD|YYYY-MM-DD. Either side may be omitted. If omitted entirely, time is aggregated over all tracked timespans. Note that a date-only upper bound is interpreted as midnight at the start of that day.
- Name
ids- Type
- string
- Description
Filter by project IDs, pipe-separated.
- Name
order- Type
- string
- Description
Sort by
durationor-duration.
Projects without tracked time in the selected date range are omitted from the results.
Request
curl -X GET "https://api.zeitstrom.com/api/v2/reports/projects/?daterange=2024-06-01|2024-06-30" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Response
{
"count": 5,
"next": null,
"previous": null,
"results": [
{
"id": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
"archived_at": null,
"name": "Website Redesign",
"code": "WEB-01",
"color": "#2196F3",
"duration": 259200,
"daterange_from": "2024-06-01T00:00:00",
"daterange_to": "2024-06-30T00:00:00"
}
]
}
Retrieve a single Project Report
GET /api/v2/reports/projects/:project_id/ returns the same object for a single project. Because projects without tracked time are excluded, a project with no tracked time in the selected date range returns 404 Not Found.
Request
curl -X GET "https://api.zeitstrom.com/api/v2/reports/projects/1a2b3c4d-5e6f-7890-abcd-ef1234567890/?daterange=2024-06-01|2024-06-30" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Project Report by Employee
Get tracked time aggregated per employee and project. Each result row represents one employee/project combination: id is the employee ID, project is the project ID (or null for time not assigned to any project), and duration is the tracked time in seconds.
Query Parameters
- Name
daterange- Type
- string
- Description
Date range:
YYYY-MM-DD|YYYY-MM-DD. Either side may be omitted. If omitted entirely, time is aggregated over all tracked timespans.
- Name
projects- Type
- string
- Description
Filter by project IDs, pipe-separated. Use the special value
nullto match time not assigned to any project.
- Name
employees- Type
- string
- Description
Filter by employee IDs, pipe-separated.
Request
curl -X GET "https://api.zeitstrom.com/api/v2/reports/projects/employees/?daterange=2024-06-01|2024-06-30" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Response
{
"count": 3,
"next": null,
"previous": null,
"results": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"project": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
"duration": 86400,
"daterange_from": "2024-06-01T00:00:00",
"daterange_to": "2024-06-30T00:00:00"
}
]
}
Export as CSV
GET /api/v2/reports/projects/employees/custom-export/ downloads the same aggregation as a CSV file and accepts the same query parameters.
The CSV export format is configured per customer. If no export format has been set up for your account, the endpoint returns a validation error — please contact support to configure it.
Export as CSV
curl -X GET "https://api.zeitstrom.com/api/v2/reports/projects/employees/custom-export/?daterange=2024-06-01|2024-06-30" \
-H "Authorization: Token <YOUR_API_TOKEN>" \
-o project-report.csv
Absence Report
Export absence data in a format tailored to your payroll system. Absence report exports are configured per customer: each export has a name (the URL path segment), a report type, and a set of output columns, all set up by Zeitstrom support. Requesting an export that has not been configured for your account returns a validation error — please contact support to set one up.
The underlying report types are:
| Type | Description |
|---|---|
annual-aggregate | Absences aggregated by year |
monthly-aggregate | Absences aggregated by month |
absences-list | Flat list of all absences |
Export names commonly follow these types (e.g. annual-aggregate), but the available names depend on your configuration. GET /api/v2/reports/absences/ (without an export name) resolves your account's default absence export, if one is configured.
Query Parameters
- Name
daterange- Type
- string
- Description
Date range:
YYYY-MM-DD|YYYY-MM-DD. Required — both bounds must be provided.
The response is a flat array of rows. The columns (keys) are defined by your export configuration and therefore vary per customer.
Request
curl -X GET "https://api.zeitstrom.com/api/v2/reports/absences/absences-list/?daterange=2024-01-01|2024-12-31" \
-H "Authorization: Token <YOUR_API_TOKEN>"
Example Response
[
{
"Personalnummer": "4711",
"von": "03.06.2024",
"bis": "05.06.2024",
"Abwesenheitsart": "U",
"Anzahl": 3,
"Dauer": "Ganzer Tag"
}
]
Absence reports support multiple output formats. Add &format=csv, &format=txt, or &format=xlsx to the query string to download the report as a file instead of JSON.