When to use this endpoint

Read ContractProgramme_contract first and send its configuration revision and only the raw choices being edited. Use config.form_overrides when editing inherited Forms; effective IDs would freeze inheritance.

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.

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
contract_idPositive integer or digit stringYesLocal, non-deleted Contract with an accessible Programme configuration.
revisionInteger-compatibleNoWhen supplied must match current config revision; omit only with deliberate lost-update risk.
sectorStringNoExact configured name or blank, max 64 characters; an unchanged retired value remains accepted.
service_form_id, qi_form_idInteger-compatibleNoZero inherits module defaults. Nonzero choices must resolve to an unarchived Job Form (type=0). Omitted fields retain the current override.
qi_field_idStringNoMax 64 characters; existing choice/contract-grade field identity. Blank inherits only when effective QI Form matches the module QI Form.
grading_set_idInteger-compatibleNoZero clears; nonzero must be an active non-deleted set. QI field/Form/set changes require contractProgrammeQI.
area_field_id, duration_field_idStringsNoExisting Site custom field names from bootstrap.site_fields, or blank; max 64 characters.
default_durationPositive integer or digit stringNo1–1440 minutes; omitted retains current configuration.
portal_qi, portal_progress0/1 or booleanNoContract-level Portal view switches; changing either requires contractProgrammePortal.
checklist_template_idInteger-compatibleNoNamed template ID; 0 explicitly disables checklists. Omitted preserves selection or legacy fallback.

Example request

$result = FM_api('ContractProgramme_saveConfig', [
	'data' => json_encode([
		'contract_id' => 210,
		'revision' => 1,
		'service_form_id' => 301,
		'default_duration' => 60,
	]),
]);

Example response

{
  "ok": 1
}

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":"Contract settings changed. Reload before saving."}Supplied config revision is stale.
{"error":"Choose an existing QI choice field"}Effective QI field does not match the Form.
{"error":"Choose an existing Site custom field"}Area/duration field is not in the Site catalogue.

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

Behaviour and edge cases

  • Only a client administrator may initialize a missing configuration for an existing non-deleted Contract. Existing configurations require Contract scope. The save increments revision even if values are unchanged.
  • manager_id and area_id are not writable through this operation. It changes operational settings only.
  • The resolved Form combination is validated even for unrelated changes. Zero Form overrides inherit dynamically; a blank QI field never borrows from another QI Form.
  • Selecting a checklist refreshes only incomplete Jobs with no saved checklist answers. Answered/completed snapshots are retained.

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.
  • Audits contract_settings_saved; checklist changes update Contract metadata and eligible Job snapshots/sync timestamps. Published inspection grade snapshots are preserved.

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 a Programme Contract → Contract Settings, edit the choices and Save; filter for ContractProgramme_saveConfig. Checklist Apply Template and QI Apply Set also use this route.

Related endpoints