Jobs: recurrence workflows and lists
Discover recurrence export IDs, then fetch aliased fields for a selected batch
/a/JobRecurrences_getExportData
Discover recurrence export IDs, then fetch aliased fields for a selected batch.
When to use this endpoint
Use the two-phase export contract: _ids=1 returns matching IDs, then _ids as JSON text plus fields as JSON text returns data. The endpoint returns JSON, not a CSV download; browser exporters resolve identities and format cells.
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 |
|---|---|---|---|
_ids | String | Yes | Literal 1 selects ID discovery. Otherwise a nonempty JSON array of recurrence IDs; values are intval-coerced. A native array is not decoded by this handler. |
fields | JSON string | Data phase | Nonempty array of allowed export field names below. Native arrays not supported. id always returned and field positions determine fN aliases. |
customer_id, customer_type | Integer-like scalars | Discovery only | Nonzero customer_id plus customer_type (default0) exact target; otherwise nonzero customer_type can filter all assets. No parent/subsidiary expansion. |
expiryFrom, expiryTo, non_expiring | Date strings, literal true string | Discovery only | expiryFrom activates inclusive expiry range; expiryTo defaults to server today with 23:59:59 appended. non_expiring="true" also includes NULL or expiry containing 0000, not the special 2999 sentinel. |
name, notes | Strings | Discovery only | Scalar lowercase substring filters; quoted input is searched as data using SQL-mode-independent text literals. |
recurringID | Integer-like scalar | Discovery only | Nonblank exact recurrence ID. |
users, formIDs, department_id | Native integer arrays | Discovery only | Nonempty lists produce exact IN conditions. Strict integer-token sanitization rejects invalid members; department_id here is an array, unlike the CRM1 table scalar. |
referenceDateField, dateFromFilter, dateToFilter, isDateUnix | String, integer offsets, flag | Discovery only | Both day offsets plus a nonblank reference field required. Allowed fields cdate, edate, last_edited; inclusive server-date day bounds. isDateUnix wraps the chosen column in FROM_UNIXTIME, even though these recurrence columns store SQL dates. Leave it off for normal rows. |
contractsFilter | Native integer array | Discovery only | Native sanitized integer list of contract IDs. Non-deleted linked jobs are matched against complete cached CSV IDs; no jobs forces no matches. |
withExpiryDate, isCompleted, isActive | Native single-element arrays | Discovery only | Expiry presence: [1] NOT NULL, [0] NULL. Completion: [1] expiry on/before today, otherwise after today; NULL excluded. Active: [1] active=1, otherwise active=0. Other array sizes skip each filter. |
jobType | Native integer array | Discovery only | Nonempty job-type IDs match stored job-type metadata. |
invoiceID | Integer-like scalar | Discovery only | Nonblank linked invoice recurrence ID. |
Example request
$ids = FM_api('JobRecurrences_getExportData', ['_ids'=>'1', 'isActive'=>['1']]);
// Decode ids, then fetch a bounded batch:
$rows = FM_api('JobRecurrences_getExportData', ['_ids'=>'[1042]', 'fields'=>'["name","frequency","completed","customer_id|customer_type"]']);
Example response
[{"id":"1042","f0":"Monthly checks","f1":"every 2 weeks","f2":"does not expire","f3_0":"101","f3_1":"0","edate":null,"on_arr":"2","every":"4"}]
Discovery response is {"ids":["1042",...]} with no count or paging. Data response is a bare array and can append dependency columns edate, on_arr and every when requested computed fields need them.
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: _ids"} | Missing/falsy selector, checked before login. |
{"error":"_ids should be a JSON array of numbers"} | Data selector decodes to empty/non-array/falsy value. |
{"error":"fields should be an array of requested field names"} | Fields decode to empty/non-array/falsy value. |
{"error":"unknown field name: bad"} | Unrecognized export field; name varies. |
{"error":"invalid users"} | A sanitized native integer list contains invalid members; label varies. |
{"error":"invalid referenceDateField: bad"} | Date reference not allowlisted; echoed value varies. |
{"error":"error in database query"} | Discovery or data-phase query failed; generated SQL is not returned. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Allowed export fields: id, customer_id|customer_type, user_id, name, edate, notes, recurrences, frequency, files, customer_type, completed, active, department_id.
- Every field gets fN in request order. customer_id|customer_type produces fN_0 and fN_1. Fields containing a colon are skipped but keep their original index gap. id is also always a separate output key.
- recurrences is the cached job-ID CSV, not a count. Notes/files remain stored strings, not formatted export cells.
- frequency: NULL mode=weekly; 0=daily, 1=monthly, 2=yearly, 3–6=every N days/weeks/months/years using intval(on_arr). These are labels, not a full explanation of selected calendar days.
- completed is expiry-derived: null/blank/zero date means "does not expire"; expiry <= server today means "complete"; later means "completes on DATE". Discovery isCompleted now uses the same inclusive today boundary.
- Discovery filters are ignored in the data phase. Explicit selected IDs are read directly without active/deleted, department/account-manager visibility or parent-scope filters. No pagination, maximum batch size or defined order.
- Contract discovery matches complete positive CSV IDs, including leading zeroes/whitespace, and excludes deleted linked jobs. No jobs for the selected contracts means no results, including legacy NULL caches.
- Name/notes filters treat quoted text as data, not SQL. Scalar/list controls and requested field names are validated; database-query errors do not expose generated SQL.
Side effects
- Closes the session write lock; otherwise read-only. Does not create files, send messages, repair caches, reconcile dates or change scheduler registration.
See it in Fieldmotion
CRM1
Jobs → Recurring Jobs or a customer’s Recurring Jobs → Export. pageJobsRecurring/pageCustomerJobsRecurring configure widgetExport with this function; widgetExport performs the ID/field requests and builds CSV.
CRM2
Recurring Jobs → Export. moduleRecurring first uses the mapped table to discover visible IDs, then widgetExportCRM2 calls this endpoint for export data. The endpoint itself does not repeat the table’s visibility controls.
Related endpoints
JobRecurrences_getDataTablediscovers IDs with CRM2 screen visibility filters.JobRecurrences_listis a different JSON-string field list without fN aliases.