When to use this endpoint

Use for CRM2’s subform image upload, where formID identifies the saved table and x/y select its row and field positions.

Do not confuse this with Job_setTableCellImage: parameter names, resizing, returned reference fields and outsourced behavior differ.

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

ParameterTypeRequiredDescription
idInteger stringYesRequired by presence, then converted to integer; positivity is not validated. The lookup requires an active job.
formIDInteger stringYesRequired by presence; converted to integer. The destination table form is not checked for existence or attachment to the job.
xInteger stringNoZero-based row index; defaults to 0. No nonnegative or upper-bound validation.
yInteger stringNoZero-based field index; defaults to 0. No nonnegative or upper-bound validation.
jpegBase64 stringConditionalRaw 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.
FiledataMultipart fileConditionalAlternative upload part; the handler reads its temporary-file bytes. Supply one nonempty image source.

Example request

$result = FM_api('Job_setSubFieldImage', [
	'id'=>'1042', 'formID'=>'302', 'x'=>'0', 'y'=>'1',
	'jpeg'=>base64_encode($imageBytes),
]);

Example response

{"ok":1,"val":"{\"src\":\"appointment-1042-1791714600.1234.jpg\"}"}

val is a JSON string containing src; the exact generated filename uses the legacy appointment- prefix, job ID and microtime.

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":"no jpeg parameter supplied"}No nonempty decoded/uploaded image bytes.
{"error":"missing or invalid parameter: id"}id is absent.
{"error":"missing or invalid parameter: formID"}formID is absent.
{"error":"job does not exist"}No active job is read.
{"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":"Unable to store job image"}Image storage reported failure or did not return a positive file-metadata ID; no answer reference is saved.

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.
  • Creates the selected table if absent. Missing rows through x become arrays and preceding cells through y-1 become empty strings; the addressed cell is replaced with the encoded src object.
  • No server-side image resize, field-type/schema check, coordinate bound or outsourced copy-back is performed. Use valid nonnegative positions from the current form.

Side effects

  • Creates a type-8 image file linked to the job. Writes subform_values, timestamps and edit marker for the active job and invalidates the meetings cache; the database result is checked before history is recorded.
  • Logs generic image-change history and a sub-field entry whose old value is the previous table (after gap filling) and whose subtype uses the job ID, not the form-field ID. Does not recalculate costs or asset links.

See it in Fieldmotion

CRM1

No direct canonical or legacy caller was found in CRM1. Its job Tables image editor uses Job_setTableCellImage instead.

CRM2

Upload an image in a subform on the job Form. pageJobForm.js posts multipart Filedata to php/api.php with extra=/Job_setSubFieldImage, id, formID, x and y.

Related endpoints