When to use this endpoint

CRM2 normally gathers filtered IDs through Contracts_getDataTable, then calls Contracts_getExportDataTable in data mode for CSV columns.

The endpoint also retains an _ids=1 selection mode, but its filters and deleted-row behavior differ from the live CRM2 selection path.

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
passwordStringYesTenant export password, checked on every request through Customers_exportCheckPass.
_idsStringYesExact 1 selects IDs; otherwise a nonempty JSON ID array requests data.
fieldsJSON array stringData phaseOrdered allowlisted names or custom:<key> tokens, returned as f0, f1, and so on.
name / number / notes / customer_name / searchStringsNoSelection filters. Numeric search matches ID; text search matches lowercased name. Customer name retains the broad-match legacy bug.
active / typeID / contractID / notInvoiceableInteger stringsNoExact selection filters. notInvoiceable reads meta.not_invoiceable.
customersListNative arrayNoValues must exactly match [0,<id>] or [1,<id>]; they become one escaped regular-expression alternation over cached customers.
date_from / date_to / non_expiringDate/date controlsNoLegacy expiry controls. With nonblank date_from, non_expiring=1 selects the range OR any non-null expiry; 0 selects only null expiry.
referenceDateField / dateFromFilter / dateToFilter / isDateUnixShared export date controlsNoInclusive day-offset filters based on the PHP server date. Allowed reference fields: cdate, date_completed, date_started, expiry_date, id, last_edited, and type_id.

Example request

$rows = FM_api('Contracts_getExportDataTable', [
	'password' => 'replace-with-export-password',
	'_ids' => json_encode([720]),
	'fields' => json_encode(['name', 'budget', 'cost', 'contract_type_name']),
]);

Example response

[
  {
    "id": "720",
    "custom": "{}",
    "f0": "North Region Service Contract",
    "f1": "25000",
    "f2": 1925.25,
    "f3": "Planned service"
  }
]

The ordinary/dynamic field allowlist and zero-valued net/profit/tax behavior match Contracts_getExportData.

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":"incorrect password"}The export password is wrong or absent.
{"error":"missing or invalid parameter: _ids"}_ids is absent.
{"error":"_ids should be a JSON array of numbers"}Data-phase IDs are malformed or empty.
{"error":"fields should be an array of requested field names"}Data-phase fields are malformed or empty.
{"error":"invalid customersList"}A customers-list token is not in the exact supported pair format.
{"error":"invalid referenceDateField"}The shared date helper rejects the requested reference.

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

Behaviour and edge cases

  • The live CRM2 path passes explicit IDs collected from its mapped table, so phase-one filters are normally bypassed.
  • The legacy customer-name filter begins with a broad %0% alternative and cannot be trusted for exact customer isolation.
  • jobs and cost use only type-6 legacy links. There is no ordering or built-in batch limit.
  • non_expiring behavior is inverted/misnamed in phase one: value 1 includes any non-null expiry, while 0 selects null expiry.

See it in Fieldmotion

CRM1

No production CRM1 caller was found; CRM1 uses Contracts_getExportData.

CRM2

On Contracts, choose Export, pass the password prompt, and choose fields. CRM2 first queries filtered IDs with Contracts_getDataTable, then sends batches here.

Related endpoints