When to use this endpoint

Read the full notes list, make the desired add/edit/remove change locally, then send the whole list. This is not an append-only note operation.

The notes widget supplies content plus optional author/time metadata; the handler only uses content when deciding whether to persist an edit.

Authentication and permissions

Authenticate with signed API-key fields or a logged-in CRM session. The handler performs no additional page or role-permission check.

Job and form IDs refer to the authenticated account. Cross-account writes occur only through the stored outsourcing relationship on the routes that explicitly mirror changes.

The dispatcher also applies account/user and IP restrictions. A CRM session carrying a CSRF token must supply it through X-FMCSRF or _csrf; missing/incorrect tokens can be rejected before this handler runs.

Parameters

ParameterTypeRequiredDescription
idInteger stringYesPositive physical job ID.
valueJSON array stringYesEntire notes list, at least two bytes and decoding to an array. Each note should contain content. [] clears the list; plain note text is rejected. CRM1 also supplies createdby and noteTime, which are stored without validation.

Example request

$result = FM_api('Job_setNotes', [
	'id'=>'1042', 'value'=>json_encode([['content'=>'Access arranged with site manager.']]),
]);

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"}Nonpositive job ID.
{"error":"missing or invalid parameter: value"}Input string is shorter than two bytes.
{"error":"invalid parameter: value"}JSON does not decode to an array.
{"error":"appointment does not exist"}No active job is read; this exact legacy error is retained.
{"error":"Unable to save job"}The primary database save failed. Successful-save history and subsequent follow-ups are not run.
{"ok":1,"warning":"Job saved; follow-up incomplete. Inspect saved state before retrying.","warnings":["Job_emailChangeNotes: Unable to queue job notes notification"],"saved":1}The primary save succeeded, but a recalculation, asset rebuild, notification or outsourced mirror failed. warnings identifies the failed follow-up; any normal response fields remain present. A benign no-change result from a follow-up is not a failure. Read saved state before retrying.

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

Behaviour and edge cases

  • The active job is read and updated; all stored notes are replaced on a meaningful change. Note objects/author/time fields are not individually validated.
  • Compares the complete decoded notes collection, preserving author/time-only changes and changes to row boundaries. JSON whitespace-only formatting changes are a no-op and return ok; PHP strict array comparison remains sensitive to property order and scalar types.
  • No conflict/version token or append semantics exist. Concurrent clients sending whole lists can erase each other’s notes. Malformed note rows can produce warnings rather than a structured error.

Side effects

  • For a detected change, performs a checked active-job notes/timestamp/edit-marker UPDATE, invalidates meetings cache and logs job history after the save succeeds.
  • Calls Job_emailChangeNotes. notification_types.job_on_change_notes must be enabled; its customer/user/creator/other-recipient choices and template/text settings control queued email. Asset jobs resolve customer recipients via owner_id; location jobs do not have equivalent resolution here.
  • Form-based template selection uses the first numeric form-ID match for this job; unmatched jobs use the configured default template. Notification failures produce saved-state warnings after the notes save.
  • Mirrors the notes list and edit timestamps only to an active outsourced counterpart; a missing/deleted counterpart or failed mirror produces a saved-state warning. Local write, mail and mirror are not transactional.

See it in Fieldmotion

CRM1

Open a job’s Main page Notes panel and add/edit/remove a note. pageJob.js sends the widget’s entire serialized list as value. The job report also sends whole lists when adding/removing notes.

CRM2

No direct canonical or legacy Job_setNotes caller was found in CRM2’s source. Do not equate its layout-widget updates with this content-only comparison contract.

Related endpoints

  • Job_setMetaVal writes one low-level metadata property without typed workflow side effects.
  • Jobs_getSome reads selected jobs and their stored notes before replacing a complete list.