When to use this endpoint

Use Asset_changesGetDT to reproduce the CRM1 asset History table.

It is a specialised positional DataTables feed. Use Asset_exportChanges when the user needs the matching CSV rather than a page of rows.

Authentication and permissions

The handler requires an authenticated tenant context, established by signed API-key fields or a CRM session. It checks the tenant table prefix but performs no page, role, or asset permission check.

Parameters

ParameterTypeRequiredDescription
aidInteger stringYesAsset ID. It is converted to an integer; existence, archived state, and soft-deleted state are not validated.
lengthInteger stringYesPage size. Zero and other integer-coercible false values become 10; negative values are passed into the SQL limit.
drawInteger stringYesDataTables draw token, returned as an integer.
startInteger stringNoZero-based offset; defaults to 0.
searchStringNoScalar substring matched against field name, new value, old value, and change date. This route does not read DataTables’ nested search[value].
order[0][column]Integer stringNoSort column: 0 date, 1 user ID, 2 related object ID, 4 field name, or 5 new value. Other values leave database order unspecified.
order[0][dir]StringNoExact asc selects ascending order; any other supplied value selects descending order. It has no effect when the column is unsupported.

Example request

$page = FM_api('Asset_changesGetDT', [
	'aid' => '4821',
	'draw' => '3',
	'start' => '0',
	'length' => '25',
	'search' => 'pressure',
	'order' => [['column' => '0', 'dir' => 'desc']],
]);

Example response

{
  "sql": "select ...",
  "draw": 3,
  "recordsTotal": "2",
  "recordsFiltered": "1",
  "data": [
    ["2026-09-24 10:15:00", "37", ["0", "1042"], ["7719", "2026-09-24 09:00:00"], "pressure", ["42", "39", 0]]
  ]
}

Each positional row is [changedAt, userId, [relatedType, relatedId], [jobId, localJobTime], fieldName, [newValue, oldValue, hideDiff]]. Database scalar values commonly remain strings.

hideDiff comes from the current asset-type template’s hide_diff flag for that field, not from the historical change row.

Errors and unusual responses

ResponseCondition
{"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: aid"}aid is absent; zero is accepted when present.
{"error":"missing or invalid parameter: length"}length is absent.
{"error":"missing or invalid parameter: draw"}draw is absent.

Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.

Behaviour and edge cases

  • Both counts are limited to the requested asset; recordsFiltered additionally applies search. Neither count checks whether the asset itself is deleted.
  • Job timestamps are converted from epoch seconds to the tenant’s local time. A missing or deleted linked job leaves the timestamp empty.
  • The asset and asset type are read without deleted-state checks. A nonexistent asset can therefore produce PHP warnings even though an empty data set is the intended practical result.
  • This read has no side effects.

See it in Fieldmotion

CRM1

Open an asset’s History tab and filter Network requests for Asset_changesGetDT. The page converts DataTables’ nested search value to this endpoint’s scalar search.

CRM2

No direct production CRM2 caller was found; CRM2 audit views use the newer log APIs.

Related endpoints