When to use this endpoint

Use for the CRM1 Refer another business and internal Referrals tables. Rows are positional; use Referrals_getDataTable for the distinct CRM2 mapped contract.

Authentication and permissions

Authenticate with signed API-key fields or a logged-in CRM session. Referrals are global platform rows, not rows in a tenant-prefixed table; the scope and additional account checks described below are therefore significant.

Requires an authenticated user ID after checking request parameter presence. Normally parent_id=current account is applied. Hardcoded account 3819 instead sees matching referrals across submitting accounts; account 32 does not receive that list exception. No further page/role check is applied.

Parameters

ParameterTypeRequiredDescription
draw / length / order / startIntegers and native order arrayYesPresence is checked in that sequence. Numeric controls must be integers, start nonnegative and length positive. order may be the legacy scalar placeholder or a native DataTables list.
order[0][column] / order[0][dir]Native nested arrayNo within required order0=id, 1=submitter name, 2=cdate, 3=company_name, 4=contact_name, 5=phone, 6=email, 7=notes, 8=status, 9=signed_date, 10=num_signed, 11=referral_source. Unknown/missing column falls back to id. asc/desc only; ties are resolved by id ascending.
statusInteger stringNoDefault -2; converted values above -1 add equality. Negative values disable this filter. Status 7 always remains excluded, so explicitly asking for it returns no rows.
search[value]StringNoNonblank, trimmed lowercase substring search over company_name, contact_name, phone, email, notes and submitter name. %/_ remain SQL LIKE wildcards; arbitrary extra field filters are not implemented.

Example request

$table = FM_api('Referrals_getDT', ['draw' => '1', 'start' => '0', 'length' => '10', 'order' => [['column' => '0', 'dir' => 'desc']], 'status' => '0']);

Example response

{"draw":1,"recordsTotal":"5","recordsFiltered":"1","data":[["1042","201","2026-10-10 09:00:00","Northwind Services","Alex Morgan","+44 28 0000 0000","alex@example.com","Interested in a demonstration.","0",null,"0",["0",{"name":"Sam Taylor","email":"sam@example.com","parent":"100"},"Example contractor"]]]}

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: draw"}draw omitted; checks run before the handler’s user-login check.
{"error":"missing or invalid parameter: length"}length omitted; checks run before the handler’s user-login check.
{"error":"missing or invalid parameter: order"}order omitted; checks run before the handler’s user-login check.
{"error":"missing or invalid parameter: start"}start omitted; checks run before the handler’s user-login check.
{"error":"referral read failed"}Checked rows or count query fails; no false empty-success page is returned.
{"error":"missing or invalid parameter: status"}Supplied status is not an integer.
{"error":"missing or invalid parameter: length"}Length is nonpositive or malformed; invalid start/order controls have corresponding errors.

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

Behaviour and edge cases

  • Each row is [id, user_id, cdate, company_name, contact_name, phone, email, notes, status, signed_date, num_signed, [referral_source, submitter, submitting_company]]. Submitter is {name,email,parent} or false, company is a string or false. Database numbers/counts are strings; draw is an integer.
  • CRM1 presents status 0=Open, 1=Contacted, 2=Signed, 3=Declined, 4=Paid. Status 7 hides a row from both table endpoints. The dedicated status setter accepts 0–4; legacy stored values are not remapped on read.
  • Both totals use the actual list visibility scope: own-account non-status-7 rows, or the existing cross-account operator exception for account 3819. recordsFiltered additionally applies status/search before pagination.
  • All displayed column indices now sort against real columns; Created By uses the submitter name. ID ascending is a deterministic tie-breaker. Row/count query failures return an error instead of an empty success.
  • Search is implemented over business/contact fields and submitter name. Extra arbitrary field filters remain ignored. There is no tenant setting for the hardcoded operator exception and no write side effect.

See it in Fieldmotion

CRM1

CRM1 Settings → Refer another business (pageRefer.js) creates referrals with Referral_new and lists/deletes them with Referrals_getDT/Referral_delete. The separate Customers → Referrals operator screen (pageReferrals.js) offers conversion and status/signing controls. Reload either table and inspect the request. The status dropdown supplies status; sorting Created By or Company Name now follows the visible column, and the search box filters the returned rows.

CRM2

CRM2 Settings → Refer another business (pageRefer.js) uses Referrals_getDataTable with Referral/Referrals widget prefixes, mapped detail/update helpers and individual Referral_delete calls. Its custom Create form still calls Referral_new, not Referral_createData. CRM2’s table does not use this positional route.

Related endpoints