When to use this endpoint

Use after selecting a user and validating the new email. This changes the account identifier directly; it does not send a verification or password-reset email.

Authentication and permissions

Authenticate with signed API-key fields or a logged-in CRM session. Session requests use the dispatcher’s CSRF protection when configured; signed requests follow the API-key authentication flow.

Requires login and an owned tenant user. Ordinary self-profile edits are allowed; editing another user requires client administrator or explicit Users Edit permission. Protected membership fields require that permission even for self. Configured TeamAccess record scope and relationship checks remain in force.

The dispatcher applies configured TeamAccess user-record scope before the handler. An explicit target outside that scope returns an error; omitted targets use the current user for the scope check. Active/deleted filtering and additional target checks are described below.

Parameters

ParameterTypeRequiredDescription
idInteger stringYesTarget user ID in the authenticated tenant. Parsed with intval; this is a single-record operation, with no pagination or sort controls.
valEmail stringYesTrimmed and lowercased, then validated with FILTER_VALIDATE_EMAIL. Blank values are rejected. A normalized unchanged value returns a warning without a write.

Example request

$result = FM_api('User_setEmail', [
	'id'=>'1042',
	'val'=>'engineer@example.test',
]);

Example response

{
  "ok": 1
}

An unchanged normalized email returns {"ok":1,"warning":"no change necessary"}.

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: id"}id is omitted, null, or converts to an integer below 1.
{"error": "missing or invalid parameter: val"}val is omitted or null.
{"error": "no email address sent"}Trimmed email is empty.
{"error": "invalid email address"}Email validation fails.
{"error": "user does not exist or is not in this client account"}Tenant-parent lookup fails.
{"error": "that email address is already registered as a FieldMotion account"}A matching global identity exists.
{"error": "user does not exist"}No target user belongs to the authenticated account.
{"error": "only client admins or users with Users edit permission can edit other users"}Caller targets another user without explicit edit authority.
{"error": "Unable to save user changes. Check the saved state before retrying."}A checked write/transaction failed; inspect saved state before retrying, especially for separate global identity storage.

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

Behaviour and edge cases

  • Checks a tenant user with the current parent. No active/deleted condition is added. An exact match with the existing tenant email returns ok=1, warning=no change necessary before checking global uniqueness.
  • Global uniqueness uses any matching identity email, regardless of account, active or deletion state. It excludes the target identity itself, so retrying after a partial global-only email update can repair the tenant row.
  • Applies the shared User self/editor policy and checks both persistence acknowledgements. Global and tenant writes do not form a distributed transaction; read back state after an uncertain failure.
  • When department hierarchy and team access is enabled, the dispatcher wraps this User write in its access-relationship validation and can reject changes that would strand outstanding Jobs. This does not make file storage, session updates or separate global identity writes one atomic operation. Without that wrapper the handler itself has no enclosing transaction; read back saved state after an uncertain failure.
  • No collection filtering, pagination, ordering or batch result is provided. Parameters on this page describe the supported scalar/encoded input; malformed nested values are not a supported contract.

Side effects

  • Updates the global identity row and the tenant user row, with last_edited and an operation-specific edited_uuid; invalidates the employees cache. Both updates are limited by user ID and the authenticated parent account.
  • Writes an entry in tenant user activity logs. It does not send an email, notification or password-reset message.
  • No verification message is sent, and the target session’s cached email is not explicitly refreshed.

See it in Fieldmotion

CRM1

Open User → Main in CRM1 and edit Email. Filter User_setEmail; the UI sends id and the complete new address.

CRM2

No direct production caller was found in CRM2. Its User layouts use the generic getRequestedDetails/updateData flow instead; do not assume that flow has the same validation or permissions as this legacy route.

Related endpoints

  • User_setName — Update the user’s display name.
  • User_setMeta — Merge one ordinary preference into both identity stores.