Customers
List customer change history
/a/Customer_getChangesDT
Return paged customer audit changes and migrate the record’s legacy embedded history when necessary.
When to use this endpoint
Use Customer_getChangesDT for the CRM1 customer Changes tab. It reads normalized customer_changes rows and transparently converts older history still embedded in the customer row.
Use Customer_exportChanges after this endpoint when a user needs a CSV of the normalized history.
Authentication and permissions
The request must authenticate with signed API-key fields or a logged-in CRM session. The handler performs no additional page or role-permission check.
The lookup and any write use the authenticated tenant; an ID from another tenant cannot be addressed through this call.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
customer_id | Integer string | Yes | Customer ID. The endpoint verifies that a customer row exists. |
start | Integer string | Yes | Zero-based row offset. |
length | Integer string | Yes | Page size. |
draw | Integer string | Yes | DataTables counter copied to the response. |
order[0][column] | Integer string | Yes | 1 user ID, 2 label, 3 encoded changes; other values sort by change epoch. |
order[0][dir] | String | Yes | Exact asc selects ascending; other values select descending. |
field | String | No | Exact label filter. Blank means all fields. This differs from the export endpoint’s substring filter. |
Example request
$changes = FM_api('Customer_getChangesDT', [
'customer_id' => '1088',
'start' => '0',
'length' => '25',
'draw' => '13',
'order' => [['column' => '0', 'dir' => 'desc']],
'field' => 'Email',
]);
Example response
{
"recordsFiltered": "1",
"data": [
[1727172000, 36, "Email", "[\"old@example.test\",\"service@example.test\"]"]
],
"draw": 13,
"recordsTotal": "8"
}
Each row is integer Unix change time, integer user ID, field label, and the raw encoded JSON change payload. The usual payload holds old value and new value; this endpoint does not decode it.
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: start"} | start is absent. |
{"error":"missing or invalid parameter: length"} | length is absent. |
{"error":"missing or invalid parameter: customer_id"} | customer_id is absent. |
{"error":"missing or invalid parameter: [order][0][dir]"} | The sort direction is absent. |
{"error":"missing or invalid parameter: [order][0][column]"} | The sort column is absent. |
{"error":"missing or invalid parameter: draw"} | draw is absent. |
{"error":"customer does not exist"} | No customer row has the supplied integer ID. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Legacy HTML snippets are parsed into label, old value, and new value. Labels are truncated to 128 bytes, dates are converted with
strtotime, and duplicate normalized rows are skipped using customer, time, user, label, and payload. - When at least one history row is inserted, the customer’s
last_editedis changed to the server’s current date/time. Merely reading the page can therefore advance customer edit polling. - The legacy embedded history is cleared before every source entry has been inserted. A malformed entry or database failure can leave a partial migration.
recordsTotalcounts all normalized changes for the customer;recordsFilteredadds the optional exact label filter.
Side effects
- Can clear
customers.changes, insert multiplecustomer_changesrows, and updatecustomers.last_edited. - Does not create a separate audit row describing the migration itself.
See it in Fieldmotion
CRM1
Open a customer and select Changes. Filter Network requests for Customer_getChangesDT; field filtering, sorting, and paging reload the endpoint. The first view of an old customer can trigger the migration described above.
CRM2
A source search found no CRM2 caller for this endpoint.
Related endpoints
Customer_exportChangesstreams normalized change rows as CSV.Customer_getAddressHistoryDTexposes separate address snapshots rather than field-change rows.