When to use this endpoint

Use Customer_setContacts only when the calling system owns the complete stored contacts value and intends to replace it.

The endpoint does not merge individual contacts or validate JSON. Read the current value first if preservation of unknown entries matters.

Authentication and permissions

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

The lookup and any write use the authenticated tenant; an ID from another tenant cannot be addressed through this call.

Parameters

ParameterTypeRequiredDescription
idInteger stringYesCustomer to update; it must convert to a positive integer.
valStringYesComplete replacement payload. It is stored verbatim; blank clears it. JSON syntax and shape are not checked.

Example request

$result = FM_api('Customer_setContacts', [
	'id' => '1088',
	'val' => json_encode([
		['name' => 'Alex Morgan', 'email' => 'alex@example.test'],
	]),
]);

Example response

{
  "ok": 1
}

A payload considered equal by the legacy loose comparison returns {"ok":1,"msg":"no change needed"}.

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 invalid.
{"error":"missing or invalid parameter: val"}val was omitted.
{"error":"customer does not exist"}No matching customer row exists.

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 lookup does not filter by active or deleted state.
  • The endpoint performs no decoding, schema validation, merging, or length check.
  • The no-change check uses loose comparison; a request it considers equal returns before any write or side effect.
  • This is a single-record mutation; it provides no list filtering or pagination.

Side effects

  • A real change updates contacts, last_edited, and edited_uuid.
  • It writes a customer audit-log entry and fires Customer_edit, but does not explicitly invalidate the customer cache.

See it in Fieldmotion

CRM1

No direct production CRM1 caller was found. Current CRM1 focused edits use the primary contact-name setter rather than this opaque contacts payload.

CRM2

No direct production CRM2 caller was found. CRM2 customer forms use the layout-driven update contract.

Related endpoints