Programme Contracts
Maintain Programme Sectors
/a/ContractProgramme_saveSectors
Create, rename and retire Sector choices without merging retained membership.
When to use this endpoint
Reload bootstrap.sector_settings or the Sectors collection first. Submit the full desired active catalogue with stable IDs and the current revision; omitted active entries are retired.
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. 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
| Parameter | Type | Required | Description |
|---|---|---|---|
revision | Scalar revision | Yes | Must exactly match sector_settings.revision, initially 0. |
entries | Array | Yes, unless sectors supplied | At most 200 ordered {id,name} objects. id=0 creates; existing active ID renames. Nonblank trimmed name max 64 characters. [] retires every active entry. |
sectors | Array of strings | Legacy alternative | Used only when entries is null/omitted. Matches exact active names to preserve IDs; renamed text is treated as a new entry. |
Example request
$result = FM_api('ContractProgramme_saveSectors', [
'data' => json_encode([
'revision' => 0,
'entries' => [
[
'id' => 0,
'name' => 'Parks',
],
],
]),
]);
Example response
{
"ok": 1,
"sector_settings": {
"sectors": [
"Parks"
],
"entries": [
{
"id": 1,
"name": "Parks",
"deleted": 0
}
],
"revision": 1
}
}
Errors and unusual responses
| Response | Condition |
|---|---|
{"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":"Sectors changed. Reopen Sectors before saving."} | Revision missing or stale. |
{"error":"This Sector name belongs to another active or retired Sector. Choose a new name to preserve existing Contract and checklist references."} | A name is reserved by another retained ID. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Names are unique ignoring case across both active and retained retired entries. Swapping names, reusing another retired name or taking a name retired in the same request is rejected. Own-name case changes are accepted.
- Renames preserve stable IDs and update active Contract configuration, Task-template and named-template Sector labels. Job snapshots retain historical wording.
- Retirement removes the new-choice option, retains deleted/ddate metadata and existing Contract/template evidence. An unchanged retired Contract value remains saveable; it cannot be assigned to a new Contract.
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 contract-programme-sectors, advances its revision and audits module_sectors_saved. Retirements append tenant deletion-log records. No Contract or Job is deleted.
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
Open Module Settings → Sectors, create, edit or delete a Sector. Filter for ContractProgramme_saveSectors; each UI action sends the complete remaining catalogue and revision.
Related endpoints
ContractProgramme_saveConfig— Assign an active Sector to a Contract.ContractProgramme_saveChecklistTemplate— Tag a named template with a Sector.ContractProgramme_saveTasks— Maintain the Sector fallback definitions.