Jobs: recurrence workflows and lists
Create the configuration for a recurring-job sequence, initially without an example job
/a/JobRecurrence_create
Create the configuration for a recurring-job sequence, initially without an example job.
When to use this endpoint
Use when a job or asset-maintenance workflow needs a new recurring sequence. Normal job creation/save establishes the example job afterward; this standalone endpoint creates configuration only.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. All records resolve in the authenticated tenant. This handler has no additional Job edit-bit, department-visibility or owner check.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | String | No | Defaults to "no name". At most 255 characters by Core_maxLengthError; blank is allowed. |
active | Integer-like scalar | No | intval; default 0. This create path does not restrict it to 0/1. |
schedule | JSON string | No | Default {}. Decoded with associative arrays and re-encoded with JSON_FORCE_OBJECT, including nested arrays. Falsy decoded input becomes an empty object. No focused-setter schedule validation. |
copy_user, copy_cust_ref, copy_job_ref | Integer strings | No | Omitted/blank values use database defaults (normally null). Loose integer validation; no boolean range check and no -1-to-null translation. |
every, customer_id, customer_type, skip_weekends | Integer strings | No | Loose integer validation without range or referenced-record validation. Omitted values use schema defaults; every normally null, others 0. Customer type 0 is customer, 1 is asset in consumers. |
on_arr | String | No | Stored verbatim; not validated against every. Use the frequency formats documented by JobRecurrence_set. |
custom | JSON text | No | Trimmed and stored only if longer than two bytes. Invalid JSON can fail database persistence. |
copy_job_value | Scalar | No | Metadata value, default integer 1. Supplied value is retained, not normalized to boolean. |
due_date_offset | Integer-like scalar | No | Metadata offset, intval; default 0, negative values are not rejected here. |
loop_recurrence, copy_form_values | Integer-like scalars | No | Default 0; copied into metadata only when isCRM2 is supplied and loosely true. |
isCRM2 | Scalar flag | No | Truthy value enables the newer metadata flags. Presence alone, even a false value, changes the expiry-notification branch. |
expiry_date | Date string | No | Stored as edate when truthy and not exactly 0000-00-00; otherwise null. This path does not validate calendar dates. |
notes | String | No | Passed to the checked notes setter after insertion; plain text becomes a content entry, JSON arrays are retained. |
Example request
$result = FM_api('JobRecurrence_create', ['name'=>'Monthly checks', 'active'=>'0', 'schedule'=>'{}']);
Example response
{
"id": "1042",
"name": "Monthly checks",
"ids": "",
"cdate": "2026-10-15",
"edate": null,
"active": "0",
"every": null,
"on_arr": null,
"customer_id": "0",
"customer_type": "0",
"next_date": null,
"user_id": "0",
"notes": null,
"files": null,
"edited_uuid": "JobRecurrence_create",
"last_edited": "2026-10-15 10:00:00",
"days_in_advance": "30",
"copy_user": null,
"copy_cust_ref": null,
"department_id": "0",
"form_id": "0",
"schedule": "{}",
"meta": "{\"copy_job_value\":1,\"due_date_offset\":0}",
"custom": null,
"copy_job_ref": null,
"created_by": "92442",
"skip_weekends": "0"
}
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":"parameter too long: name. max length 255 characters"} | Name exceeds the character limit. |
{"error":"Job Recurrence field \"every\" should be an integer","errors":[{"msg":"Job Recurrence field \"every\" should be an integer","val":"x"}]} | A validated integer field fails the legacy integer check; field/value vary. |
{"error":"could not create job recurrence"} | Insert does not return a positive ID. Later follow-up failures need not become this error. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Creating configuration alone does not create or attach an example job. Normal job creation/save and asset-maintenance creation call this internally, then establish job linkage.
- The complete stored row is returned, not just its ID. Database numeric fields are normally strings; notes, schedule, meta and custom remain JSON-encoded strings. The example uses a 30-day tenant generation horizon; the actual value comes from recurrence-days.
- created_by is the session parent account ID rather than necessarily the acting sub-user. cdate is a date column, so its inserted datetime loses the time.
- This is not the strict configuration setter: integer ranges, target existence, frequency and schedule consistency are not checked. User/form/department/ids/next_date supplied directly are not creation inputs.
- 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
- Inserts a tenant recurrence and a global worker registration with last-job ID 0, current last-job date and recurrence-days; registration is attempted even for inactive configurations. It does not run generation synchronously.
- Optional notes invoke the checked notes setter and history. Its result is ignored by create; the returned row is read afterward. The tenant insert is checked, but notes, registration and notification steps are not one distributed transaction.
- With expiry and no isCRM2 parameter, creates a type-7 reminder using strtotime(expiry_date) minus the notification_types.job_recurrence_expires_soon.num lead days. With isCRM2 present, calls the mapped create notification instead.
- For crmVersion=2, sends mention notices using mapped request values; the newly inserted ID is not injected into that request, so the notice link can contain 0.
See it in Fieldmotion
CRM1
Create or edit a job and configure recurrence, or create asset maintenance. Inspect Job_new / Job_save / AssetMaintenance_create: the recurrence create call is internal, not necessarily a separate Network request.
CRM2
Configure recurrence in the job editor and inspect Job_save, which calls this internally. Newer flags depend on isCRM2 carried into the recurrence payload.
Related endpoints
JobRecurrence_setvalidates frequency changes on an existing sequence.