Jobs: forms and resources
Remove an empty job table row
/a/Job_deleteEmptyTableColumn
Remove one stored table row after checking its cells for PHP-truthy values.
When to use this endpoint
Use for empty placeholder-row cleanup. Despite the endpoint and parameter names, column indexes an entire stored row, not a form-definition column.
Read the current row order first; successful removal shifts the zero-based indexes of later rows.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. The handler performs no additional page or role-permission check.
Job and form IDs refer to the authenticated account. Cross-account writes occur only through the stored outsourcing relationship on the routes that explicitly mirror changes.
The dispatcher also applies account/user and IP restrictions. A CRM session carrying a CSRF token must supply it through X-FMCSRF or _csrf; missing/incorrect tokens can be rejected before this handler runs.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
appointment_id | Integer string | Yes | Positive physical job ID. This exact legacy wire name is required; id/job_id are not aliases. |
table_id | Integer string | Yes | Positive table ID in the saved table answers. |
column | Integer string | Yes | Zero-based outer row index, converted with intval. Defaults to -1 and must be nonnegative. |
force | Integer string | No | Legacy bypass: default 0; any nonzero integer skips the emptiness check. Avoid using this as a normal empty-row cleanup option. |
Example request
$result = FM_api('Job_deleteEmptyTableColumn', [
'appointment_id'=>'1042', 'table_id'=>'302', 'column'=>'1',
]);
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: appointment_id"} | Job ID is nonpositive. |
{"error":"missing or invalid parameter: column"} | Converted index is negative. |
{"error":"missing or invalid parameter: table_id"} | Table ID is nonpositive. |
{"error":"Job does not include data from table 302"} | The active job’s saved collection has no requested table; missing/deleted jobs also reach this branch. |
{"error":"That column does not exist in the appointment table data"} | Requested stored row is not present and the index is beyond the table length. |
{"error":"Cannot delete that column as it is not empty"} | At least one cell is PHP-truthy and force is zero. |
{"error":"Unable to save job"} | The primary database save failed. Successful-save history and subsequent follow-ups are not run. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Only active jobs are read and updated. No table-form schema or field is deleted.
- A row array is considered empty when every cell is PHP-falsy: numeric zero and the string "0" do not protect the row from removal. Non-array legacy row values are not inspected for nonempty cells.
- Splices one outer row and reindexes the remaining rows. There is no paging, optimistic concurrency control or returned updated table.
Side effects
- Writes canonical table JSON, last_edited and edited_uuid; invalidates the meetings cache and records job history. The database write is checked before history is recorded.
- Does not rebuild asset links, recalculate costs, return consumed stock, delete image files or mirror outsourced table answers.
See it in Fieldmotion
CRM1
The Tables page’s empty-row cleanup in pageJobTables.js removes empty local rows and calls Job_deleteEmptyTableColumn using appointment_id, table_id and column. Watch Network while editing tables.
CRM2
No direct canonical or legacy caller was found in CRM2’s source. Its table form editing is a separate workflow; do not infer that this cleanup route runs there.
Related endpoints
Job_deleteTableColumnremoves a selected populated or empty stored row.Job_setTableCellspatches selected row/field positions while retaining unspecified cells.Job_updateCostsrefreshes cost/resource snapshots and invokes the price follow-up.