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

ParameterTypeRequiredDescription
customer_idInteger stringYesCustomer ID. The endpoint verifies that a customer row exists.
startInteger stringYesZero-based row offset.
lengthInteger stringYesPage size.
drawInteger stringYesDataTables counter copied to the response.
order[0][column]Integer stringYes1 user ID, 2 label, 3 encoded changes; other values sort by change epoch.
order[0][dir]StringYesExact asc selects ascending; other values select descending.
fieldStringNoExact 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

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: 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_edited is 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.
  • recordsTotal counts all normalized changes for the customer; recordsFiltered adds the optional exact label filter.

Side effects

  • Can clear customers.changes, insert multiple customer_changes rows, and update customers.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