Daily Reports

Daily reports (Tagesberichte) document what happened on a construction site or project on a single calendar day: who was on site and for how long, the weather, subcontractors, activities, material usage, comments, photos, and signatures. A report is identified by the combination of a project and a date — it is not a stored object of its own, but materializes from the individual entries recorded for that day, either authored on site in the mobile app or filled in automatically from time tracking.

The Report Object

A report is the group of all entries that share a project and a date. Reports only exist for projects that have daily reports enabled in the project's settings, and only for days that have at least one entry. The tag_id is the project's id as returned by the Projects API.

Every report has a computed status describing its position in the review lifecycle:

  • draft — the report is being worked on and can be edited on site.
  • submitted — the site crew handed the report in for review. Only supervisors (users with the approve permission) may still change it.
  • closed — the report was approved. Like submitted, it is locked for regular editors.
  • Name
    id
    Type
    string
    Description

    Synthetic identifier of the report in the form <tag_id>|<date>, e.g. 3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31|2024-06-18. Read-only.

  • Name
    date
    Type
    string (YYYY-MM-DD)
    Description

    The calendar day the report covers.

  • Name
    tag_id
    Type
    string (UUID)
    Description

    The project the report belongs to.

  • Name
    status
    Type
    string
    Description

    Computed report status: draft, submitted, or closed.


Field Configurations

Which fields a daily report contains is configurable per organization, and the configuration is versioned by date. Your organization keeps a list of configurations, each with a valid_from date; the configuration that applies to a report is the one with the most recent valid_from on or before the report's date (a configuration becomes active on its valid_from day). If no custom configuration exists, a default form applies with these fields:

Field idTypeLabel (German)
weatherweatherWitterung
employee-working-timesemployee-working-timesMitarbeitende
subcontractorssubcontractorsNachunternehmen
activitiesactivitiesTätigkeiten
materialsstringMaterial- / Geräteeinsatz
commentsstringBemerkungen / Behinderungen
photosimageFotos
signaturessignatureUnterschriften

Versioning has two consequences you will notice in the API:

  • Every entry is interpreted and validated against the configuration that is active on the entry's date, not the one active today. Historical reports keep the form they were written with, even after the organization changes its report layout.
  • Entries whose field id does not exist in the configuration active for their date (for example, a field that was later removed) are omitted from entry listings and PDFs — they have no schema to render.

Use the field-types endpoint to discover the available field types and how entries of each type are grouped.


The Entry Object

Entries are append-only: nothing is ever updated in place. Each entry belongs to a logical group identified by its group_id, which combines the report's date and tag_id with type-specific keys (for example, one group per employee for working times, or one group per author-and-text for comments). The most recent entry of a group is its current value; older entries are the group's history. An entry with burned: true is a tombstone that marks its group as deleted.

Entries written by the system — the time-tracking autofill and the automatic weather capture — have author_id: null; the affected employee is carried in on_behalf_of_id. Manually authored entries carry the author, and on_behalf_of_id names the person the entry is about (e.g. who signed, or whose working time was corrected).

  • Name
    id
    Type
    string (UUID)
    Description

    Unique identifier of the entry. Read-only.

  • Name
    group_id
    Type
    string
    Description

    Pipe-separated grouping key, starting with date and tag_id followed by the field type's grouping values. Read-only.

  • Name
    group_count
    Type
    integer
    Description

    Number of entries in this entry's group that match the request's filters, including tombstones — filtering by ids excludes the group's other entries from the count. Only present in list responses. Read-only.

  • Name
    field_id
    Type
    string
    Description

    Id of the report field the entry belongs to, as defined in the active field configuration (e.g. comments).

  • Name
    type
    Type
    string
    Description

    The field's type: weather, employee-working-times, subcontractors, activities, string, image, or signature.

  • Name
    date
    Type
    string (YYYY-MM-DD)
    Description

    The report day the entry belongs to.

  • Name
    tag_id
    Type
    string (UUID)
    Description

    The project the entry belongs to.

  • Name
    author_id
    Type
    string (UUID) or null
    Description

    The user who authored the entry, or null for system-generated entries (autofill, weather capture).

  • Name
    author_name
    Type
    string or null
    Description

    Full name of the author, or null.

  • Name
    on_behalf_of_id
    Type
    string (UUID) or null
    Description

    The user the entry is about (e.g. the employee whose hours are recorded, or the person who signed), or null.

  • Name
    on_behalf_of_name
    Type
    string or null
    Description

    Full name of the on_behalf_of user, or null.

  • Name
    burned
    Type
    boolean
    Description

    true marks the entry as a tombstone: the group it belongs to should be treated as deleted if the tombstone is the group's latest entry.

  • Name
    submitted_at
    Type
    string (ISO 8601, local time) or null
    Description

    When the entry reached the server, e.g. 2024-06-18T16:42:07. null for system-generated entries.

  • Name
    created_at
    Type
    string (ISO 8601, local time)
    Description

    When the entry was stored. Read-only.

  • Name
    modified_at
    Type
    string (ISO 8601, local time)
    Description

    When the entry was last modified. Read-only.

Type-specific value fields

In addition to the common properties above, each entry carries the value fields of its type:

  • weathertime (string, a clock time such as 08:00), temperature, precipitation, cloud_cover (each a number or null), and wind (a [speed, direction] pair with the direction in degrees 0359, or null). Grouped by time, so a report holds one weather row per configured time slot.
  • employee-working-timeshours (number between 0 and 24). Grouped by on_behalf_of_id: one row per employee and day.
  • subcontractorsname (string), employees (integer), hours (number or null), comment (string or null). Grouped by on_behalf_of_id and name.
  • activitiestext (string). Grouped by on_behalf_of_id and text, so the same activity text for the same person deduplicates.
  • stringvalue (string). Used by the default materials and comments fields. Grouped by on_behalf_of_id and value.
  • imageimage_id (string), image_key (string or null, the S3 object key from the photo upload flow), image_url (string or null — a pre-signed download URL derived from image_key, valid for one hour), latitude / longitude (numbers or null), and taken_at (string or null). Grouped by on_behalf_of_id and image_id.
  • signatureimage (string, a data:image/... data URL of the signature). Grouped by on_behalf_of_id: one signature per person per report.

GET/api/v2/daily-reports/reports/

List all Reports

Retrieve a paginated list of report descriptors, one per project and date that has at least one entry. Results are ordered by date descending, then by project id, and cover only projects that have daily reports enabled and that your token is allowed to see.

Query Parameters

  • Name
    date_from
    Type
    string (YYYY-MM-DD)
    Description

    Only include reports on or after this date. Invalid values are ignored.

  • Name
    date_to
    Type
    string (YYYY-MM-DD)
    Description

    Only include reports on or before this date. Invalid values are ignored.

  • Name
    projects
    Type
    string
    Description

    Restrict to specific projects by passing a pipe-separated list of project ids (UUIDs). Invalid UUIDs are dropped from the list; if no valid id remains, the result is empty.

  • Name
    status
    Type
    string
    Description

    Pipe-separated set of statuses to keep, e.g. status=submitted|closed. Valid values are draft, submitted, and closed; unknown values are ignored, and an empty filter returns all reports.

  • Name
    limit
    Type
    integer
    Description

    Number of results per page. Defaults to 100, maximum 1000.

  • Name
    offset
    Type
    integer
    Description

    Number of results to skip for pagination. Defaults to 0.

Request

curl -X GET "https://api.zeitstrom.com/api/v2/daily-reports/reports/?date_from=2024-06-17&date_to=2024-06-18&status=draft|submitted" \
  -H "Authorization: Token <YOUR_API_TOKEN>"

Response

{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31|2024-06-18",
      "date": "2024-06-18",
      "tag_id": "3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31",
      "status": "submitted"
    },
    {
      "id": "3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31|2024-06-17",
      "date": "2024-06-17",
      "tag_id": "3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31",
      "status": "draft"
    }
  ]
}

GET/api/v2/daily-reports/reports/field-types/

List Field Types

Retrieve the available field types and the keys entries of each type are grouped by. Every group_by list starts with the common date and tag_id keys, followed by the type's own grouping values.

Request

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

Response

{
  "count": 7,
  "next": null,
  "previous": null,
  "results": [
    { "id": "weather", "group_by": ["date", "tag_id", "time"] },
    { "id": "employee-working-times", "group_by": ["date", "tag_id", "on_behalf_of_id"] },
    { "id": "subcontractors", "group_by": ["date", "tag_id", "on_behalf_of_id", "name"] },
    { "id": "activities", "group_by": ["date", "tag_id", "on_behalf_of_id", "text"] },
    { "id": "string", "group_by": ["date", "tag_id", "on_behalf_of_id", "value"] },
    { "id": "image", "group_by": ["date", "tag_id", "on_behalf_of_id", "image_id"] },
    { "id": "signature", "group_by": ["date", "tag_id", "on_behalf_of_id"] }
  ]
}

GET/api/v2/daily-reports/reports/status/

Retrieve Report Status

Get the current status of a single report. A report without any recorded status transition is a draft.

Query Parameters

  • Name
    tag
    Type
    string (UUID)
    Description

    The project id. Required. An unknown or inaccessible project returns a 400 validation error.

  • Name
    date
    Type
    string (YYYY-MM-DD)
    Description

    The report date. Required.

Request

curl -X GET "https://api.zeitstrom.com/api/v2/daily-reports/reports/status/?tag=3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31&date=2024-06-18" \
  -H "Authorization: Token <YOUR_API_TOKEN>"

Response

{
  "tag_id": "3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31",
  "date": "2024-06-18",
  "status": "submitted"
}

POST/api/v2/daily-reports/reports/autofill/

Autofill a Report

Compute and store report entries from the day's time tracking on the project. Only fields whose active configuration carries autofill_from_tracking and whose type is employee-working-times or activities are filled — with the default configuration these are employee-working-times (each employee's tracked hours on the project, rounded to two decimals) and activities (one entry per distinct tracking comment and employee).

The operation creates entries as a side effect. System-written entries have author_id: null. The autofill is idempotent: repeated calls converge to the same state, unchanged values are skipped, and a value that was manually corrected by a user is never overwritten.

Autofilling a report that is submitted or closed requires the daily_reports:approve permission; without it the request returns 403 Forbidden.

  • Name
    tag
    Type
    string (UUID)
    Description

    The project id. Required. An unknown or inaccessible project returns a 400 validation error.

  • Name
    date
    Type
    string (YYYY-MM-DD)
    Description

    The report date. Required.

  • Name
    field
    Type
    string
    Description

    Optional field id to restrict the autofill to a single field, e.g. activities. A field that is not autofillable results in filled: [].

Request

curl -X POST "https://api.zeitstrom.com/api/v2/daily-reports/reports/autofill/" \
  -H "Authorization: Token <YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "tag": "3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31",
    "date": "2024-06-18"
  }'

Response

{
  "tag_id": "3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31",
  "date": "2024-06-18",
  "filled": ["employee-working-times", "activities"]
}

GET/api/v2/daily-reports/reports/pdf/

Download a Report PDF

Render a single report as a print-friendly PDF. The response streams the PDF binary (Content-Type: application/pdf) with a filename of the form Tagesbericht-<project code>-<date>.pdf. The PDF contains the fields of the configuration active for the report's date, with the report's status shown in the header.

Query Parameters

  • Name
    tag
    Type
    string (UUID)
    Description

    The project id. Required. An unknown or inaccessible project returns a 400 validation error.

  • Name
    date
    Type
    string (YYYY-MM-DD)
    Description

    The report date. Required.

Request

curl -X GET "https://api.zeitstrom.com/api/v2/daily-reports/reports/pdf/?tag=3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31&date=2024-06-18" \
  -H "Authorization: Token <YOUR_API_TOKEN>" \
  -o "Tagesbericht-2024-06-18.pdf"

GET/api/v2/daily-reports/entries/

List all Entries

Retrieve a paginated list of report entries, projected through the field configuration active for each entry's date. Entries of fields that no longer exist in the active configuration are omitted. To reconstruct the current content of a report, request grouped=1 for a single project and date and treat groups whose latest entry is burned: true as deleted.

Query Parameters

  • Name
    tags
    Type
    string
    Description

    Restrict to specific projects by passing a pipe-separated list of project ids (UUIDs). If any id is invalid or refers to a project you cannot see, the result is empty.

  • Name
    daterange
    Type
    string
    Description

    Inclusive date range in the form YYYY-MM-DD|YYYY-MM-DD, e.g. daterange=2024-06-18|2024-06-18. Both dates are required; a malformed or half-open range yields an empty result.

  • Name
    grouped
    Type
    string
    Description

    Set grouped=1 to return only the most recent entry per group. The returned group_count still reflects the full group size.

  • Name
    ids
    Type
    string
    Description

    Restrict to specific entries by passing a pipe-separated list of entry ids (UUIDs). Invalid UUIDs are dropped from the list; if no valid id remains, the result is empty.

  • Name
    limit
    Type
    integer
    Description

    Number of results per page. Defaults to 100, maximum 1000.

  • Name
    offset
    Type
    integer
    Description

    Number of results to skip for pagination. Defaults to 0.

Request

curl -X GET "https://api.zeitstrom.com/api/v2/daily-reports/entries/?tags=3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31&daterange=2024-06-18|2024-06-18&grouped=1" \
  -H "Authorization: Token <YOUR_API_TOKEN>"

Response

{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "group_id": "2024-06-18|3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31|508d5250-7399-4b65-a574-3da53d9ddc25",
      "id": "6b0f2d84-3c9e-4f17-8a52-b1d4e7c90a63",
      "field_id": "employee-working-times",
      "type": "employee-working-times",
      "created_at": "2024-06-18T17:02:11",
      "modified_at": "2024-06-18T17:02:11",
      "submitted_at": null,
      "date": "2024-06-18",
      "tag_id": "3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31",
      "author_id": null,
      "on_behalf_of_id": "508d5250-7399-4b65-a574-3da53d9ddc25",
      "author_name": null,
      "on_behalf_of_name": "Anna Schmidt",
      "burned": false,
      "hours": 7.75,
      "group_count": 1
    },
    {
      "group_id": "2024-06-18|3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31|e7c9a4d2-1f38-4b6a-9c05-8d2f7b3e6a14|Lieferung Schalholz verspätet",
      "id": "9d47c1f0-5e2b-4a86-b3f9-0c61d8a24e57",
      "field_id": "comments",
      "type": "string",
      "created_at": "2024-06-18T16:42:09",
      "modified_at": "2024-06-18T16:42:09",
      "submitted_at": "2024-06-18T16:42:07",
      "date": "2024-06-18",
      "tag_id": "3f2b8c1e-9a47-4d05-b8a1-6c2d94e07f31",
      "author_id": "e7c9a4d2-1f38-4b6a-9c05-8d2f7b3e6a14",
      "on_behalf_of_id": "e7c9a4d2-1f38-4b6a-9c05-8d2f7b3e6a14",
      "author_name": "Jonas Weber",
      "on_behalf_of_name": "Jonas Weber",
      "burned": false,
      "value": "Lieferung Schalholz verspätet",
      "group_count": 1
    }
  ]
}

POST/api/v2/daily-reports/entries/upload-photo-token/

Get a Photo Upload Token

Generate a pre-signed upload token for a daily-report photo (at most 5 MB). The response contains a pre-signed S3 url and form fields, valid for 12 hours. Upload the photo as a multipart/form-data POST to url, including all fields plus the file itself. The returned fields.key is the object key that photo entries store as their image_key; when entries are read, the server signs it back into a temporary image_url download link. Keys are validated to lie inside your organization's upload namespace.

  • Name
    employee_id
    Type
    string (UUID)
    Description

    The employee the photo belongs to. Must be an active (non-archived) employee of your organization. Required.

  • Name
    filename
    Type
    string
    Description

    Name of the file, used as part of the storage key.

  • Name
    filetype
    Type
    string
    Description

    MIME type of the file (e.g. image/jpeg), used to derive the file extension.

  • Name
    filesize
    Type
    integer
    Description

    Size of the file in bytes. Validated against the 5 MB limit.

Request

curl -X POST "https://api.zeitstrom.com/api/v2/daily-reports/entries/upload-photo-token/" \
  -H "Authorization: Token <YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "employee_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "filename": "betonage-nord",
    "filetype": "image/jpeg",
    "filesize": 2048576
  }'

Response

{
  "url": "https://s3.eu-central-1.amazonaws.com/zeitstrom-uploads",
  "fields": {
    "key": "i-f4a5b6c7-d8e9-0123-fabc-456789012345/e-a1b2c3d4-e5f6-7890-abcd-ef1234567890/daily-reports/2024/06/18/0d3e2b1a-4c5d-6e7f-8901-234567890abc/2024-06-18_4f2a_betonage-nord.jpg",
    "AWSAccessKeyId": "AKIAIOSFODNN7EXAMPLE",
    "policy": "eyJleHBpcmF0aW9uIjogIjIwMjQtMDYtMTlUMDY6MzA6MDBaIiwgImNvbmRpdGlvbnMiOiBbXX0=",
    "signature": "hV0kwGx0ZQKgQnJ1zW0m9dEXAMPLE"
  }
}

Was this page helpful?