Jobs: forms and resources
Append ordered job table rows
/a/Job_tableRowAppend
Append one or more rows already arranged in destination field order to a selected job table.
When to use this endpoint
Use when the integration has prepared each row in the table form’s field order and does not need a CSV column map.
Unlike Job_addTableRow, this call validates the decoded outer/row array shapes, but does not recalculate costs after saving.
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 |
|---|---|---|---|
job_id | Integer string | Yes | Positive physical job ID. |
table_id | Integer string | Yes | Positive destination table ID. The handler does not check the table form exists or is attached to this job. |
rows | JSON array string | Yes | Nonempty array of row arrays, for example [["Inspection","Passed"]]. Empty row arrays are accepted; row width and cell types are not validated. A native array is not accepted by json_decode. |
Example request
$result = FM_api('Job_tableRowAppend', [
'job_id'=>'1042', 'table_id'=>'302',
'rows'=>json_encode([['Inspection','Passed']]),
]);
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: job_id"} | Nonpositive job ID. |
{"error":"missing or invalid parameter: table_id"} | Nonpositive table ID. |
{"error":"missing parameter: rows"} | rows is absent or PHP-falsy. |
{"error":"invalid parameter: rows. must be a JSON-encoded array"} | Decoded rows is not an array. |
{"error":"invalid parameter: rows. must have at least 1 contained array (the table rows)"} | Outer array is empty. |
{"error":"invalid parameter: rows. all objects in the main array must themselves be arrays"} | At least one row is not an array. |
{"error":"job 1042 does not exist"} | No active job is read; the ID is interpolated. |
{"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
- Appends in input order, creating the target table in the answer collection if necessary. Existing rows and other tables remain.
- There is no deduplication, pagination, maximum batch size, form-field check or concurrency token. Repeated calls append again.
- Falsey stored table JSON falls back to an empty array; truthy malformed/scalar legacy collections are not comprehensively normalized.
Side effects
- Unchecked table-answer UPDATE with last_edited and edited_uuid. The read checks active state, but the final UPDATE is ID-only.
- No direct history, meetings-cache invalidation option, asset-link rebuild, cost/price recalculation, stock movement or outsourced mirror is requested by this handler. Refresh dependent state separately where required.
See it in Fieldmotion
CRM1
No direct canonical or legacy caller was found in CRM1’s source. This endpoint is available to integrations and internal server calls; do not infer a dedicated screen.
CRM2
No direct canonical or legacy caller was found in CRM2’s source. Its layout-driven job editing uses a separate contract.
Related endpoints
Job_addTableRowimports mapped positional rows with optional replacement of one table.Job_setTableCellspatches selected row/field positions while retaining unspecified cells.Job_updateCostsrefreshes cost/resource snapshots and invokes the price follow-up.