Opportunities
Export opportunity data
/a/Opportunities_getExportData
Run the legacy two-phase opportunity CSV export: first discover IDs, then resolve requested columns and form fields.
When to use this endpoint
Use Opportunities_getExportData only through the CRM export widget, which manages the _ids sentinel/JSON batch contract and fN columns.
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 |
|---|---|---|---|
_ids | String | Yes | Exact/loosely equal 1 starts ID discovery. Otherwise it must be a non-empty JSON array of IDs for row resolution. |
from / to | Local date strings | Phase 1 only, optional | Inclusive tenant-local calendar bounds on cdate, converted to epochs at 00:00:00/23:59:59. |
search | String | Phase 1 only, optional | Legacy broad search. Any nonblank value currently generates malformed SQL; do not use until the implementation is corrected. |
opportunityID / quoteID / value / notes | Scalars | Phase 1 only, optional | Exact ID/quote/value filters or lowercase notes substring. Notes is interpolated without escaping. The quote filter is redundantly added twice. |
isStarred / formIDList / customersList / usersList / status / source | Native integer arrays | Phase 1 only, optional | Validated integer IN filters. They are applied only for non-empty native arrays. |
referenceDateField / dateFromFilter / dateToFilter / isDateUnix | Field / relative days / flag | Phase 1 only, optional | When both day offsets and a nonblank field exist, filter cdate, last_edited, or legacy won_date. Set isDateUnix for epoch fields. |
fields | JSON array string | Phase 2 | Non-empty requested field list. Allowed stored names: cdate, customer_id, id, last_edited, marketing_source, notes, parent, quote_id, status, user_id, value, callback, callback_notes. Form values use <form-id>:<stored-field-key>. |
Example request
// Phase 1
$ids = FM_api('Opportunities_getExportData', [
'_ids' => '1',
'from' => '2026-09-01',
'to' => '2026-09-30',
]);
// Phase 2
$rows = FM_api('Opportunities_getExportData', [
'_ids' => json_encode($ids['ids']),
'fields' => json_encode(['id', 'status', '12:field-1', 'parent']),
]);
Example response
[
{
"opportunity_id": "481",
"form_id": "12",
"form_values": "{\"field-1\":\"Yes\"}",
"subform_values": null,
"f0": "481",
"f1": "Draft",
"f2": "Yes",
"f3": "900",
"customer_id": "1042"
}
]
Phase 1 instead returns {"ids":[481,482]}. Phase 2 always includes the four helper columns shown; each requested field is returned as f0, f1, and so on. Requesting parent can also expose the helper customer_id.
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: _ids"} | _ids is omitted. |
{"error":"invalid <filter>"} | A phase-1 integer-list filter contains a non-integer value. |
{"error":"invalid referenceDateField"} | The requested relative-date field is not in the three-name allowlist. |
{"error":"_ids should be a JSON array of numbers"} | Phase-2 _ids is malformed, empty, or not an array. Despite the wording, members are merely integer-converted. |
{"error":"fields should be an array of requested field names"} | fields is missing, malformed, empty, or not a JSON array. |
{"error":"unknown field name: ..."} | A non-form field is outside the allowlist. |
Database/runtime error | Nonblank search, unsafe notes, an unavailable won_date column, or malformed IDs produce invalid SQL. |
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-1 IDs are sorted ascending. Phase-2 rows have no explicit order, so callers must match by
opportunity_id. - Status is translated to its name only for the first requested
statusoccurrence. Other IDs remain numeric; lead source/user/customer are not name-expanded by this route—the export widget handles their field types. parentlooks up the opportunity customer’sparent_id. A form-field request is populated only when its form ID equals the row’sform_idand its key exists inform_values.- The
won_datefilter option is present in code but no corresponding opportunity column appears in the canonical tenant schema/migrations reviewed for this batch.
See it in Fieldmotion
CRM1
The Opportunities Export button uses phase 1 with its date range and table search, then phase 2 for selected base/form columns.
CRM2
CRM2 first obtains filtered IDs from Opportunities_getDataTable, then its export widget uses phase 2 with those IDs.
Related endpoints
Opportunities_getDataTableis the safer CRM2 filtered-ID source.Opportunities_getDTsupplies the legacy visible table.