When to use this endpoint

Use the scheduler's Set Job Times action after it has calculated proposed placements. The endpoint applies placements; it does not perform route optimization or reserve availability.

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.

Every distinct active job and every proposed date/tenant user is validated before the first save. This does not make the later saves atomic.

Parameters

ParameterTypeRequiredDescription
jobsJSON-encoded arrayYesNonempty JSON array of objects with id, job_time and user_id. Native arrays are not decoded by this endpoint.
jobs[].idIntegerYesPositive active job ID. Repeated IDs are keyed before processing, so the LAST row for an ID wins.
jobs[].job_timeSeconds or local datetime stringYesSeconds or a tenant-local datetime accepted by Job_setMeetingTime; every proposed time is validated before any save.
jobs[].user_idIntegerYesActive tenant user ID, or 0 unassigned. Each proposed user is prevalidated before writes; no user_type support.

Example request

$result = FM_api('Jobs_setUsersAndTimes', [
	'jobs' => json_encode([
		['id' => 1042, 'job_time' => 1791885600, 'user_id' => 27],
		['id' => 1088, 'job_time' => 1791889200, 'user_id' => 27],
	]),
]);

Example response

{"ok":1}

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: jobs"}Invalid JSON/non-array/empty list.
{"error":"missing or invalid job data"}A row has nonpositive id or omits job_time/user_id.
{"error":"failed to get jobs"}No active requested jobs resolved.
{"error":"failed to get all jobs"}Some requested jobs are missing/deleted.
{"error":"failed to set time for job 1042: missing or invalid parameter: value"}Example nested date failure; processing stops before assignment for that job.
{"error":"Failed to update job assignment"}A runtime assignment write failed after its time save; the response also contains saved/time_saved, failedId and updatedIds.

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

Behaviour and edge cases

  • Deduplicates by job ID with the last row winning, then validates all active IDs, date values and tenant-user targets before writing. No batch cap or overlap/availability reservation.
  • Processes the keyed input order: time then assignment for each row. A persistence failure stops with updatedIds and failedId; an assignment failure can also include time_saved=1/saved=1 for the current job.
  • Each setter sees a freshly loaded current row. Preloaded globals and request fields are restored, so assignment mail can use the updated start and later helper calls do not inherit another job.
  • user_type inside jobs rows is ignored; this remains a tenant-user assignment flow, not typed outsourcing handover.
  • The established upper-bound date error is Cannot set meeting time later than 2200. A successful response aggregates narrow-setter warnings without rolling back saved rows.

Side effects

  • Runs the narrow time and user setter effects: edit metadata/history, completion estimates, recurrence/reminders, date and assignment mail, mobile-removal markers, costs and possible outsource date mirroring.

See it in Fieldmotion

CRM1

In Scheduler, calculate placements and choose Set Job Times. widgetScheduler.js sends JSON batches with id/job_time/user_id; the legacy callback advances without inspecting each result.

CRM2

Scheduler and Smart Scheduler use widgetScheduler.js with the same JSON rows. CRM2 checks for ok=1 and stops with SCHEDULER_APPLY_FAILED on an error; displayed progress covers prior request batches, not the prefix of the failing request.

Related endpoints