Assets
Update mapped asset data
/a/Asset_updateData
Update named Asset map fields, movement history, and CRM2 notification data for one asset.
When to use this endpoint
Use Asset_updateData for CRM2 configurable Asset layouts and for new integrations that need the server’s circular-whereabouts guard.
Use Asset_edit only when reproducing the legacy CRM1 wire names and archive behavior.
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 |
|---|---|---|---|
id | Integer string | Yes | Asset ID. Presence, not positivity, is checked up front. The intended contract is one scalar ID; the generic helper’s array mode is not safe with this wrapper’s movement and notification logic. |
name / code / bookID / make / model / customQR | Mapped strings | No | Replace the corresponding fields. This endpoint does not run the asset uniqueness-setting checks. |
active / archived / typeID / departments / value / warranty | Mapped values | No | Core mapped fields. Warranty must be blank or a real YYYY-MM-DD date. Referenced IDs are not validated, and changing archived here does not maintain deletion logs. |
location | Object | No | Whereabouts as {"id": targetId, "type": 0|1|2|3}. A changed type 2 target is rejected before any write if traversal reaches this asset or repeats an asset. |
locationID / locationType | Integer strings | No | Low-level components accepted by the map, but they bypass this wrapper’s circular check, address snapshot, and movement-history handling. Use location. |
ownerID | Integer string | No | Preferred owner customer ID. It persists the value and lets the wrapper refresh job caches and append owner history. Target existence is not checked. |
owner | Object | No | Picker form {"id": customerId}. The generic helper persists it as ownerID, but the outer wrapper does not notice this form for owner-history or job-cache side effects. |
owner_id | Integer string | No | Do not use. The wrapper notices it as an owner change, but it is not a mapped write field, so it can refresh caches and append misleading owner history without changing the asset owner. |
widgetTableContact / contacts | JSON/array | No | Widget contact rows are converted and replace contacts when conversion succeeds. |
widgetAssetServiceFrequency / metaServiceFrequency | Object | No | Widget input is copied to metadata. When existing meta.last_serviced and frequency exist, meta.next_serviced is recalculated using every (default 1): frequency 0 means days, 1 weeks, 2 months, and 3 years. |
registrationNumber / url / homeLocation / homeLocationID / homeLocationType | Mapped metadata values | No | Written directly to metadata. Unlike the legacy edit/home-location routes, names are not resolved and type/target validity is not checked. |
customValues / customMainValues / metaSkills and other meta* fields | JSON-compatible values | No | Replace the corresponding mapped metadata values. customValues is a complete map, not a merge, and display labels are not normalized. |
meta / files / jobDetails / locID / editedUuid / lastEdited / cdate / appID | Mapped low-level values | No | Accepted by the generic map even when marked hidden or read-only. Unknown keys are ignored. |
noRecord / noRecordCustom | Arrays of field keys | No | Marks matching generic audit entries hidden; it does not suppress the write or notification events. |
Example request
$result = FM_api('Asset_updateData', [
'id' => '4821',
'name' => 'Compressor 4',
'ownerID' => '1042',
'location' => ['type' => '1', 'id' => '1042'],
'customValues' => ['inspection_class' => 'A'],
]);
Example response
{
"ok": 1
}
A no-op can return {"warning":"No Change."}; no recognized update fields returns {"warning":"no updated fields."}; a missing/deleted row returns {"warning":"No data."}. These warning responses do not contain ok.
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: id"} | The id key is absent. |
{"error":"Asset whereabouts cannot create a circular reference."} | A changed Asset-type location reaches this asset or any repeated asset in the active graph. The check happens before mapped writes. |
{"error":"invalid date parameter: warranty"} | A supplied warranty is not blank and not a valid YYYY-MM-DD date. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Soft-deleted assets are excluded from the generic update. Archived assets remain writable. Unknown keys are ignored; if all supplied keys are unknown, the route returns a warning.
- An unchanged legacy circular whereabouts relation is allowed so another field can be saved. Changing to a non-Asset target clears the condition. Deleted targets terminate cycle traversal.
- When
ownerIDorlocationchanges, the route backfills an initial movement when necessary and appends a combined movement. A location change records an address snapshot only when the new type is customer. Theownerpicker alias persists without those owner-specific side effects. - No uniqueness tenant setting is consulted. A successful update can therefore create duplicate name, serial-number, or book-ID values even when the focused/legacy routes reject them.
- This route is intended for one record and provides no list pagination.
Side effects
- Updates the asset, refreshes
last_edited, invalidates the asset cache, and writes per-field generic audit entries. - Owner changes refresh parent/customer job caches. Owner or location changes write movement history; qualifying location changes also call the address-history endpoint.
- After a mapped result that includes old data, the wrapper attempts asset
update2andtime2notification-service events using old/new mapped data. A missing/deleted row can still reach this step with empty old data, while some warning/no-op paths skip it. Operations are not transactional.
See it in Fieldmotion
CRM1
No primary production CRM1 save uses this route; Asset_edit can delegate service-frequency updates to it.
CRM2
The shared Asset layout map registers this as its update route. Asset details and cycle-protection regression flows use it.
Related endpoints
Asset_getWhereaboutsBlockedTargetspre-filters invalid picker choices.Asset_getLayoutDetailsreads the matching field map.Asset_updateFieldis a lower-level bulk single-field write and does not run this wrapper’s side effects.