Price bands and stock pricing
Set final stock selling prices
/a/Stocks_setPrice
Atomically save validated final amounts to stock.price, with sync metadata and field history.
When to use this endpoint
Use when the client has already calculated selling prices. This API does not apply percentage/absolute adjustments itself or restrict IDs to a supplier.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session; all normal calls use that tenant. These handlers do not enforce an additional role or finance-page permission.
Use strings for signed numeric values, including values inside native arrays. Only JSON-encode parameters explicitly described as JSON text; see Getting started.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
prices | JSON array text of [stockID, amount] pairs | Yes | JSON text of positional [positive stockID, finite numeric amount] pairs. Native arrays, malformed pairs, nonnumeric/nonfinite amounts and invalid IDs are rejected before writes. All IDs must reference non-deleted stock. An empty JSON array is a safe no-op. |
Example request
$result = FM_api('Stocks_setPrice', ['prices'=>json_encode([['1042', '13.45'], ['1043', '20']])]);
Example response
{"ok":1}
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: prices"} | Omitted input or JSON that does not decode to an array. |
{"error":"stock does not exist"} | At least one requested ID is missing or deleted; no changes are committed. |
{"error":"pricing write failed"} | A primary write or required history write fails; the transaction is rolled back. |
{"error":"pricing read failed"} | A checked lookup fails; nothing is committed. |
{"error":"pricing transaction failed"} | Transaction start or commit fails. |
{"error":"pricing operation failed"} | Unexpected database/runtime failure; no success is returned. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Changes only stock.price plus edit metadata. Archived but non-deleted rows are eligible. Duplicate IDs are consolidated before writing, with the last supplied value winning.
- Amounts are final values, not adjustment instructions. No percentage, tax, supplier, price-band or currency calculation is performed; storage precision remains schema-dependent.
- Changed rows are written once, advance last_edited to server datetime and receive edited_uuid=Stocks_setPrice. Unchanged normalized amounts do not generate another timestamp/history update.
- No per-row partial success: all target existence checks, changes and history must succeed before ok=1. Empty batches return ok=1 without row/cache/history writes.
- The mobile app has no direct caller for this endpoint in the searched JavaScript or
m/wwwintermediary. It downloads price bands throughsyncDownloadsinto its localpriceBandstable.
Side effects
- Writes stock.price, last_edited and edited_uuid, invalidates stocks cache, and records checked history for every changed item. Audit and primary writes share the transaction. No quantity/movement change, fixed-band JSON update, configured event, notification or external request.
- Changing the base price affects subsequent relative-band calculations but leaves fixed overrides unchanged.
See it in Fieldmotion
CRM1
Open Supplier Edit → Adjust Prices. The dialog computes the percentage/absolute adjustment and selected decimal rounding in JavaScript, then sends final pairs to Stocks_setPrice. Filter that endpoint; the server does not verify supplier membership.
CRM2
No direct CRM2 caller for Stocks_setPrice was found. Stock mapped edits use Stock_updateData; customer pricing is calculated locally from cached objects.
Related endpoints
Stocks_getPricereads effective customer-specific stock prices.Stocks_setCostwrites the other stock amount independently.