Celery API Changelog

What changed in each release of the Celery API. Entries marked Breaking need a change on your side.

v4.8.1

29 October 2026 Breaking 2 bugfixes
  • Breaking POST catch/integrations/dyflexis/hours currently returns 200 {"message":"Payroll period received successful."} even when the payload matches no active integration, so clients cannot distinguish a dropped payload from a queued one. The intended behavior is for an unmatched payload to return a non-200 response, using the existing 404 {"message":"Could not find system name and office name in any active integration."} when no integration is found. Clients consuming this webhook should not treat every 200 as proof that the hours were accepted and forwarded. #486
  • Breaking PUT /employees/{id} no longer disables an employee’s self-service login by clearing user_context.active as a side effect of an update. Integrations can continue sending the same employee payloads; the employee’s existing user context is now preserved when updating fields like name or address. POST /employees is unaffected. #538

v4.8.0

17 October 2026 1 feature
  • Added a new /employee-wage-codes resource to read and manage the fixed wage codes linked to a single employee. It supports GET /employee-wage-codes?employee_id={employee_id}, POST /employee-wage-codes, GET /employee-wage-codes/{employee_wage_code_id}, PUT /employee-wage-codes/{employee_wage_code_id}, and DELETE /employee-wage-codes/{employee_wage_code_id}. List and detail responses include id, code, wage_code_id, read_only, and settings, with the detail resource also returning employer_id and employee_id; PUT replaces settings completely and DELETE removes the linked wage code. #519

v4.7.0

2 October 2026 Breaking 2 features 1 bugfix
  • GET /wage-codes/{wage_code_id} is new and returns a single wage code with employer_id, available and settings, where settings describes the fields the wage code accepts. GET /wage-codes accepts a code query parameter to filter on one or more comma-separated wage code numbers and an employee_id query parameter to limit the list to the wage codes available to that employee. employee_id is also accepted on the single wage code endpoint, in which case available and settings are evaluated for that employee; an unknown employee or one of another employer returns 404. #518
  • GET /pay-periods is new and lists the pay periods of one pay schedule. The pay_schedule_id query parameter is required, the response is paginated with page and limit, and each item carries id, label, period, period_start, period_end, payday, year, position, is_special, type and special_position. Special periods such as holiday pay or a thirteenth month are included and flagged with is_special, and the optional year query parameter limits the list to one year. A missing or invalid pay_schedule_id, or one that belongs to another employer, returns 422. #502
  • Breaking GET /team-members now returns XCG in compensation.pay_rate_currency for employers paying in Antillean guilders, where ANG was returned before. Clients that match on ANG must accept XCG. Other currency codes are unchanged. #523

v4.6.0

16 September 2026 3 features 2 bugfixes
  • GET /pay-runs/{pay_run_id}/employees/{employee_id}/wage-codes and GET /pay-runs/{pay_run_id}/employees/{employee_id}/wage-codes/{wage_code_id} are new and expose the wage codes on an employee's payslip in a pay run. The list is paginated and each item carries id, code, description, type, amount, base_amount, is_fixed and is_payout; the single resource adds employer_id, employee_id and pay_run_id. An unknown pay run, employee or wage code returns 404. #508
  • GET /pay-runs/{pay_run_id}/employees and GET /pay-runs/{pay_run_id}/employees/{employee_id} are new. The list returns each employee in the pay run with wage_codes as id and code references only; the single resource returns the full wage code objects and adds employer_id and pay_run_id. employee_id accepts a Celery ID or an ext. external ID, and an unknown pay run or employee returns 404. #507
  • GET /pay-runs and GET /pay-runs/{pay_run_id} are new. The list is paginated, can be filtered with the pay_period_id query parameter and returns pay runs without their employees; the single resource adds employer_id and an employees array of id and full_name references. An unknown pay_run_id returns 404. #506
  • POST /time-off-requests and PUT /time-off-requests/{time_off_request_id} no longer fail with 500 or an unexpected 422 when sent with Accept-Language: nl or Accept-Language: es. Requests in English were not affected. #514
  • GET /wage-codes and GET /pay-schedules are now also available to user contexts with a read-only role. #224

v4.5.0

13 September 2026 Breaking 3 features
  • GET /pay-schedules is new and lists the pay schedules of the employer in X-Celery-Employer-Id. The response is paginated with page and limit and each item carries id, name, period, payday and is_default, so a client can discover valid pay schedules instead of relying on the payment_schedule_id and payment_schedule_name values embedded in other resources. #497
  • GET /wage-codes items now carry an id field holding the wage code's UUID, a stable identifier to reference the wage code with. #492
  • Breaking the response language is now selected with the Accept-Language request header on every endpoint. A ?language= query parameter is still accepted on GET /documents, GET /documents/{document_id} and GET /calendar-events, where it takes precedence over the header, and it now also accepts es; POST /time-off-request-description keeps its required language body field, which now also accepts es. The language is no longer remembered between requests, so a client that wants Dutch (nl) or Spanish (es) responses must send Accept-Language on every request; without it the response is English. #406

v4.4.3

19 August 2026 1 change 1 bugfix
  • A logging improvement for the Dyflexis hours webhook; no change for API clients. #485
  • A reliability improvement in internal error reporting; no change for API clients. #479

v4.4.1

20 July 2026 2 changes 1 bugfix
  • A build tooling update; no change for API clients. #463
  • The Dyflexis hours webhook now imports the received hours directly when that option is enabled for the employer; otherwise it behaves as before. The endpoint URL and its authentication are unchanged. #466
  • A build tooling fix; no change for API clients. #470

v4.4.0

9 July 2026 1 feature 1 change 1 bugfix
  • GET /time-off-requests, GET /time-off-requests/{time_off_request_id}, GET /calendar-events and GET /tasks now include the employee the item is about. TimeOffRequest gains employee with full_name and avatar_url, CalendarEvent gains subject with full_name and avatar_url, and Task gains reference_owner_avatar_url next to the existing owner fields. A client no longer needs GET /team-members to show the name and avatar for these items. #461
  • Additional test coverage for the break_time validation on POST /time-off-requests and PUT /time-off-requests/{time_off_request_id}; no change for API clients. #457
  • POST /time-off-requests and PUT /time-off-requests/{time_off_request_id} now return 422 when break_time in no_work_schedule_days or no_work_schedule_period exceeds 180 minutes, where such values used to fail with 500. The specification documents the maximum of 180 on both fields. #410

v4.3.2

29 June 2026 1 bugfix
  • A deployment tooling update; no change for API clients. #451

v4.3.0

28 June 2026 1 change
  • The API now runs on PHP 8.4. Its changed rounding behaviour can shift a calculated payroll amount by one cent compared to earlier versions. #447

v4.2.0

26 June 2026 1 change
  • The underlying framework was upgraded to a supported major version; no change for API clients. #445

v4.1.1

26 June 2026 6 changes 2 bugfixes
  • A code style tooling update; no change for API clients. #443
  • A build pipeline update; no change for API clients. #435
  • A build pipeline update; no change for API clients. #434
  • GET /employees?status=out_of_service now returns the out-of-service employees instead of an empty list. #429
  • PUT /time-off-requests/{time_off_request_id} no longer sends a status change notification when an employee edits their own request. Notifications for status changes made by managers and HR are unchanged. #420
  • A code maintenance tooling update; no change for API clients. #424
  • A test suite improvement; no change for API clients. #438
  • A code maintenance improvement; no change for API clients. #426

v4.1.0

6 June 2026 Breaking 1 feature 1 bugfix
  • Employee responses now carry nationality_code, the ISO 3166-1 alpha-2 code of the employee's nationality, next to the localised nationality name. POST /employees and PUT /employees/{employee_id} accept nationality_code; when both fields are sent, nationality_code takes precedence, and an unknown code or a nationality name that cannot be resolved returns 422. #417
  • Breaking the Dyflexis hours webhook POST /catch/integrations/dyflexis/hours now requires an Authorization: Bearer <token> header with the token configured for the integration and returns 401 without it. The behaviour after authentication is unchanged. #415

v4.0.14

24 May 2026 Breaking 4 bugfixes
  • The SSO webhook endpoints under /catch/sso now require a signed token and return 401 otherwise. These endpoints are called by the identity provider, not by API integrations. #398
  • Breaking an employee can no longer edit their own time-off request through PUT /time-off-requests/{time_off_request_id} once it has been approved or denied; the call returns 422 with error code 1421. To change an approved request the employee deletes it and submits a new one, as in the web application. #291
  • Breaking PUT /time-off-requests/{time_off_request_id} now returns 422 with an error on status when an employee sends a status they are not allowed to set, where the value used to be ignored with a 200 response. #394
  • DELETE /time-off-requests/{time_off_request_id} by an employee on their own request now notifies the employee's managers and HR managers, as the web application does. Deletions by managers and HR are unchanged. #403

v4.0.12

15 May 2026 1 bugfix
  • When PUT /time-off-requests/{time_off_request_id} closes an open-ended sick leave by setting its end date, managers now receive the "reported better" notification instead of the generic approval notification. #399

v4.0.11

10 May 2026 1 bugfix
  • POST /time-off-request-description with language: es now returns the duration description; it used to fail on Spanish abbreviated month names. #396

v4.0.10

8 May 2026 Breaking 1 bugfix
  • Breaking DELETE /time-off-requests/{time_off_request_id} on an archived, already removed past time-off request now returns 422 with error code 1420 instead of reopening the request. #395

v4.0.9

5 May 2026 1 bugfix
  • External ID mappings are now correctly scoped to the API application that created them, so lookups, uniqueness and conflict checks on /external-id-mappings and on ext. identifiers apply per application. A request whose API application cannot be resolved now returns 401. #390

v4.0.6

27 April 2026 1 change
  • Request logging now records the user context of each call; no change for API clients. #386

v4.0.4

19 April 2026 1 bugfix
  • PUT /employees/{employee_id} now saves date_of_last_working_day; the value used to be ignored and the stored date cleared. #381

v4.0.3

9 April 2026 1 bugfix
  • A build tooling fix; no change for API clients. #377

v4.0.0

6 April 2026 1 feature
  • The API moved to a new version of its database layer. Paginated responses now report a current_page of at least 1. #346