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

ParameterTypeRequiredDescription
idInteger stringYesPositive 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

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"}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_restore recovers the retained soft-deleted row only.
  • Jobs_delete uses the same helper for a selected ID batch.
  • Job_setStatus includes the extra single-job transition follow-ups.