Reusable document and recurrence templates
Replace a reusable template payload
/a/Template_setObj
Replace the payload of an existing reusable preset
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
| Parameter | Type | Required | Description |
|---|---|---|---|
id | Integer | Yes | Integer-converted positive template ID. No type or creator match is enforced. |
obj | JSON text | Yes | Trimmed 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
| Response | Condition |
|---|---|
{"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
- Templates_get supplies the selectable presets for one type.
- Template_get reads one stored preset without applying it.
- Template_new creates a separate preset; Template_setObj replaces an existing preset’s payload.
- Template_delete removes the reusable preset, not documents previously created from it.