When to use this endpoint

Use the Jobs multi-edit Change User workflow. This is not an atomic batch of Job_setUserIdAndType calls; notifications and status handling differ.

Authentication and permissions

Authenticate with signed API-key fields or a logged-in CRM session. Legacy edit-restriction bit 128 is enforced; client administrators retain the existing admin exception.

The primary job selection is tenant-scoped. There is no automatic schedule-conflict or assignee-ownership check. Cross-tenant follow-ups use persisted outsourcing context.

Parameters

ParameterTypeRequiredDescription
job_idsArray or JSON arrayYes, or legacy aliasNonempty job-ID list. Values are integer-coerced; duplicates/missing/deleted IDs are collapsed/omitted by the active-row lookup. No complete-match check.
appointment_idsArray or JSON arrayLegacy alternativeAccepted only when job_ids is absent/null. Both CRM multi-edit callers still send this exact old wire name. Prefer job_ids in new integrations.
user_idInteger stringNoDefaults to 0 unassigned; negative is rejected. Positive type-0 IDs must resolve to an active tenant user.
user_typeInteger stringNo0 tenant user (default), 1 actively linked outsource company. Other values and type 1 with ID 0 are rejected.

Example request

$result = FM_api('Jobs_setUser', [
	'job_ids' => json_encode(['1042', '1088']),
	'user_id' => '27', 'user_type' => '0',
]);

Example response

[27,"0"]

Returns unique affected NEW then OLD user IDs, not job IDs and not {ok:1}. Existing DB IDs are often strings. array_unique retains numeric keys; some multi-user batches encode as an object with sparse numeric keys rather than a JSON list. No changes returns [].

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: user_id"}Negative target ID.
{"error":"job_ids should be a JSON-encoded array of job IDs"}Missing, null or empty list.
{"error":"Failed to update job assignment"}Primary write failed; earlier jobs can already be saved.
{"error":"tenant job does not exist"}An old outsourced counterpart could not be cancelled after local assignment.
{"error":"Invalid job assignee"}Unsupported type/ID or missing/inactive tenant user.
{"error":"you are not linked to that outsource client"}No active type-1 outgoing outsourcing link.

Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.

Behaviour and edge cases

  • Enforces the edit restriction with client-admin exception and prevalidates the typed assignee. Does not reopen status 4, unlike the single assignment setters.
  • Skips unchanged typed assignments. Writes previousUser, resets on_app=0 and advances sync metadata for each change.
  • Old outsource copies are cancelled when metadata identifies them, but this path does not remove the local outsourced metadata. New type-1 assignment calls Outsourcing_sendJob without checking its response.
  • Immediate Job_emailAbout is attempted when the tenant/form/Job Type notification gate enables it, even though this loop does not constrain the call to user_type=0. It does not create the assignment cron type-5/6 rows used by the single typed setter.
  • Withdraws removal markers for the new numeric ID and records the old numeric user's removal without checking the old assignment type. No batch size limit or transaction; database row order is unspecified.

Side effects

  • Updates assignments and mobile state; cancellation/creation of outsource copies, customer last_edited writes, immediate assignment mail, mobile deletion audits and Job_updateCosts.
  • Assignment emails receive typed old/new snapshots; current customer numeric IDs are touched even for asset-target jobs. The wrapper does not add its own set-user history beyond nested follow-ups.

See it in Fieldmotion

CRM1

Select jobs → Change User. jobsMultiEdit.js sends the legacy appointment_ids field and a typed user selector.

CRM2

The same Change User bulk action in lib/jobsMultiEdit.js also sends appointment_ids. Its response is used as completion, not as a job-ID result list.

Related endpoints