REST DocumentationChangelog

Changelog

The REST API specification is generated from the source code and published with every ZEP release. Since the switch to the generated specification the version number describes the API contract (1.x.y), not the product release: a breaking change bumps the major version and lands in a new /api/v2, additive changes keep v1. Releases after the switch are written by the release pipeline from the diff of the specification and only appear when the API changed; the switch release and everything before it were written by hand.

v8.0.27 · OpenAPI 1.0.0 · 22.10.2026

Search combines with the other filters: GET /projects, GET /projects/{id}/tasks (SQ2-1240)

search matches the name or the description, and both now apply together with the other filters (project, status, …). Before, a match on the description or name bypassed them, so GET /projects/12/tasks?search=meeting also returned tasks of other projects. No contract change.

v8.0.24 · OpenAPI 1.0.0 · 22.10.2026

Contacts without primary: POST /customers/{customer_number}/contacts, PUT/PATCH /customers/{customer_number}/contacts/{id} (SQ2-1301)

Creating a contact with primary set to null answered 500. A contact created without primary — null or left out — now becomes the customer’s primary contact when the customer has none yet, and a secondary one otherwise, as in ZEP; before, a left-out primary was stored empty and read back as null. Updating with primary: null keeps the contact’s current value instead of clearing it. No contract change.

Error body when ZEP rejects a write: POST /receipts, PUT/PATCH /receipts/{id}, POST /tickets, PUT/PATCH /tickets/{id}, POST /tickets/{id}/subtasks, PUT/PATCH /tickets/{id}/subtasks/{subtask_id} (SQ2-1301)

When ZEP rejected the write without an error text, these endpoints answered a bare 500 instead of the documented {"success": false, "message": …}. They now always answer with that body: message is ZEP’s text, or “The request could not be processed.” when ZEP sent none. The status stays 500. No contract change.

Project billability and billing type on update: PUT/PATCH /projects/{project} (SQ2-1302)

default_billability: null answered 500. It now keeps the project’s current default billability, the same as leaving the field out. An unknown value (99, "foo", {"id": 99}) for default_billability also answered 500; for billing_type and receipts_billability it was accepted and cleared the field. All three now reject it with 422 and a validation error on the field. No contract change.

v8.0.17 · OpenAPI 1.0.0 · 13.10.2026

Vehicles: GET /vehicles (SQ2-1138)

Lists the vehicles of one vehicle list; the id is the short name that attendances carry as vehicle_id. Vehicles live in dated lists; the list valid on date (YYYY-MM-DD, default today) is the one with the latest start date on or before it. Before the first list the answer is empty. Paginated with limit, read-only. Not available on ZEP Clock.

Invoice creator: GET /invoices, GET /invoices/{invoice} (SQ2-1135)

Each invoice now carries creator_username, the username of the employee who created the invoice document — the employee ZEP shows on the invoice. After a correction it is the employee who corrected the invoice; null when no invoice document is stored.

Attendances accept the vehicle short name: POST /attendances, PATCH /attendances/{id} (SCH-409)

vehicle_id is the vehicle’s short name (as GET already returned it, e.g. PKW), a string of at most 32 characters. Requests rejected it as “must be a number”; a number only ever worked for numeric short names and still does (it is read as the short name), send the short name as a string.

The vehicle_id type change is listed as a fix, not as a breaking change: the request never accepted a vehicle before (every value was rejected), so no working integration depends on the old type. A number that matches a numeric short name is still accepted.

  • FIX POST /attendances, PATCH /attendances/{id}, PUT /attendances/{id}: the vehicle_id request property type changed from number, null to string, null
  • INFO POST /attendances, PATCH /attendances/{id}, PUT /attendances/{id}: the vehicle_id request property’s maxLength was set to 32
  • NEW GET /invoices: added the required property data/items/creator_username to the response with the 200 status
  • NEW GET /invoices/{invoice_number}: added the required property data/creator_username to the response with the 200 status
  • NEW GET /vehicles: endpoint added

v8.0.15 · OpenAPI 1.0.0 · 12.10.2026

Task description limited to 255 characters: POST /projects/{id}/tasks, PUT/PATCH /projects/{id}/tasks/{task_id} (SCH-418)

A description longer than 255 characters answered 500, because the task’s description holds at most 255. It is now rejected with 422 and a validation error on description, and the request schema declares maxLength: 255.

  • INFO POST /projects/{id}/tasks, PATCH /projects/{id}/tasks/{task_id}, PUT /projects/{id}/tasks/{task_id}: the description request property’s maxLength was set to 255

v8.0.11 · OpenAPI 1.0.0 · 10.10.2026

List endpoints sort by orderBy and order

Most list endpoints accepted both parameters and ignored them, so GET /offers?orderBy=status came back in id order. Every list endpoint that documents them now sorts by the record’s key, its writable fields or created/modified, named as in the response (status, name, valid_until, …), order asc or desc. Records with the same value follow in key order (resource plannings: start date, employee, id), so paging stays stable, and links keep the sort. Any other orderBy value sorts by the default, the key (name for locations, the start date for resource plannings); before, it answered 500 on the location, location list and dynamic attribute definition lists. GET /plannings keeps its date order, and GET /projects/{project}/employees its own. No contract change.

v8.0.10 · OpenAPI 1.0.0 · 06.10.2026

GET /resource-plannings lists the plannings of the resource planning: date range, unit (percent or hours per day) and value, plus the planned hours per calendar month and in total. Filterable by date_from/date_to, employee_ids[], project_ids[], customer_numbers[] and modified_after/modified_before. Only with the resource planning module (MOD_PLANNING_NEXT, or product line 4 without MOD_RESSOURCENPLANUNG); other tenants get 404. GET /plannings is unchanged.

  • NEW GET /resource-plannings: endpoint added

v8.0.9 · OpenAPI 1.0.0 · 06.10.2026

The REST API is available on every ZEP product line (Produktwelt 2026) without the separate MOD_SOAP module; tenants on a product line received 404 before. Legacy licences still need MOD_SOAP. The contract itself did not change.

v8.0.7 · OpenAPI 1.0.0 · 25.09.2026 — the generated specification becomes authoritative

  • INFO The OpenAPI document is now generated from the code (controllers, form requests, resources) on every release and published here unchanged — the same file the interactive reference renders. Descriptions live next to the field they describe and cannot drift any more.
  • INFO Version scheme: info.version is 1.0.0 and follows the contract from now on. The previous numbers (7.12.49 and earlier) mirrored the ZEP product version.
  • INFO Every reference page in this documentation (and this navigation) is generated from the specification, in English and German. The response examples are the field examples of the specification.
  • INFO A separate specification for ZEP Clock is published alongside the full version; the reference page offers a switch, and every endpoint page states whether it is available on a Clock instance.
  • NEW All resource update operations accept PUT as an alias of PATCH — the router always did, the documentation now says so.
  • DEPRECATED GET Planning (legacy alias): GET /planning redirects to GET /plannings and answers with Deprecation, Sunset (2027-08-31) and Link headers. It will be removed on or after 2027-08-31.
  • DEPRECATED Customers: the status object carries deprecated: true and x-sunset: 2027-08-31 in the specification. Read inactive instead; status is not part of API v2.
  • FIX Stricter input validation, for requests that did not return a usable result before: POST /attendances, PATCH /attendances/{id} and PUT /attendances/{id} take date as YYYY-MM-DD only (a time component ended in a server error, 500); GET /departments rejects an empty start_date or end_date (it never produced a correct filter). Both now answer 422; clients that already send plain dates are not affected.
  • FIX Path parameters are named after the key the API resolves by: /absence-reasons/{name}, /activities/{activity}, /categories/{name}, /customers/{customer_number}/contacts/{id}, /invoices/{invoice_number}. Numeric ids never worked there; the documentation used to say otherwise.
  • FIX created and modified are documented on every resource instead of created_at / updated_at, which the API never returned.
  • FIX Regular working times expose holidayCalendar and breakRegulationType with the English field names the API always returned (name, note, country, region), not the German column names the old document listed.
  • FIX Nullability and required-ness of every response field match the real responses (measured against a running instance), and the status[] filter of the invoice item endpoints declares its values as integers.

v7.12.49 (24.07.2026)

Covers everything since v7.12 (22.06.2026).

  • FIX POST Create attendance: The booking rules are now checked before writing, and violations come back as 422 with per-field messages — closed month, past the approval date, recording period, non-working day or holiday, employment period, runtime of the project, task or ticket, planned hours exceeded. The API was the only entry point that accepted such bookings; the web interface, SOAP and Clock have always refused them. If you book validly, nothing changes for you.
  • FIX Attendances: A booking ending at 00:00 belongs to the following day. That rollover is now part of the overlap check, so double bookings across the day boundary are detected and refused.
  • FIX GET Customers: status stays and now reports the actual state. Previously an inactive customer came back as { "value": 1, "label": "Active" }, although the documentation always said 1 = active. Nothing changes for active customers; if your client compensated for the inversion, drop that compensation.
  • DEPRECATED Customers: inactive (boolean) supersedes status. status is still emitted and still accepted on POST and PATCH; if both are sent, inactive wins. The ?status= filter is deprecated as well, replaced by ?inactive=. A sunset date will be announced separately.
  • NEW PATCH Update attendance
  • NEW DELETE Delete attendance: Validates the lock periods — closed month, approval date, recording period
  • NEW POST Create customer contact
  • NEW GET Get customer contact
  • NEW PATCH Update customer contact
  • NEW DELETE Delete customer contact
  • NEW PATCH Update project task
  • NEW Attendances: end_date on every response — the calendar day the booking ends on. to alone is ambiguous for a day-end booking, which is stored as to = 00:00:00 on the start date.
  • NEW Customer contacts: department and categories on the response
  • NEW The modified_after and modified_before filters on several list endpoints
  • NEW Languages sk (Slovak) and tr (Turkish)
  • FIX An empty date filter returns 422 instead of 500 — on Absences and five further endpoints
  • FIX Employees whose employment period has no start or end date are no longer rejected as “outside the employment period”. An absent bound now means open-ended.
  • FIX default_billability and receipts_billability are no longer ignored on POST and PATCH
  • FIX Planning: The configured defaults are returned
  • INFO Nine operations that already existed are now documented — among them POST /absences, GET /attendances/:id and PATCH /employees/:username. Plus 66 response fields the endpoints always returned, and two relation keys on regular working times that never matched their documented names.

v7.12 (22.06.2026)

v7.8.74 (09.01.2026)

v7.8.64 (2026-01-07)

v7.7.0 (2025-10-07)

  • NEW GET Articles: Added endpoint for retrieving articles
  • NEW GET Article details: Added endpoint for single article
  • NEW GET Planning: Added endpoint for retrieving planning entries
  • NEW GET Project locations: Added endpoint for project locations
  • NEW PUT Update employee: Added endpoint for updating employees
  • NEW PUT Update employment period: Added endpoint for updating employment periods
  • FIX Corrected plan_can_exceed data type from boolean to enum (0-4) in all project endpoints
  • FIX Added missing filter parameters (project_status, project_start_date, project_end_date) for Employee projects
  • FIX Added missing id field in ProjectEmployee response examples

v7.6.1 (2025-09-22)

v7.4.2 (2025-06-24)

  • NEW GET Attendances: Added new fields project_release, project_released_at and project_released_by for project time approval
  • NEW GET Attendance details: Added new fields for project time approval

v7.4.1 (2025-06-18)

  • INFO OpenAPI specification updated to include all documented endpoints
  • NEW POST Create employee
  • FIX GET Absences: Updated response examples to match current API structure, including new fields absence_reason_id, absenceReason object, and corrected date formats
  • FIX GET Attendances: Updated response examples to match current API structure and date/time formats
  • NEW GET Attendance details: Added documentation for single attendance endpoint
  • FIX GET Departments: Updated response examples with new fields parent_id, manager_count, children_count
  • FIX GET Department details: Updated response structure with manager array instead of manager_count
  • FIX GET Department employees: Updated response examples with new field approval_date and language object structure
  • FIX GET Employees: Added new fields categories and dynamicAttributes arrays, changed release_date to approval_date
  • NEW GET Employee transponders: Added documentation for retrieving RFID transponders assigned to an employee
  • FIX GET Devices: Updated response examples to match current API structure with device types and status codes
  • FIX GET Device details: Updated response structure showing employees and categories arrays
  • FIX GET Customers: Updated response structure with new fields vat (replacing tax), status as object, department_id, categories and dynamicAttributes arrays
  • FIX GET Customer details: Updated response with new address fields, removed employees array, added complete priceTables structure
  • FIX GET Offers: Updated response examples and added missing field order_probability_percent
  • NEW GET Offer items: Added documentation for retrieving offer items/positions
  • FIX GET Receipts: Updated response structure with simplified receipt_type_id as string instead of object, changed field names is_amount_gross_or_net to is_amount_net and is_invoice_amount_gross_or_net to is_invoice_amount_net
  • FIX GET Receipt details: Updated response structure to match list endpoint with same field changes
  • FIX GET Receipt amounts: Updated response examples with realistic data and added new fields is_amount_net and is_invoice_amount_net
  • FIX GET Receipt attachments: Added response example with Base64-encoded file contents
  • FIX GET Tickets: Fixed response examples - incorrectly contained receipt data instead of ticket data, added categories array
  • FIX GET Ticket details: Updated response example with current data
  • FIX GET Ticket subtasks: Updated response example with realistic data
  • FIX GET Ticket subtask details: Updated response example with anonymized data
  • NEW GET Folders: Added new endpoint for retrieving folders
  • NEW GET Folder documents: Added new endpoint for retrieving documents within a folder
  • NEW GET Price groups: Added new endpoint for retrieving price groups
  • NEW GET Activities: Added new endpoint for retrieving activities
  • NEW GET Absence reasons: Added new endpoint for retrieving absence reasons
  • NEW GET Categories: Added new endpoint for retrieving categories

v7.4.0 (2025-06-17)

  • NEW Major version update with enhanced API capabilities
  • INFO Updated API documentation and improved endpoint descriptions

v6.13.17 (2024-09-16)

v6.13.16 (2024-08-27)

v6.12.5 (2024-03-06)

  • The rate limiting has been increased to 12000 requests per hour. A maximum of 1000 requests are allowed per 5 minutes
  • Added name parameter to project filter for Projects
  • Bugfix for Projects: The plan_hours value did not show planned hours if they were defined in subtasks. The value plan_hours_children has been added for this purpose
  • Bugfix for Projects: The project does not have to be completely within a filtered period. It is sufficient if it was active within the period
  • Bugfix for Employees: Under certain circumstances, a server error occurred. This error has been fixed

v6.12.4 (2024-03-01)

  • Some performance improvements

v6.12.3 (2024-02-16)

v6.12.2 (2024-02-02)

v6.12.1 (2024-01-14)