When to use this endpoint

Save revised editor defaults to an existing template. This is a whole-payload replacement, not a JSON merge, rename or type change. Read the current preset first if values not present in the editor must be retained.

Authentication and permissions

Authenticate with signed API-key fields or a logged-in CRM session. Template_get, Template_new, Template_setObj and Templates_get require an authenticated tenant context; Template_delete and both table handlers also call the login guard. There is no handler-level administrator, page, role, creator or ownership check.

Templates are shared within the authenticated tenant, not private to created_by. There is no user, department, feature-setting or active/deleted filter. The dispatcher also applies its normal account, authentication and team-access checks; the shared table predicate adds no template-specific row restriction.

Parameters

ParameterTypeRequiredDescription
idIntegerYesInteger-converted positive template ID. No type or creator match is enforced.
objJSON textYesTrimmed nonblank payload string; JSON-encode before signing. JSON syntax is checked, but no object schema is enforced. Omitted/null/non-string/blank/malformed JSON fails.

Example request

$result = FM_api('Template_setObj', [
	'id' => '1042',
	'obj' => json_encode(['notes' => 'Revised quote notes']),
]);

Example response

{"ok":1}

If the stored obj string strictly equals the trimmed input, returns {"ok":1,"msg":"no updated needed"} with that exact legacy spelling. Equivalent JSON with different whitespace/key order is not a no-op by this comparison.

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"}Integer-converted id is below 1.
{"error":"missing or invalid parameter: obj"}Missing, non-string, blank or malformed JSON payload.
{"error":"Unable to update template"}The UPDATE fails or throws.
{"error":"template does not exist"}ID lookup yields no row; a failed lookup is not distinguished from absence.

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

Behaviour and edge cases

  • Replaces obj and sets last_edited to current Unix seconds only on the non-no-op path. Name, type, cdate and created_by remain unchanged.
  • There is no optimistic concurrency token, version check, merge, ownership restriction or propagation to documents already created from this preset. Last writer wins.
  • No direct mobile-app or m-service caller for this template family was found in the source search. The CRM2 widget’s payload is client-defined; storing it does not validate that another document endpoint will accept every field.

Side effects

  • Updates one tenant template. No explicit history/audit entry, event, notification, provider call or cache-invalidation option is invoked.

See it in Fieldmotion

CRM1

In CRM1, open a job’s recurrence editor and use Save as Template; filter browser requests for Template_new or Template_setObj. The editor lists type 1 templates through Templates_get and removes job-specific values before saving. CRM2’s recurrence editor uses the same type-1 workflow.

CRM2

CRM2’s widgetTemplate.js loads Templates_get with JSON-encoded id/name/obj fields, parses obj locally, and uses Template_new, Template_setObj and Template_delete from its save/trash controls. Observe these requests in a create dialog whose configured layout includes the Template widget, such as a quote or invoice. The widget is layout-dependent, not present on every screen.

Related endpoints