When to use this endpoint

Maintain the date-based calendar before previewing work. To change a holiday’s date, retire the old date and save the new one; lookup identity is the date, not a submitted row ID.

Send operation fields inside one JSON-encoded data object. When data is present it replaces top-level operation fields; otherwise the handler accepts the top-level request. String data is limited to 2 MB. Reserved transport/internal keys are removed. Malformed or non-array JSON becomes an empty input, so validate JSON before sending.

Authentication and permissions

Authenticate with a signed API key or logged-in CRM session; session requests follow dispatcher CSRF checks. API-key requests use the key owner’s identity and permissions.

Requires the Contracts entitlement (features & 64), features2.contractProgrammes and Contracts View. Also requires features2.contractProgrammePublishing. Requires Contracts Edit.

All storage belongs to the authenticated tenant. Contract operations follow the actor’s recursive HR manager/team scope, or the configured TeamAccess Contract/Department policy. Client administrators have broad Contract scope; private Programme and route ownership still applies. Active assignees must be within the permitted team.

Only a client administrator may perform this operation, in addition to the permissions above.

The tenant must have the Programme storage upgrade (foundation 803; independent route ownership 804 before planning). Requests never create or repair tables. A missing/incompatible storage failure can return an initialization/storage error or Contracts operation failed. Check the saved state before retrying.

Parameters

ParameterTypeRequiredDescription
dateYYYY-MM-DDYesReal calendar date; existing row is located even if deleted.
nameStringYesNonblank trimmed label, max 128 characters, also required when deleting.
deleted0/1 or booleanNoDefaults to 0 (active/reactivates existing row); 1 retires with ddate.

Example request

$result = FM_api('ContractProgramme_saveHoliday', [
	'data' => json_encode([
		'date' => '2026-12-25',
		'name' => 'Christmas Day',
		'deleted' => 0,
	]),
]);

Example response

{
  "ok": 1,
  "id": 1010
}

Errors and unusual responses

ResponseCondition
{"error":"not logged in"}No authenticated tenant context is available. Invalid signed credentials can be rejected by the dispatcher before the handler runs.
{"error":"Programme Contracts is not enabled"}Workspace flag or Contracts entitlement is disabled.
{"error":"Permission denied"}Contracts View or the required action permission is unavailable.
{"error":"This Contracts capability is not enabled"}The operation’s additional feature flag is disabled.
{"error":"Invalid date"}Missing date or not an exact real YYYY-MM-DD date.
{"error":"Client administrator access is required"}Actor is not a client administrator.

Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.

Behaviour and edge cases

  • Upserts by date. Omitted deleted reactivates a retained holiday and clears ddate. Deleting an unknown date creates a retained deleted row.
  • No request_key or revision is required; repeat deletes can append another deletion audit. Already published dates are unchanged.
  • The holiday label has no effect on scheduling: preview uses only active date values.

Side effects

  • The service serializes writes on the tenant owner in a transaction. Validation, persistence, audit or TeamAccess outstanding-Job access failures roll back that transaction. Successful changed writes refresh linked Contract/Customer sync timestamps and shared mobile update markers, then invalidate CRM caches after success. These operations do not create schema or enable account features.
  • Writes/reactivates the date row and holiday_saved audit. deleted=1 appends a contract_programme_holidays deletion-log record.

See it in Fieldmotion

CRM1

No direct caller was found in CRM1 source. This workflow is implemented by the opted-in CRM2 Programme Contracts workspace.

CRM2

No direct saveHoliday caller was found in CRM2/CRM1 source. Calendar maintenance is an administrator API action; observe its effect using Publish Jobs → Preview.

Related endpoints