When to use this endpoint

Use for CRM1 stock selection in purchase orders, invoices, quotes and job tables. The row shape is intentionally positional rather than mapped objects.

Authentication and permissions

Authenticate with signed API-key fields or a logged-in CRM session. The handler calls the user-login guard but adds no stock-page, finance or administrator permission check.

Queries use the authenticated tenant. Sign numeric values as strings; JSON-encode only parameters described as JSON text. See Getting started.

Parameters

ParameterTypeRequiredDescription
idInteger-compatible stringNoCategory ID, not stock ID. Omitted/zero means all categories. Nonzero uses the active category’s stored stock membership CSV; missing category or empty membership returns [] immediately.
supplier_idInteger-compatible stringNoNonzero filters stock.supplier_id, not stock_suppliers or many-to-many relationships. Omitted/zero removes this filter.
fieldsNative array or JSON array textNoAccepted order: any supplied names from id, name, code, in_stock, average_cost, price, nominal_code, tax_rate, price_bands. Invalid/malformed or wholly unrecognized selection falls back to id,name,code. ID is not added to a valid projection.

Example request

$items = FM_api('Stock_listByCategory', ['id'=>'1088', 'fields'=>json_encode(['id','name','code'])]);

Example response

[["1042","Filter cartridge","FLT-01"]]

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.
[]No eligible category membership or filtered rows.
{"error":"supplier not linked to any stock"}No selected rows and a nonzero supplier_id has no non-deleted, unarchived stock anywhere. The early missing/empty category return bypasses this check.

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

Behaviour and edge cases

  • Filters stock.deleted=0 and is_archived=0; the category lookup also filters deleted=0. Does not recursively include child categories.
  • Orders by name, with no paging or tie-breaker. Output positions follow distinct selected SQL fields; repeated column names collapse in the associative database row before conversion to positions. Names/types are not enriched and price_bands remains encoded JSON.
  • If the supplier has eligible stock outside this category, an empty category result is [] rather than the supplier error. Does not validate the supplier itself.
  • Reads category.stock membership, not category_ids JSON on each stock row. No page/finance or feature-setting guard is enforced.
  • No direct mobile caller was found in the current app JavaScript or m/www intermediary. The app receives stock through syncDownloads, which selects non-deleted stock by edit timestamp; these calls are not the app synchronization protocol.

Side effects

  • Read-only; no audit, edit timestamp, event or stock movement.

See it in Fieldmotion

CRM1

In a purchase-order line, open the stock picker and change category. Stock_listByCategory receives category id, supplier_id and JSON fields; the same positional picker is used by invoice, quote costs and job table screens.

CRM2

No direct CRM2 browser caller was found for this exact endpoint; the Stocks module uses mapped Stock reads and writes.

Related endpoints