Jobs: recurrence workflows and lists
Save checked recurrence frequency/copy settings and reconcile future-job generation
/a/JobRecurrence_set
Save checked recurrence frequency/copy settings and reconcile future-job generation.
When to use this endpoint
Save checked recurrence frequency/copy settings and reconcile future-job generation.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session and tenant context. Job edit-restriction bit 128 applies, with the existing client-administrator exception. There is no additional recurrence-owner or department-visibility filter.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | Canonical positive integer string | Yes | Existing recurrence ID; strict integer validation after the legacy missing-ID check. |
active, copy_cust_ref, copy_user, skip_weekends | 0/1 integer strings | No | Blank strings normalize to 0 in this batch route. Omitted settings remain unchanged. |
copy_job_ref | -1/0/1 integer string | No | -1 stores NULL; blank normalizes to 0. |
every | 0–6 integer string | No | 0=weekday selection, 1=day-of-month selection, 2=day-of-year selection, 3/4/5/6=every N days/weeks/months/years. Blank normalizes to 0. |
on_arr | CSV or JSON-array string | No | Nonempty selected indices: mode 0=0–6, mode 1=0–30, mode 2=0–364; modes 3–6 require exactly one positive interval. Validated against supplied every or the stored value. Native arrays rejected. |
edate | YYYY-MM-DD or blank string | No | Expiry date; blank/exact zero-date sentinels clear to NULL. Strict calendar validation. This is not the create parameter expiry_date. |
copy_job_value | 0/1 integer string | No | Metadata flag; empty string is not normalized. |
due_date_offset | Nonnegative integer string | No | Metadata offset; no empty-string normalization. |
skip-run | Truthy flag | No | Suppresses this batch’s global registration/reminder reconciliation and priority bump. Does not suppress checked local writes or child cleanup. |
Example request
$result = FM_api('JobRecurrence_set', ['id'=>'1042', 'every'=>'4', 'on_arr'=>'2', 'copy_job_value'=>'1', 'due_date_offset'=>'0']);
Example response
{"ok":1}
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":"invalid or missing parameter: id"} | ID absent/nonpositive in initial guard. |
{"error":"missing or invalid parameter: every"} | Strict integer/range validation failed; parameter label varies. |
{"error":"missing or invalid parameter: val"} | Malformed expiry date, via shared date validator. |
{"error":"nothing to edit"} | No supported setting supplied. |
{"error":"job recurrence 1042 does not exist"} | No matching row; numeric ID varies. |
{"error":"Invalid saved recurrence metadata"} | Stored metadata cannot be decoded as array/object. |
{"error":"No permission to edit"} | Job edit restriction applies. |
{"error":"Unable to save job delivery changes"} | Local checked save/history failed. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- This is one sequence per request, not a multi-ID save. At least one supported setting is required; name, notes, schedule, user, form, department, loop and copy-form flags are not accepted configuration keys here.
- Locks the row, decodes stored metadata, validates inputs and commits changed columns/history atomically. Unchanged values skip local writes/history but can still reconcile global registration when skip-run is false.
- Actual changes to generation settings trigger from-now cleanup. If only expiry changes to a non-null date, cleanup retains that entire tenant-local day; clearing expiry alone does not remove jobs. The first valid cached anchor and completed/overdue jobs remain.
- Changing every without on_arr validates the supplied mode but does not cross-validate the old selector against the new mode. Supply both together when changing frequency.
- After local save, cleanup and global scheduler/reminder reconciliation can fail independently. Returns ok=1, saved=1, warning/warnings and sometimes cleanup details for committed saves; this is not a rollback response.
- For active sequences, default reconciliation replaces the global registration with current recurrence-days, aligns expiry and backdates last_run. Inactive sequences lose registration. Type-7 expiry reminders are rebuilt using tenant-local midnight and the configured notification lead days.
- Mobile clients were checked separately: recurrence notes/files are synchronized through m/www syncDownloads/syncDownloadOne and notes uploads, not direct calls to this endpoint. Those intermediary contracts are not expanded by this API route.
Side effects
- Writes settings, last_edited, operation marker and per-change history in a checked tenant transaction. Metadata updates preserve other decoded keys.
- Runs canonical future-child cleanup after commit. Global registration/reminder work uses a separate checked global transaction. A worker may regenerate children later; no synchronous generation here.
See it in Fieldmotion
CRM1
Jobs → Recurring Jobs → Change Frequency, including bulk selection. pageJobsRecurring submits configuration to JobRecurrence_set one ID at a time.
CRM2
Recurring Jobs → bulk Change Frequency. moduleRecurring serially sends one JobRecurrence_set request for each selected ID; inspect warnings as well as errors.
Related endpoints
JobRecurrence_deleteFromDatedefines cleanup cutoffs and anchor retention.JobRecurrence_setSchedulevalidates the generation override map.