When to use this endpoint

Use ScheduleOfRates_setCustomerCosts for customer-specific prices from CRM1 or CRM2. The stored values affect later Job/quote price selection; they do not change the base cost.

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

ParameterTypeRequiredDescription
idInteger stringYesPositive rate ID.
valsNative object/arrayNoCustomer-ID-to-price mapping. Values are floating-point converted and keys are retained by PHP/JSON rules. Omission means an empty array. JSON text is not decoded.
mergeInteger stringNoExact integer 1 updates/adds supplied keys while retaining existing meta.customerCosts; otherwise the complete mapping is replaced.

Example request

FM_api('ScheduleOfRates_setCustomerCosts', [
	'id' => '430001',
	'vals' => [
		'1042' => 145,
		'1088' => 140,
	],
]);

Example response

{
  "ok": 1
}

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: id"}The ID is absent or not positive.
{"error":"schedule of rates does not exist"}The ID has no row.
Runtime type errorvals is a scalar/JSON string, or merge targets legacy customerCosts data that is not an array.
{"ok":1,"msg":"no change needed"}The newly encoded complete metadata exactly matches the stored metadata string.

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

Behaviour and edge cases

  • Other metadata keys are preserved. Invalid/blank existing metadata is treated as an empty object.
  • With tenant setting sor-child-gets-parent-price=1, server Job price calculation checks a direct parent’s override before the child’s own override. With the setting off, it checks the direct customer override. Price-band/base-price fallback follows afterward.
  • CRM callers may generate child customer entries themselves; this endpoint only stores the submitted mapping.

Side effects

  • On change, advances last_edited and the scheduleOfRates cache marker.
  • Fires the tenant-configurable SOR_edit event with the rate ID. Any configured listeners run synchronously and can add integration-specific side effects.

See it in Fieldmotion

CRM1

The rate Prices dialog and Customer Schedule of Rates page replace mappings through this route.

CRM2

Customer-specific price tools use this route, sometimes with merge=1. The main Schedule of Rates editor uses mapped update instead.

Related endpoints