User accounts and profiles
Query the mapped Users table
/a/Users_getDataTable
Read named User fields and optional area, skill, GPS and Job-allocation enrichment.
When to use this endpoint
Use for CRM2 Users lists, export-selection and restricted list pickers. This shares DataProcessClass with other mapped table APIs, but has User-specific filters and post-processing.
Send a native fields list. The helper that recognizes picker fields can parse JSON text, but the actual table/enrichment pipeline still expects an array.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. Session requests use the dispatcher’s CSRF protection when configured.
Configured TeamAccess row scope is applied in the queries. Ordinary collection requests do not need artificial record IDs. Explicit IDs still pass dispatcher record authorization; unavailable IDs can be rejected there rather than silently omitted.
Users View is required, with strict role checks. The bounded CRM2 listPicker exception permits only its declared picker fields; roleCheck never bypasses authorization.
Financial fields require client administrator, explicit Users Edit, or the legacy Salaries permission (general permission bit value 8). Unauthorised list projections omit those fields; explicitly requested table/export financial fields return a permission error.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
fields | Native or JSON string list | Yes | Flat native/JSON list of User map names, e.g. id,name,email,active,departments,roleID,workerID,costPerHour,pricePerHour,hoursPerWeek,workLocationId. Extra enrichment selectors are area,skill,allocatedToJob. id is always added. Unknown names are skipped; credentials are rejected and financial fields require authority. |
isTable | Integer flag | No | Default table mode. Exactly 0 returns data without draw/counts and ignores table pagination; optional positive limit then caps it. |
start / length | Integer strings | No | Nonnegative offset and length from 1 to 10000; defaults 0/10. |
draw | Integer string | No | Default 0 response sequence in table mode. |
limit | Integer string | No | Nonnegative integer, default 0. Positive cap applies only in non-table mode; zero adds no cap. |
orderBy / orderDesc | Mapped field / SQL direction | No | In table mode, supplied together select a mapped order field (case-insensitive fallback). Direction must be asc or desc; other values return an error. |
order | Native nested array | No | Fallback table sort. Nonnegative order[0][column] is offset by minus one for the checkbox column, then resolved against requested fields. Direction must be asc or desc. |
searchField / searchValue | String or field list / string | No | Shared search defaults to All fields. User-specific scalar searchField roleID/departments/skills resolves names first; active accepts active/archived labels. Those special branches consume the search fields. |
department / departments | Scalar ID / native ID list | No | Special membership regex filter; department takes precedence. Default department filtering can replace these with the non-admin’s own departments, or restrict to self when none. |
skills | Native or JSON ID list | No | Flat native/JSON positive-ID list. A nonempty list selects users having any selected skill; [] leaves this filter unset. |
hasFiles | Native flag list | No | Exactly [0] means has type-4 file; [1] means no such file; both/multiple/empty apply no file filter. File deleted status is not checked. |
Mapped User field filters | Scalars or native arrays | No | Mapped names such as id,active,roleID,nonLogin may also be filters. Scalar quoted fields use contains matching; scalar integer fields use equality; lists use IN. This is distinct from fields projection. |
referenceDate / dateFrom / dateTo | Mapped date field / integer day offsets | No | When referenceDate resolves to a mapped field and both bounds are present, dateFrom/dateTo are integer-converted relative days from account-local today. Datetime bounds expand to 00:00:00 and 23:59:59, inclusive. ISO date strings are not parsed as literal date bounds by this path. |
timeRangeFrom / timeRangeTo | Integer hours | No | Integer hours 0–23. Shared reference-date filtering activates when timeRangeFrom is present; timeRangeTo alone remains ignored. Defaults 0/23; reversed bounds are swapped. Uses the configured timezone or Europe/London fallback, without an overnight wrap. |
offsetFrom / offsetTo | Native hour/minute objects | No | Optional hour/minute components for datetime bounds: hour is negated, minute is added. Pure date fields omit these time components. Account-local today is derived first; later date arithmetic uses the restored PHP timezone. |
groupBy / advanceSearch | Native structures | No | groupBy is a flat mapped-field list. advanceSearch is a native list using column (or mapped id), condition, value and optional andOr for the next entry. Conditions: equal, contains, notEqual, greaterThan, greaterThanOrEqual, lesserThan, lesserThanOrEqual; connectors AND/OR. Raw where SQL, malformed entries and nested values are rejected. Grouped results retain ungrouped counts. |
listPicker | Integer flag | No | CRM2-only constrained read exception when Users View is denied. Requires 1 and a nonempty requested field set wholly within id,name,departments,roleID,email,allocatedToJob,area,skill,costPerHour. It is not general permission to read profiles. |
roleCheck | Integer legacy control | No | Ignored compatibility control. It never bypasses Users View or financial authorization. |
jobAssigneeContract | Legacy presence control | No | For scoped callers, a nonnegative Contract ID narrows to eligible field-team assignees and removes conflicting explicit department filters. Zero uses the general eligible field team. A missing/inaccessible Contract yields no candidates. |
Example request
$result = FM_api('Users_getDataTable', [
'fields'=>['id', 'name', 'active', 'departments'],
'draw'=>'1',
'start'=>'0',
'length'=>'10',
]);
Example response
{
"data": [
{
"id": "1042",
"name": "Alex Morgan",
"active": "1",
"departments": [
"18"
]
}
],
"draw": 1,
"recordsTotal": "1",
"recordsFiltered": "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": "permission denied"} | Users View fails and the constrained picker exception does not apply. |
{"error": "missing or invalid parameter: fields"} | fields absent/null. |
{"error": "error in database query"} | The shared data query fails. |
{"error":"invalid parameter: example"} | A supplied native control is malformed; the response names that control. Lists must be flat, and numeric IDs must be positive integers unless the parameter explicitly permits zero. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Strict Users View applies unless the constrained CRM2 listPicker exception matches. roleCheck is ignored and cannot disable authorization.
- Excludes meta.is_tmp whose extracted text equals 1; a present false/zero differs from the stricter SQL-null exclusion in Users_list. No parent/active filter is automatically added, and users is not a soft-delete table in this helper.
- Requested ordinary columns preserve database types/JSON text. departments is decoded to an array, falling back to CSV splitting; blank storage can therefore return [""], not []. Nested mapped references such as role use their declared map layout; hidden fields are not automatically removed.
- password, gcmId and widgetPassword are rejected before querying. Raw meta is returned as sanitized JSON text without trusted login tokens; pay_type is blank without financial authority. Cost/rate/hours fields require financial authority.
- area is a list of type-7 Location ID strings; skill is a list of integer Skill IDs without multipliers. allocatedToJob contains incomplete, non-deleted direct-user Jobs whose scheduled start is at least now minus their own duration, ordered by start; it includes future Jobs without a right-hand time bound. Entries are {id,meetingTime,hours}, with local datetime and numeric hours.
- With GPS account feature bit 16, all returned rows receive gpsCreateDate/gpsLatitude/gpsLongitude from latest GPS, or blank strings, even when those fields were not requested.
- Skill name search uses EXISTS so multiple matching skills do not duplicate users. Ordering appends user ID ASC. recordsTotal counts visible non-temporary users before request filters; recordsFiltered counts the filtered rows before page slicing.
- All main queries and counts apply TeamAccess user scope. The legacy department-based fallback applies only to otherwise unrestricted roles; CSV and JSON department membership both work.
- Native controls are validated before mapped SQL construction: flat field/ID lists, bounded paging, asc/desc directions and allowlisted advanced-search conditions. Raw advanceSearch.where SQL is rejected.
Side effects
- Reads data without changing business records, edit markers, activity history or notifications. Shared setting reads can populate their normal settings cache.
See it in Fieldmotion
CRM1
No direct production caller was found in CRM1; its Users screen uses the positional Users_getDT contract.
CRM2
Open CRM2 Users or an assignee picker and filter Users_getDataTable. The export-selection pass requests fields=[id], isTable=0, limit=0; picker calls use the constrained listPicker marker.
Related endpoints
Users_getDT— Compare CRM1’s positional table format.Users_list— Read the basic selectable user list and its explicit scope predicate.Users_getExportData— Follow the two-phase legacy export contract.