Exports

The exports API generates data exports in formats compatible with payroll and accounting systems. Exports can be generated synchronously for small datasets or asynchronously for large ones.

Overview

Exports combine time tracking data from employees, timespans, and absences into structured output. Four exporter engines are available, each running under its own URL:

ExporterDescriptionconfig parameter
genericFlexible exporter with configurable columns, row types, and filters. See the Generic Reporting API.Must be omitted.
sageFixed layout compatible with Sage payroll software.Must be omitted.
datevFixed layout compatible with DATEV payroll software (common in Germany).Required: Steuerberaternummer|Mandantennummer.
multiCombines multiple generic export configurations into one request. See Multi-Export.Required: JSON array of export configurations.

Exporter names are lowercase and case-sensitive: generic, sage, datev, multi.

Exports only include employees visible to the authenticated user — for example, department leaders only export data for employees of their departments. Employees archived before the start of the export period are excluded automatically.


GET/api/v2/exports/

List Available Exporters

Returns a map of exporter names to their endpoint URLs. Query parameters are ignored on this route; exports are generated on the per-exporter detail routes below.

Request

curl -X GET "https://api.zeitstrom.com/api/v2/exports/" \
  -H "Authorization: Token <YOUR_API_TOKEN>"

Response

{
  "sage": "https://api.zeitstrom.com/api/v2/exports/sage/",
  "datev": "https://api.zeitstrom.com/api/v2/exports/datev/",
  "generic": "https://api.zeitstrom.com/api/v2/exports/generic/",
  "multi": "https://api.zeitstrom.com/api/v2/exports/multi/"
}

GET/api/v2/exports/:exporter/

Run an Export

Generate an export with the exporter named in the path, e.g. /api/v2/exports/generic/ or /api/v2/exports/datev/.

Query Parameters

  • Name
    daterange
    Type
    string
    Description

    Date range for the export: YYYY-MM-DD|YYYY-MM-DD. Required.

  • Name
    export_format
    Type
    string
    Description

    Output format: csv, json, table, plain, or xlsx. Defaults to csv. The csv format accepts additional options such as csv:delimiter>%3b, see CSV Format Options.

  • Name
    response_only
    Type
    boolean
    Description

    When true, the response body is the raw export itself, served with the format's content type — i.e. a direct file download. When false (the default), the export is wrapped in a JSON envelope containing the request configuration and the data (see below).

  • Name
    types
    Type
    string
    Description

    Row types to include, pipe-separated (generic exporter). See Row Types.

  • Name
    columns
    Type
    string
    Description

    Columns to include, pipe-separated (generic exporter). See Column Customization.

  • Name
    config
    Type
    string
    Description

    Exporter-specific configuration. Required for datev and multi, must be omitted for generic and sage (see the table above).

  • Name
    employee_ids
    Type
    string
    Description

    Restrict the export to specific employees, pipe-separated UUIDs. Duplicate or unknown IDs are rejected with a 400 validation error.

  • Name
    employee_group_ids
    Type
    string
    Description

    Restrict the export to specific departments, pipe-separated UUIDs. When combined with employee_ids, employees matching either list are included.

  • Name
    filter
    Type
    string
    Description

    Additional employee filters as key=value pairs. Multiple filters are combined with | in a single filter parameter. See Filtering.

  • Name
    skip_zero_rows
    Type
    boolean
    Description

    Skip rows with zero values (generic exporter). Defaults to true. The sage and datev exporters ignore this parameter.

  • Name
    prefix
    Type
    string
    Description

    Base64-encoded text prepended to the output. Only supported for the csv, plain, and table formats.

  • Name
    is_async
    Type
    boolean
    Description

    Generate the export in the background. Defaults to false. See Asynchronous Exports.

With response_only=true the endpoint behaves like a file download:

Direct CSV Download

curl -X GET "https://api.zeitstrom.com/api/v2/exports/generic/?daterange=2024-06-01|2024-06-30&types=credit-time:hours&columns=first-name|last-name|value&export_format=csv&response_only=true" \
  -H "Authorization: Token <YOUR_API_TOKEN>" \
  -o export-june.csv

Without response_only, the report is wrapped in a JSON envelope that echoes the validated request configuration:

JSON Envelope

curl -X GET "https://api.zeitstrom.com/api/v2/exports/generic/?daterange=2024-06-01|2024-06-30&types=credit-time:hours&columns=first-name|last-name|value&export_format=json" \
  -H "Authorization: Token <YOUR_API_TOKEN>"

Response

{
  "request": {
    "is_async": false,
    "skip_zero_rows": true,
    "exporter": "generic",
    "export_format": "json",
    "daterange": ["2024-06-01", "2024-06-30"],
    "employee_ids": null,
    "types": ["credit-time:hours"],
    "columns": ["first-name", "last-name", "value"],
    "response_only": false,
    "prefix": null,
    "filter": null
  },
  "response": [
    { "first-name": "Max", "last-name": "Mustermann", "value": 152.5 },
    { "first-name": "Erika", "last-name": "Musterfrau", "value": 148.25 }
  ]
}

Export Formats

FormatContent-Type (response_only=true)Description
csvtext/csvComma-separated values. Delimiter and header row are configurable, see CSV Format Options.
jsonapplication/jsonJSON array of objects.
xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetExcel spreadsheet.
tabletext/plainFormatted ASCII table.
plaintext/plainPlain text output.

GET/api/v2/exports/sage/

The Sage Exporter

Produces a fixed-layout wage record export for Sage payroll. It takes no config or columns parameters — the layout is predefined. The types parameter may optionally contain pipe-separated wage type codes (e.g. types=301|400) to restrict the output to those rows.

With export_format=csv the output is semicolon-delimited and includes a header row with the columns MDNr;AbrMon;AbrJahr;ANNr;LANr;Dat;Kost;KoTr;AA;Anz;Betrag;Zuschlag;Text. The accounting month (AbrMon) and year (AbrJahr) are taken from the start of the daterange, ANNr is the employee's accounting number, Kost is the employee's department name, and Anz is the count formatted with a decimal comma. Employees without an accounting number are omitted.

Each row carries one wage type code in LANr:

CodeContent
301Sunday work hours.
305Night work hours (23:00–06:00).
360Vacation days, one row per day (Dat holds the day of month).
157Vacation day total per employee.
402Vacation hours total per employee.
99001Sick leave and education/training days, one row per day.
158Sick day total per employee.
403Sick hours total per employee.
424Education/training hours total per employee.
400Planned working hours for the period.
401Recorded (tracked) working hours for the period.

Request

curl -X GET "https://api.zeitstrom.com/api/v2/exports/sage/?daterange=2024-06-01|2024-06-30&export_format=csv&response_only=true" \
  -H "Authorization: Token <YOUR_API_TOKEN>" \
  -o sage-june.csv

GET/api/v2/exports/datev/

The DATEV Exporter

Produces a wage record export for DATEV payroll. It requires a config parameter containing the tax advisor number (Steuerberaternummer) and client number (Mandantennummer), pipe-separated. Both values must be numeric, otherwise the request fails with a 400 validation error.

With export_format=csv the output is semicolon-delimited without a header row. The first row identifies the file: advisor number, client number, and the accounting month as MM/YYYY (taken from the start of the daterange). Each following row contains the employee's accounting number (Personalnummer), a wage type code, and the count formatted with a decimal comma. Employees without an accounting number and zero-value rows are omitted.

CodeContent
1000Recorded (tracked) working hours.
8560Vacation days.
1602Vacation hours.
8570Sick days.
1652Sick hours.
1015Public holiday hours.

Request

curl -X GET "https://api.zeitstrom.com/api/v2/exports/datev/?config=12345|67890&daterange=2024-06-01|2024-06-30&export_format=csv&response_only=true" \
  -H "Authorization: Token <YOUR_API_TOKEN>" \
  -o datev-june.csv

Discovery Endpoints

Each exporter route exposes four discovery endpoints that return human-readable reference pages (HTML, no authentication required) describing the building blocks of the Generic Reporting API:

EndpointContent
GET /api/v2/exports/generic/columns/Available columns.
GET /api/v2/exports/generic/types/Available row types.
GET /api/v2/exports/generic/modifiers/Available value modifiers.
GET /api/v2/exports/generic/filters/Available filters.

See Discovery Endpoints for details on how columns, types, modifiers, and filters are used.


Asynchronous Exports

For large datasets, add is_async=true to any export request. Instead of the export itself, the endpoint returns a background task:

Start Async Export

curl -X GET "https://api.zeitstrom.com/api/v2/exports/generic/?daterange=2024-01-01|2024-12-31&types=credit-time:hours&columns=first-name|last-name|value&export_format=xlsx&response_only=true&is_async=true" \
  -H "Authorization: Token <YOUR_API_TOKEN>"

Response

{
  "id": "9f2b6c1e-4a3d-4b7e-9c0a-1d2e3f4a5b6c",
  "created_at": "2024-06-30T06:15:00",
  "finished_at": null,
  "status": "created",
  "target": null
}

The request parameters are validated up front exactly like a synchronous export — in particular, xlsx still requires response_only=true.

Repeating the same request with identical parameters within 12 hours does not start a new export; it returns the current state of the existing task. This is also how you poll for completion: send the same request again until status is finished. status is one of created, in_progress, finished, or error.

Once finished, target contains a presigned download URL for the generated file, valid for 12 hours:

Finished Task

{
  "id": "9f2b6c1e-4a3d-4b7e-9c0a-1d2e3f4a5b6c",
  "created_at": "2024-06-30T06:15:00",
  "finished_at": "2024-06-30T06:16:42",
  "status": "finished",
  "target": "https://zeitstrom-exports.s3.eu-central-1.amazonaws.com/…/9f2b6c1e-4a3d-4b7e-9c0a-1d2e3f4a5b6c.xlsx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=43200&X-Amz-Signature=…"
}

You can also track background tasks through the asynchronous tasks endpoints described below.


The Asynchronous Task Object

  • Name
    id
    Type
    string (UUID)
    Description

    Unique identifier for the task.

  • Name
    status
    Type
    string
    Description

    One of created, in_progress, or finished. Tasks that failed with an error are hidden from these endpoints.

  • Name
    label
    Type
    string or null
    Description

    Optional human-readable label.

  • Name
    description
    Type
    string or null
    Description

    Optional human-readable description.

  • Name
    action
    Type
    string
    Description

    The kind of background job. Exports started via is_async=true use generic_export.

  • Name
    created_at
    Type
    string (ISO 8601)
    Description

    Timestamp when the task was created.

  • Name
    started_at
    Type
    string (ISO 8601) or null
    Description

    Timestamp when processing started, or null if still queued.

  • Name
    finished_at
    Type
    string (ISO 8601) or null
    Description

    Timestamp when processing finished, or null while pending.

  • Name
    result
    Type
    object or null
    Description

    Result data of the task. For exports this holds an internal storage reference to the generated file — to obtain a download URL, use the target field returned by the export endpoint.


GET/api/v2/asynchronous-tasks/tasks/

List Asynchronous Tasks

Retrieve a paginated list of your own background tasks. Only tasks started by the authenticated user are returned.

Request

curl -X GET "https://api.zeitstrom.com/api/v2/asynchronous-tasks/tasks/" \
  -H "Authorization: Token <YOUR_API_TOKEN>"

Response

{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "9f2b6c1e-4a3d-4b7e-9c0a-1d2e3f4a5b6c",
      "status": "finished",
      "label": null,
      "description": null,
      "action": "generic_export",
      "created_at": "2024-06-30T06:15:00",
      "started_at": "2024-06-30T06:15:05",
      "finished_at": "2024-06-30T06:16:42",
      "result": {
        "file": "i-3f9c2d71-58a4-4c0e-9b12-7e6a1f0d4c88/u-b4d9e2a6-1c35-47f8-8a90-52c7e3b1d6f4/2024/06/30/9f2b6c1e-4a3d-4b7e-9c0a-1d2e3f4a5b6c.xlsx"
      }
    }
  ]
}

GET/api/v2/asynchronous-tasks/tasks/:id/

Retrieve an Asynchronous Task

Get the current state of a specific task.

Request

curl -X GET "https://api.zeitstrom.com/api/v2/asynchronous-tasks/tasks/9f2b6c1e-4a3d-4b7e-9c0a-1d2e3f4a5b6c/" \
  -H "Authorization: Token <YOUR_API_TOKEN>"

DELETE/api/v2/asynchronous-tasks/tasks/:id/

Delete an Asynchronous Task

Delete an export task. For finished exports, the generated file is removed from storage as well, invalidating previously issued download URLs.

Request

curl -X DELETE "https://api.zeitstrom.com/api/v2/asynchronous-tasks/tasks/9f2b6c1e-4a3d-4b7e-9c0a-1d2e3f4a5b6c/" \
  -H "Authorization: Token <YOUR_API_TOKEN>"

Was this page helpful?