When to use this endpoint

Use for write-off review over all history or a selected creation-date range; this request does not write stock off.

Authentication and permissions

Authenticate with a signed API-key request or a logged-in CRM session. Requires Stock view (pageStocks_view) and table export (pageMain_exportTableData) permissions through the shared export guard; denial returns permission denied.

Client administrators and the all permission satisfy the checks. Legacy users with no role use the helper’s allow fallback when no explicit permission list is loaded. This is not merely the CRM1 export-button bit check.

Queries use the authenticated tenant. No department/owner restriction or stock-tracking feature gate is added by these handlers. CRM2 features2.stockTracking changes the export choices offered, not server authorization. Session CSRF and API signing still apply.

Parameters

ParameterTypeRequiredDescription
dateFromDate strings YYYY-MM-DDNo; both to filterBoth must be present to filter history cdate. Start is inclusive; end is exclusive at dateTo + 1 day. One-sided input is ignored. No format/range validation is implemented.
dateToDate strings YYYY-MM-DDNo; both to filterBoth must be present to filter history cdate. Start is inclusive; end is exclusive at dateTo + 1 day. One-sided input is ignored. No format/range validation is implemented.

Example request

$csv = FM_api('Stock_exportWriteOff', []);

Example response

"Stock ID",Name,Code,Cost,"Date Written Off",Qty,Batch/Serial,"From Initial Qty","From Updated Qty",Reason
1042,"Filter cartridge",FLT-01,4.5,"2026-10-05 09:00:00",2,BATCH-01,10,8,damaged

Success is raw CSV, not JSON: retain the response body instead of JSON-decoding it. The response uses text/csv and the final download filename stock_writeoff.csv. Column positions and blank cells are meaningful.

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":"permission denied"}Either required export permission is denied.
Header-only CSV or interrupted outputMost database reads are not checked for failure. A blank export is not proof that the database contained no matching rows; malformed stored JSON can interrupt legacy reports.
{"error":"invalid parameter: stockIDsFilter"}A supplied selected-ID list is not a string of positive decimal IDs.
{"error":"invalid parameter: search"}A supplied stock/date filter is an array or other non-scalar value; the error names that parameter.
{"error":"could not create stock export"}The per-request CSV stream cannot be created, written or rewound.

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

Behaviour and edge cases

  • Selects history type 9 joined to current stock without deleted/archive filtering. No stockIDsFilter or shared stock filters are consumed, including when CRM2 launches from a filtered table.
  • Cost is current stock average cost, not historical batch cost. From Updated Qty is from_qty minus history qty; both before/after quantity outputs preserve fractions.
  • Batch/Serial comes from history meta.reference with newline characters removed; Reason comes from meta.reason. Dates format Unix cdate in server timezone; SQL date boundaries use database UNIX_TIMESTAMP conversion.
  • No row ordering is declared. The download filename is stock_writeoff.csv.
  • No pagination or result limit is implemented. The entire result is exported; a header-only CSV is a valid empty result.
  • No stock quantity, audit, edit timestamp, notification or event is changed. Reads across multiple queries are not a transactionally frozen snapshot.
  • No direct caller for this exact endpoint was found in the current app JavaScript or m/www intermediary; these are office reporting/source-selection calls, not the app download protocol.
  • The shared guard rejects non-scalar supplied stock/date filters and validates any supplied stockIDsFilter even on reports that do not use it for selection.

Side effects

  • Builds CSV in a checked per-request php://temp stream, then streams it, closes it and exits. No shared tenant filename is written; concurrent requests generate independent files.

See it in Fieldmotion

CRM1

No direct caller for this exact endpoint was found in CRM1. Its Stock page has separate warehouse, user, vehicle, customer and cost export actions.

CRM2

Open Stocks → Export → Write Off. Choose All or Date Created and a date range. That special form sends dateFrom/dateTo when chosen but not the table’s selected-ID list.

Related endpoints