Schedule of Rates
Create mapped Schedule of Rates data
/a/ScheduleOfRate_createData
Create one Schedule of Rates row through CRM2’s mapped data helper.
When to use this endpoint
Use ScheduleOfRate_createData for CRM2’s shared Schedule of Rates create form. It accepts the newer camel-case field map, including nested nominal, tax-type, and customer-price metadata.
Use ScheduleOfRates_add only for the older CRM1 payload and its account-code resolution rules.
Authentication and permissions
The request must authenticate with signed API-key fields or a logged-in CRM session. The handler calls the normal login guard but performs no additional page or role-permission check.
All reads and writes use the authenticated tenant. The CRM screens apply client-side Schedule of Rates permissions, but those controls are not repeated by this endpoint.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name / code / description | String | No | Stored verbatim; the helper does not trim, require, or deduplicate these fields. |
cost | Number | No | Base customer price after floating-point conversion; defaults to the schema value when omitted. |
stockUsed | String or native array | No | Stored in stock_used. A native array is JSON-encoded; a string is stored without validating its JSON. CRM2 uses [[stockId, quantity], ...]. |
labourUsed | String or native array | No | Stored in labour_used. CRM2 uses objects such as {"user_id":18,"hours":2,"cost":50}; legacy readers also accept two-item arrays. |
assetTypes | String or native array | No | Stored in asset_types; CRM callers use a JSON array of asset-type IDs. |
priceBands | JSON string or native object | No | Stored in the JSON column price_bands, normally as an object keyed by price-band ID. Blank becomes SQL null. |
archived | Integer string | No | Integer-converted archive flag; the schema defaults to 0. |
meta | String or native object | No | Complete raw metadata value. Do not combine a replacement with nested metadata keys unless that interaction has been tested. |
metaNominal / metaNominalID / metaNominalCode / metaTaxTypeID / metaCustomerCosts | Scalar or native value | No | Values written into meta.nominal, meta.nominal_id, meta.nominal_code, meta.tax_type_id, and meta.customerCosts. Account, tax, and customer IDs are not validated here. |
taxType | Native object | No | Composite CRM2 picker value. id maps to metaTaxTypeID and nominalID maps to metaNominalID. Supplying the explicit metadata keys is clearer for integrations. |
lastEdited | Datetime string | No | Explicit replacement. If omitted, current server time is stored automatically. Blank writes SQL null. |
Example request
$created = FM_api('ScheduleOfRate_createData', [
'name' => 'Annual service',
'code' => 'AS-01',
'cost' => 150,
'stockUsed' => [[74, 1]],
'labourUsed' => [[
'user_id' => 18,
'hours' => 2,
'cost' => 50,
]],
]);
Example response
{
"ok": 1,
"id": 430001
}
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 parameters."} | No writable mapped field was supplied. |
Database error | A supplied JSON-column value is not valid for the tenant database. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Unknown keys and
idare ignored. At least one other mapped key must be accepted. - Native arrays/objects supplied to text fields are JSON-encoded by the shared helper; already-encoded strings are stored as received.
- These endpoints store the base price in
cost; they do not calculate a customer’s final price. Job/quote consumers can applymeta.customerCosts, the tenant settingsor-child-gets-parent-price, and the customer’s price band later. - There is no filtering or pagination because exactly one insert is attempted.
Side effects
- Inserts a tenant
schedule_of_ratesrow, advances theschedule_of_ratescache marker, and writes generic field-level history for accepted values. - Fires the tenant-configurable
SOR_newevent with the new rate ID. Any configured listeners run synchronously and can add integration-specific side effects.
See it in Fieldmotion
CRM1
CRM1 creates rates through ScheduleOfRates_add, not this mapped route.
CRM2
Open Stock → Schedule of Rates and create a rate. The shared display widget calls this route through its singular ScheduleOfRate API prefix.
Related endpoints
ScheduleOfRate_updateDataupdates the same mapped fields.ScheduleOfRate_getRequestedDetailsreads the mapped representation.