When to use this endpoint

Use Customers_edit for the CRM customer CSV import workflow after columns have been mapped to legacy customer field names.

Do not use it as a transactional bulk API. Each row independently calls Customer_edit or Customer_new, and successful earlier rows remain committed after later errors.

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
customersRequest array of objectsYesNonempty native request array. Despite an unreachable JSON-decoding branch, a JSON string is rejected by the initial type check. Each object is one create/update row.
run_triggersInteger/boolean-likeYesConverted to an integer. Each row receives do_not_run_trigger = 1 - run_triggers; values outside 0/1 produce unusual trigger-control integers.
customers[].idInteger stringNoTruthy positive ID selects Customer_edit; otherwise the row is passed to Customer_new.
customers[].parentString or numberNoA truthy nonnumeric value is resolved by exact customer name to parent_id; a missing match returns a row error. Numeric values are left for the child endpoint’s normal parameters.
customers[].account_managerString or numberNoA truthy nonnumeric value is resolved by exact user name; a missing match returns a row error.
customers[].departmentString or numberNoA truthy nonnumeric name is resolved exactly. If absent, a new department is created and its ID is used.
customers[].typeString or numberNoA truthy nonnumeric value is resolved by exact customer-type name; a missing match returns a row error.
customers[].countryStringNoValues longer than three characters are uppercased and looked up in the static country-name map. Unknown names can become an unset/null value; no explicit row error is generated here.
customers[].callbackStringNoFalsy/non-numeric-leading values are removed. Otherwise the time is stripped, and DD/MM/YYYY is converted to YYYY-MM-DD.
customers[].notesStringNoLegacy text beginning [{' has single quotes replaced by double quotes.
customers[].<other fields>Legacy customer valuesNoRemaining keys pass to Customer_edit or Customer_new; use the target endpoint’s snake-case parameter contract.

Example request

$result = FM_api('Customers_edit', [
	'run_triggers' => '0',
	'customers' => [
		['id' => '1042', 'name' => 'Northwind Belfast'],
		['name' => 'Northwind Cork', 'country' => 'Ireland'],
	],
]);

Example response

{
  "statuses": [
    {"ok": 1, "id": 1042, "errors": [], "updates": {"name": "\"Northwind Belfast\""}},
    {"ok": 1, "id": 1088}
  ]
}

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":"customers parameter not supplied or empty"}customers is absent, not a native array, or empty.
{"error":"run_triggers parameter not supplied or empty"}The run_triggers key is absent. A supplied zero is accepted despite the message wording.
statuses[n]: {"error":"parent does not exist"}A named parent cannot be resolved.
statuses[n]: {"error":"account_manager does not exist"}A named account manager cannot be resolved.
statuses[n]: {"error":"department does not exist"}Department resolution/creation returns strict false.
statuses[n]: {"error":"type does not exist"}A named customer type cannot be resolved.

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

Behaviour and edge cases

  • Name-to-ID caches are reused within the batch. Lookups are exact database comparisons and do not explicitly exclude inactive users/types/departments.
  • Missing named departments are created as a side effect, unlike missing parent, manager, or type records.
  • Rows are processed in request order. The handler removes the HTTP referrer before child calls to avoid legacy redirects.
  • Callback normalization cannot clear a callback because a falsy value is removed before the child call.
  • There is no pagination or batch-size limit.

Side effects

  • Combines all side effects of Customer_new and Customer_edit, including geocoding, audit/history rows, events, trigger emails, and notifications where their child routes apply.
  • May create departments while processing import rows.

See it in Fieldmotion

CRM1

The customer import dialog sends mapped rows to Customers_edit. Inspect the final import request and its per-row statuses.

CRM2

The CRM2 customer import module calls the same route and shows row-level outcomes; filter Network requests for Customers_edit.

Related endpoints