When to use this endpoint

Use Asset_getFinancialExportData through the shared export widget used by CRM1’s asset Financials screen.

The literal _ids=1 starts the selection phase. Later requests send a JSON array of those job IDs and a JSON array of field identifiers.

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
_idsStringYesLiteral 1 starts phase one. In phase two it must be a non-empty JSON array; every element is converted to an integer.
asset_idInteger stringPhase oneSelects non-deleted direct jobs for this asset. Asset existence and deleted state are not checked.
job_refStringPhase one in practiceJob-reference substring. The implementation reads this key directly; omission can emit a PHP notice and behaves like blank.
nameStringPhase one in practiceRead directly but currently ignored; CRM1 supplies its customer/asset-name filter here.
searchStringNoLowercased substring matched against job reference or current asset name in phase one.
fieldsJSON array of stringsPhase twoNon-empty list of export IDs. Supported values are asset_id, customer_id|customer_type, id, job_ref, hours, hours_cost, invoice_ids, invoice_nums, meeting_time_e, meta, mileage, mileage_cost, schedule_of_rates_cost, schedule_of_rates, schedule_of_rates_invoiced, stock_cost, stock_invoiced, job_stock_used, total_cost, total_invoiced, and user_id|user_type. IDs containing a colon are silently skipped as prospective custom fields.

Example request

// Phase 1
$selection = FM_api('Asset_getFinancialExportData', [
	'_ids' => '1',
	'asset_id' => '4821',
	'job_ref' => '',
	'name' => '',
	'search' => '',
]);

// Phase 2
$rows = FM_api('Asset_getFinancialExportData', [
	'_ids' => json_encode($selection['ids']),
	'fields' => json_encode(['id', 'job_ref', 'hours_cost', 'total_cost']),
]);

Example response

[
  {
    "job_id": "7719",
    "asset_id": "4821",
    "meta": "{...}",
    "f0": "7719",
    "f1": "JOB-7719",
    "f2": "125.00",
    "f3": 217.5
  }
]

Phase one returns {"ids":[...]} ordered by job ID. Phase two returns a bare array with fixed job_id, asset_id, and raw JSON-string meta, then f0, f1, and so on in requested-field order. Paired identifiers use suffixes such as f1_0 and f1_1.

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:_ids"}_ids is absent.
{"error":"missing or invalid parameter: asset_id"}Phase one omits asset_id.
{"error":"_ids should be a JSON array of numbers"}Phase-two _ids does not decode to a non-empty array. Non-numeric elements inside a valid array are silently converted to zero.
{"error":"fields should be an array of requested field names"}fields is missing, invalid JSON, empty, or not an array.
{"error":"unknown field name: NAME"}A non-colon field identifier is not allowlisted.

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

Behaviour and edge cases

  • Phase one selects non-deleted direct asset jobs and ignores linked-only jobs. Phase two does not exclude deleted jobs and has no explicit ordering, so output order is not guaranteed to match _ids.
  • SOR detail is returned as a JSON string of current SOR definitions with quantity. The cost calculation does not multiply current stock/labour cost by that quantity.
  • Invoice IDs and numbers are comma-separated strings. Totals count only parsed invoice rows for the job; non-deleted linked invoices with unusable data can still appear in the ID list.
  • total_cost adds labour, mileage, stock, and estimated SOR cost. The CRM1 caller requests those component fields together; integrations should do the same because dependency-only combinations are poorly exercised.
  • There is no server-side page size in phase two; the export widget is responsible for batching IDs. The endpoint is read-only.

See it in Fieldmotion

CRM1

Open an asset’s Financials tab, select Export, and filter Network requests for Asset_getFinancialExportData.

CRM2

No direct production CRM2 caller was found.

Related endpoints