Jobs: forms and resources
Upload a job table-cell image
/a/Job_setTableCellImage
Save an image reference into a job table cell, resizing large recognized images and attempting outsourced copy-back.
When to use this endpoint
Use for the CRM1 Tables image editor after obtaining table ID and zero-based row/field positions.
Job_setSubFieldImage is the different multipart contract used by CRM2’s job Form tables.
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 | Conditional | Positive physical active-job ID. Preferred name; defaults to the legacy alias only when absent/null. |
appointment_id | Integer string | Conditional | Legacy fallback when job_id is absent/null; defaults to 0 if neither is supplied. A present job_id=0 does not fall back. |
table_id | Integer string | No | Destination table ID, integer-converted; defaults to 0 and is not checked against form definitions. |
x | Integer string | No | Zero-based row position; default 0, no bounds validation. |
y | Integer string | No | Zero-based field position; default 0, no bounds validation. |
jpeg | Base64 string | Conditional | Raw base64 image bytes or the exact data:image/jpeg;base64, prefix followed by base64. Decoding is non-strict. If present it overrides Filedata, even when blank. |
Filedata | Multipart file | Conditional | Alternative upload part; the handler reads its temporary-file bytes. Supply one nonempty image source. |
Example request
$result = FM_api('Job_setTableCellImage', [
'job_id'=>'1042', 'table_id'=>'302', 'x'=>'0', 'y'=>'1',
'jpeg'=>base64_encode($imageBytes),
]);
Example response
{"ok":1,"val":"{\"src\":\"appointment-1042-1791714600.1234.jpg\",\"cid\":\"42\"}"}
val is an encoded JSON string with src and the authenticated account’s cid; cid is the session value, commonly a string. The generated src uses the exact legacy appointment- filename prefix.
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":"no jpeg parameter supplied"} | No nonempty bytes; checked before login. Coordinates are not explicitly validated. |
{"error":"Unable to save job"} | The primary database save failed. Successful-save history and subsequent follow-ups are not run. Image storage may already have created a file. |
{"error":"job does not exist"} | The job does not exist or is soft-deleted; no answer or resource write is performed. |
{"error":"Unable to store job image"} | Image storage reported failure or did not return a positive file-metadata ID; no answer reference is saved. |
{"ok":1,"val":"{\"src\":\"appointment-1042-1791714600.1234.jpg\",\"cid\":\"42\"}","warning":"Job saved; follow-up incomplete. Inspect saved state before retrying.","warnings":["Unable to mirror outsourced image"],"saved":1} | The primary save succeeded, but a recalculation, asset rebuild, notification or outsourced mirror failed. warnings identifies the failed follow-up; any normal response fields remain present. A benign no-change result from a follow-up is not a failure. Read saved state before retrying. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Image bytes are not validated as JPEG. A .jpg filename does not prove the content type; a base64 value takes precedence over an uploaded file.
- Each upload creates a new image reference; replacing a cell/answer does not delete its previous image file. Storage errors or a missing file-metadata ID return Unable to store job image before the answer is saved.
- Recognized images larger than 1024 pixels in either dimension are aspect-fitted within 1024×1024 and re-encoded as JPEG quality 85 when GD succeeds. Smaller, unrecognized or unsuccessfully decoded images retain their original bytes.
- Requires an active job before storage is attempted; lookup and UPDATE both exclude deleted jobs. Missing or nonpositive job IDs return job does not exist without creating a file.
- Creates missing tables, row gaps and preceding blank cells, then stores the encoded src/cid reference. No field-type or attached-form validation occurs.
Side effects
- Creates checked type-8 image storage/metadata, then performs a checked active-job table-answer/timestamp/edit-marker UPDATE, meetings-cache invalidation and generic job history.
- Mirrors the stored image bytes and reference to an active outsourced counterpart, using its account ID in the mirrored cell. A missing/deleted counterpart receives no copied file; a failed mirror returns a saved-state warning.
- No cost or asset-link recalculation, old-image cleanup or transaction is used.
See it in Fieldmotion
CRM1
Upload an image in a job’s Tables page. pageJobTables.js converts it to a JPEG data URI and sends Job_setTableCellImage with appointment_id, table_id, x/y and an extra name that this handler does not read.
CRM2
No direct caller was found in CRM2. Its job Form subform upload uses Job_setSubFieldImage with formID and multipart Filedata instead.
Related endpoints
Job_setSubFieldImageis the CRM2 subform upload contract using formID.Job_setFieldImageuploads image bytes into a named main-form answer.Job_setTableCellspatches selected row/field positions while retaining unspecified cells.