Sales, finance and marketing reports
Read Quote activity by marketing source
/a/Report_getMarketingLeadSource
Break down Quote count or value by marketing source, report period and selected entity.
When to use this endpoint
Break down Quote count or value by marketing source, report period and selected entity. Use this for the matching saved Reports dashboard chart or table; the result is chart series, not raw object records or a PDF.
res contains optional overall activity followed by numeric status series and unused zero series. xLabels repeats source names, xLabels1 contains the helper’s primary axis and xLabels2 its secondary period axis.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. The handler requires login and account feature bit 8192 in employer.features.
The dispatcher rejects these legacy Report routes for a user with configured TeamAccess record scope, including assigned-only/parent-manager access or a department hierarchy scope. It returns an explicit legacy-report scope error; it does not return a silently partial chart.
For an allowed unscoped request, the handler reads the authenticated tenant and adds no Reports/Quotes/Invoices page-permission check, account-manager restriction or per-object ownership check. Selecting user IDs is a chart filter, not authorization.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
daysFrom | Integer string | Yes | Start of range: relative day offset when durationType is omitted/not 1; Unix seconds when durationType=1. Must be an integer string or integer; blank and malformed values are rejected. Use an ordered, bounded range. |
daysTo | Integer string | Yes | End of range in the same mode as daysFrom. Must be an integer; no reversed-range validation. The handler expands to the final day’s 23:59:59 unless the behavior below says otherwise. |
durationType | Integer string | No | Defaults to 0. Exactly 1 uses Unix seconds; every other integer treats daysFrom/daysTo as offsets from the current PHP time. ISO date strings are not parsed as dates. |
userType | Integer string | Yes | 0 summary, 1 users, 2 customers, 3 asset-axis labels. Must be an integer from 0 through 3. User grouping uses user_id. Type 3 still aggregates customer_id rather than following an asset relationship. |
user | Native array of ID strings or ["All"] | No | Defaults to ["All"]; a supplied empty list is rejected. Summary mode ignores the selection. IDs are validated as integer values before SQL. Do not JSON-encode the array. |
displayType | Integer string | Yes | 0 counts; 1 net value. Other values fall back to counts. Value aggregates are integer-converted; this is not a precise currency export. |
frequency | Integer string | No | Defaults to 0 monthly; 1 weekly, 2 quarterly, 3 yearly. Controls both helper labels and SQL period grouping. Values outside 0–3 are rejected. |
legend | Native array of strings | Yes | Numeric Quote status IDs, optionally including exact token Opportunity for overall activity. Use real IDs, not All; the UI expands All before sending. Array order determines meaningful series order. Opportunity alone is supported; at least one valid legend token is required. |
leadSource | Native array of IDs or ["All"] | No | Defaults to all marketing_sources rows; All also means all. Explicit IDs are intersected with known source IDs; no remaining IDs returns No data in marketing source. A supplied empty list is invalid. |
Example request
$report = FM_api('Report_getMarketingLeadSource', [
'daysFrom'=>'1768003200',
'daysTo'=>'1768003200',
'durationType'=>'1',
'frequency'=>'0',
'userType'=>'0',
'user'=>['All'],
'displayType'=>'0',
'legend'=>['1'],
'leadSource'=>['7'],
]);
Example response
{
"res": [
[
0
],
[
0
]
],
"xLabels": [
"Referral"
],
"xLabels1": [
"Jan 2026"
],
"xLabels2": []
}
The example uses Unix seconds for 2026-01-10 00:00:00 UTC. The handler expands the resulting account-local date to its documented day boundaries.
Representative empty-cohort result from the real handler with a January 2026 summary axis and a source fixture named Referral.
res contains optional overall activity followed by numeric status series and unused zero series. xLabels repeats source names, xLabels1 contains the helper’s primary axis and xLabels2 its secondary period axis.
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":"This legacy report does not support your configured record scope. Use the scoped Contracts reports or table exports."} | The dispatcher detects configured TeamAccess record scope. This applies before the handler’s own checks. |
{"error":"no permission to access api"} | Account reporting feature bit 8192 is absent. |
{"error":"missing parameter: daysFrom"} | daysFrom omitted or null. Present blank scalars and malformed list controls return an invalid-parameter error instead. Required lists must be native arrays. |
{"error":"missing parameter: daysTo"} | daysTo omitted or null. Present blank scalars and malformed list controls return an invalid-parameter error instead. Required lists must be native arrays. |
{"error":"missing parameter: userType"} | userType omitted or null. Present blank scalars and malformed list controls return an invalid-parameter error instead. Required lists must be native arrays. |
{"error":"missing parameter: displayType"} | displayType omitted or null. Present blank scalars and malformed list controls return an invalid-parameter error instead. Required lists must be native arrays. |
{"error":"missing parameter: legend"} | legend omitted or null. Present blank scalars and malformed list controls return an invalid-parameter error instead. Required lists must be native arrays. |
{"error":"No data in marketing source"} | No known marketing sources remain after selection. |
{"error":"invalid parameter: legend"} | A supplied numeric control is malformed, a list has the wrong shape or an unsupported token, or frequency/userType is outside 0–3. The message names the invalid control; validation occurs before chart 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
- List controls must be native lists of strings or integers. Encoded JSON strings, nested/object-keyed arrays and nonnumeric IDs are rejected before SQL. Only the documented All, Opportunity and composite legend tokens are accepted. Empty user/status/leadSource lists are invalid; empty legends are accepted only on the status-series reports, MarketingExpense and SalesPerLeadSource.
- Loads marketing_sources ordered by name without active/deleted filtering. Omitted leadSource, or a native list containing All, keeps every source; other selections are intersected with known IDs, retaining supplied order and duplicates.
- No selected known source returns "No data in marketing source". Records without a selected marketing_source are excluded, including unassigned zero unless a source with that ID exists.
- The outer axis is period/entity, then marketing source. Numeric legend entries select Quote status; the exact Opportunity token prepends overall Quote activity rather than switching object type.
- Quote cdate is a datetime; displayType=1 sums total_net. Summary sets the grouping owner to 0; user type 1 uses user_id and types 2/3 use customer_id.
- Allocated rows exceed the meaningful status series: with legend=["1"] there are two rows, the second zero; overall plus status can leave two unused rows.
- Opportunity alone returns the overall series without running a numeric status query. Mixed selections still return the existing overall/status series and unused legacy zero rows.
- There is no pagination, row limit or result checkpoint. Keep the date range and entity selection bounded; label helpers expand every selected period/entity combination.
- The underlying aggregate queries do not exclude deleted source objects. Related label/source queries also have no general active/deleted filter. Totals can differ from active-record lists; no deletion behavior is changed by this documentation.
- PHP date conversion uses the account timezone setting (missing/null falls back to Europe/Dublin; blank means UTC). SQL date/Unix functions use the database session timezone; alignment is not enforced by this handler. Date endpoints are expanded to whole local days, not retained at the supplied time of day.
- Amounts are aggregate reporting numbers without currency codes or decimal preservation. Do not treat them as an invoice/quote ledger export.
- Axis order is period then entity name. One selected entity collapses the entity labels into date labels; multiple entities repeat names in xLabels with dates in xLabels1. Temporary users whose meta.is_tmp is non-null are excluded from the user-axis lookup. Zero buckets are prefilled; unmatched entity/date keys are dropped. Weekly labels and SQL grouping use ISO week-year and enumerate actual Mondays, including ISO week 53 and calendar-year boundary weeks.
- No direct mobile-app or m-service caller was found for this route. Browser report definitions are separate from the newer Report_getData template contract.
Side effects
- Reads report data only. No record, audit, status, notification, mail, report-cache or schema writes occur. Date helpers temporarily change PHP timezone on paths noted above.
See it in Fieldmotion
CRM1
Open Reports dashboard, add or preview the Marketing Lead Source report, set its filters, and inspect Network for Report_getMarketingLeadSource. pageReportDashboard.js builds Report_get plus the saved api name and expands All selectors using reportDashboard/Constant.js; chart presentation options and labels are client-side.
CRM2
Open the saved Reports dashboard report using api=MarketingLeadSource, change or preview its filters, and inspect Report_getMarketingLeadSource. lib/displayReport.js builds this route dynamically from the saved definition, expands supported All selectors, and renders the returned series. The newer widgetReport.js instead calls Report_getData with a report template; its payload is a different contract.
Related endpoints
Report_getMarketingExpense— Compare selected marketing-source expense with selected Quote status net values across report periods.Report_getSalesPerLeadSource— Compare selected marketing-source Quote activity across status, period and selected entity axes.