Jobs: field and bulk edits
Replace miscellaneous job costs
/a/Job_setMisc
Replace miscellaneous resource rows and save their stored cost subtotal.
When to use this endpoint
Replace miscellaneous resource rows and save their stored cost subtotal.
Read the target job first with Jobs_getSome to obtain the current values and confirm the IDs belong to the intended account.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. The request uses the authenticated account’s job IDs, not mobile app IDs.
No extra page, role, assignee, department or client-administrator check is applied by this handler.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | Integer string | Yes | Physical job ID in the authenticated account, converted with intval; must be positive. |
misc_used | JSON-encoded array | Yes | Required present string; normally objects with description, cost, price, qty and optionally cost_total/price_total. The entire stored value is replaced. Invalid/scalar JSON is not rejected by the setter. |
misc_cost | Number/string | Yes | Required present subtotal, converted with floatval. Recomputed row cost overrides it if nonzero; exact trimmed '[]' forces zero. Otherwise the supplied subtotal is retained. |
Example request
$result = FM_api('Job_setMisc', ['id'=>'1042', 'misc_used'=>json_encode([['description'=>'Parking', 'cost'=>'5', 'price'=>'6', 'qty'=>'1']]), 'misc_cost'=>'5']);
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: id"} | id is absent or converts to a nonpositive integer. |
{"error":"missing parameter: misc_used"} | misc_used is absent or null. |
{"error":"missing parameter: misc_cost"} | misc_cost is absent or null. |
{"error":"Unable to save job"} | The primary database write failed. History and dependent effects are not performed for that failed save. |
{"error":"job does not exist"} | The active target is missing/deleted or the existence lookup failed. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- For each array row, cost_total takes precedence when present, otherwise cost multiplied by qty (or amt) contributes. Non-array rows are ignored by the calculator.
- A zero calculated sum for nonempty/invalid data falls back to misc_cost, including when positive and negative row costs cancel. Only the exact trimmed [] spelling forces the empty-list zero rule.
- Requires an active job before writing. A missing/deleted target or failed existence lookup returns job does not exist. The final UPDATE also excludes deleted jobs.
- Does not call Job_updateCosts/Job_updatePrices or regenerate invoices; stored sell-price fields can remain unchanged until another recalculation.
- The primary UPDATE is checked before history and dependent effects. There is no transaction combining this field write with later cross-object effects; inspect committed-success warnings before retrying.
Side effects
- Writes last_edited and edited_uuid with the changed fields and invalidates the meetings cache.
- Records a job history entry. No mail is sent directly by this setter.
- Replaces misc_used and misc_cost. No outsourcing mirror or direct mail/event call is made.
See it in Fieldmotion
CRM1
Open Job > Costs and edit Misc Costs rows. pageJobCosts.js sends JSON.stringify(newMisc) and the UI’s subtotal to Job_setMisc after the edit.
CRM2
No direct CRM2 caller was found in the canonical/legacy route search. CRM2’s layout-driven updates are a separate contract.
Related endpoints
Jobs_getSomereads the stored miscellaneous rows and subtotal after editing.Jobs_getSomereads selected job records before editing and verifies the stored result afterward.