When to use this endpoint

Attach a job to a contract or clear its contract association from a focused edit.

Read the target job first with Jobs_getSome to obtain the current values and confirm the IDs belong to the intended account.

Authentication and permissions

Authenticate with signed API-key fields or a logged-in CRM session. The request uses the authenticated account’s job IDs, not mobile app IDs.

The legacy userdata.permissions bit 128 blocks editing with No permission to edit; this handler does not exempt client administrators from that bit. It does not add an assignee/department scope.

Parameters

ParameterTypeRequiredDescription
idInteger stringYesPhysical job ID in the authenticated account, converted with intval; must be positive.
contract_idInteger stringYesContract ID converted to integer; zero detaches. Omitted defaults to -1 and is rejected. Blank/nonnumeric present input coerces to zero.

Example request

$result = FM_api('Job_setContractId', ['id'=>'1042', 'contract_id'=>'302']);

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":"missing or invalid parameter: id"}id is absent or converts to a nonpositive integer.
{"error":"No permission to edit"}The legacy edit restriction bit is set.
{"error":"missing or invalid parameter: contract_id"}The integer contract ID is negative, including omitted input.
{"error":"job does not exist"}No active job row is read, or that read fails.
{"ok":1,"warning":"value already set"}The converted requested ID matches the stored contract and the positive destination is active.
{"error":"Contract does not exist"}The positive destination contract is missing/deleted; the previous association is preserved.
{"error":"Unable to save contract"}A transactional read, write or commit failed; the association is rolled back.

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

Behaviour and edge cases

  • Locks the active job and old/new contract rows in a tenant transaction. A positive destination must exist and be active, including when the requested contract ID equals the saved ID.
  • Compares the converted integer contract IDs. An unchanged valid association returns a no-change warning without writes.
  • Changed assignments replace all type-6 job/contract relationships; zero detaches. The job column, relationship writes and old/new contract customer-cache dirty markers commit together. Any checked read/write or transaction failure rolls back.
  • This is not a contract create or customer change. It does not mirror to an outsourced job.

Side effects

  • Updates the job’s last_edited/edited_uuid and invalidates the meetings cache.
  • Records job history and contract add/remove history for the changed association.
  • Flags both the previous and destination contract’s customer caches dirty when their rows exist, including a move between two positive contract IDs. No mail is sent.

See it in Fieldmotion

CRM1

Open a job’s Main page, click its Contract field and select a contract or blank entry. pageJob.js sends Job_setContractId; inspect that request in Network.

CRM2

No direct CRM2 caller was found in the canonical/legacy route search. CRM2’s layout-driven updates are a separate contract.

Related endpoints

  • Contracts_list supplies selectable contracts.
  • Jobs_getSome reads selected job records before editing and verifies the stored result afterward.