Jobs: scheduling and lifecycle
Soft-delete one job
/a/Job_delete
Remove a job from active views and mobile sync while cleaning up selected links and schedules.
When to use this endpoint
Use for a single confirmed deletion. It is not equivalent to Cancelled status: the job is retained with deleted=1 and a deletion timestamp, and selected relation/history records are removed.
Authentication and permissions
Requires login. Permission bit 16 blocks deletion unless the caller is a client admin; the returned error includes the permissions value.
Uses the authenticated tenant. There is no department, owner or finance guard.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | Integer string | Yes | Positive physical job ID. A retained already-deleted row is an idempotent no-op. |
Example request
$result = FM_api('Job_delete', ['id' => '1042']);
Example response
{"ok":1}
Normal success remains {"ok":1}. Already-deleted is a no-op warning; external follow-up failure retains ok and adds saved=1/warning/warnings.
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"} | Missing/nonpositive ID. |
{"error":"no such job exists"} | No physical job row. |
{"error":"insufficient CRM permissions"} | Delete bit 16 set without client-admin exception; permissions is also returned. |
{"error":"Unable to save job delivery changes"} | Checked local write or deletion audit failed; local changes roll back. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Retains the job row with deleted=1 and ddate. Active-row deletion and all local relation/deletion audits commit together; a local DB/audit failure rolls back that job's cleanup.
- Removes quote, primary/ancillary invoice, contract and task links (types 2/3/4/6/8), auditing every removed relation. Quote/invoice counts are recomputed from distinct remaining active jobs rather than decrementing cached values. Invoice timestamps are refreshed and other metadata/counters preserved.
- Detaches recurrence membership through the canonical helper. If no jobs remain, retains the sequence inactive with an empty ID cache and null next date; it does not hard-delete that recurring business row.
- Removes derived asset-job association rows, but retains movement history. Asset availability ignores job bookings tied to deleted jobs; historical location/owner records are not erased.
- Already-deleted jobs return ok with job already deleted and do not repeat audits, remote cancellation or notification cleanup. Missing physical rows remain an error.
- Contract dirty markers are part of local cleanup. After local commit, refreshes customer/recurrence state, retires global cron entries, cancels an outsourced counterpart and sends the CRM2 delete-state notification. A failed post-commit follow-up returns saved=1 with a warning instead of inviting replay.
Side effects
- Checked local soft deletion, relation/audit cleanup and target recounts; contract dirty markers; retained asset movement history.
- After commit: global cron retirement, customer counts, recurrence schedule disable/refresh, outsourced cancellation/mobile-removal audit and CRM2 deletion notification. Cross-tenant/global effects are not distributed-atomic.
See it in Fieldmotion
CRM1
Choose Delete on Jobs or Job detail and confirm the dialog. Even bulk UI deletion loops over Job_delete rather than calling Jobs_delete.
CRM2
Jobs module and job editor delete actions resolve to Job_delete; import-history rollback also uses it for job imports.
Related endpoints
Job_restorerecovers the retained soft-deleted row only.Jobs_deleteuses the same helper for a selected ID batch.Job_setStatusincludes the extra single-job transition follow-ups.