---
title: "Update an existing user"
method: PATCH
path: "/v1/user/{userId}"
tags: ["user"]
---

# Update an existing user

`PATCH /v1/user/{userId}`

## Path parameters

- `userId` string, required

## Request body

- UpdateUser
  - `appId` string — if the user is an app user, the id of the app
  - `name` Name
    - `first` string — first name
    - `middle` string — middle name
    - `last` string, required — last name
    - `pref` string — preferred first name
    - `prefLast` string — preferred last name
  - `email` string — email address of user
  - `orgs` OrgAccess[] — list of member orgs with permission levels
    - `orgId` string, required — org id
    - `personId` string — person id, if this user directly corresponds with a person
    - `access` 'NONE' | 'PREBOARDING' | 'VIEW' | 'LIMITED' | 'MEMBER_LIMITED_COMP' | 'MEMBER' | 'CUSTOM' | 'TECH_OWNER' | 'TIMEOFF' | 'CONTACT' | 'COMP_CASH' | 'COMP_EQUITY' | 'COMP_ALL' | 'RECRUIT_SENSITIVE' | 'RECRUIT_PRIMARY' | 'SENSITIVE_LIMITED_COMP' | 'SENSITIVE' | 'PRIMARY' | 'PEOPLE_OPS_ADMIN' | 'PEOPLE_OPS_ADMIN_NO_COMP_DATA' | 'PEOPLE_OPS_ADMIN_NO_SENSITIVE_DATA' | 'OWNER', required — legacy access permission level
    - `groupIds` string[] — group ids that the above access applies to
    - `expr` string — expression that the above access applies to
    - `expireAt` string — timestamp that this org access will expire
    - `roleId` string — the role id that defines the users access
    - `policyIds` string[] — additional policy ids, applied additively on top of the policies defined by the role
    - `status` 'INACTIVE' | 'PREBOARDING' | 'ACTIVATION' | 'ACTIVE' | 'OFFBOARDED' — Onboarding status of the user in this org
    - `homeEmail` string — Personal email address of user, while they are preboarding
    - `workEmail` string — Work email address of user, once they have started
    - `workRoleId` string — Active role ID that defines the user's access once they have started
  - `imagePath` string — path to full-sized profile image in storage
  - `status` 'SUPERUSER' | 'NORMAL' | 'INACTIVE' | 'UNINSTALLED' — current status of user
  - `options` object — for apps, options (specific options are specific to the particular app); for users, user-set preferences
  - `internalOptions` object — internal (ChartHop controlled) options
  - `secrets` object — write-only secrets; the content of these secrets are not retrievable via the external-facing API
  - `emailSettings` UserEmailSetting[] — Email settings for the user
    - `category` 'ADMINISTRATIVE' | 'BILLING' | 'DATA_IMPORT_AND_SYNC_STATUS' | 'TRIAL_REMINDERS' | 'APPROVAL_NOTIFICATIONS', required — Category of emails
    - `subscribed` boolean, required — Is user subscribed to the category of emails
  - `sensitive` 'GLOBAL' | 'ORG' | 'SENSITIVE' | 'PERSONAL' | 'MANAGER' | 'HIGH' | 'PRIVATE' — sensitivity level of the user's configuration; only applicable to APP users
  - `shareAccess` ShareAccess[] — users and groups who have access to configure this user; only applicable to APP users
    - `access` 'NONE' | 'LIMITED_READ' | 'LIMITED_WRITE' | 'STANDARD_READ' | 'STANDARD_WRITE' | 'COMPENSATION_READ' | 'FULL_READ' | 'COMP_PLANNING_PARTICIPANT' | 'COMPENSATION_WRITE' | 'WRITE' | 'COMPENSATION_OWNER' | 'OWNER', required — access permission level
    - `userId` string — user id
    - `groupId` string — group id
    - `fields` string — fields
  - `agentConfig` AiAgentConfig
    - `personality` string
    - `instructions` string
    - `guardrails` string
    - `enableMemory` boolean
    - `enableMcpServer` boolean — whether this agent exposes an MCP server endpoint for per-user OAuth access
    - `enableMcpWrite` boolean — whether this agent's MCP server may invoke write/mutating tools (e.g. a non-read-only AskAgent delegation). Read-only by default: when unset or false, a tool that mutates on the call is rejected at the MCP edge regardless of the agent's role/policy. This is defense in depth layered on top of the role, never a grant beyond it.
    - `isExternal` boolean — whether this agent is an external (non-ChartHop) client, e.g. Claude Code or ChatGPT. External agents have no ChartHop-side prompt/behavior config: only permissions, MCP, and activity are configurable.
    - `approvedPolicyRules` PolicyRule[]
      - `allow` string[] — allow rules
      - `deny` string[] — deny rules
      - `categories` string[] — categories the rule is limited to
      - `fields` string[] — fields the rule is limited to
      - `departmentIds` string[] — departments the rule is limited to
      - `filter` string — custom filter the rule is limited to
      - `directions` string[] — directions that the rule applies to -- either self or under
      - `types` string[] — types that the rule applies to
      - `targets` PolicyRuleTarget[] — targets allowed for messaging (email addresses, chat channels, user ids)
        - `userId` string
        - `personId` string
        - `channel` string
        - `email` string
      - `visibleSensitive` string[] — if specified, controls visibility of sensitive entities -- for example, ['Manager Shared', 'Manager Only']
      - `fieldsSensitive` string[] — if specified, controls applicability of fields by sensitivity -- for example, ['Manager Shared', 'Manager Only']
    - `approvalGuidelines` string
    - `managerJobId` string
    - `messagingConfig` MessagingConfig
      - `slackAppId` string
      - `slackClientId` string
      - `slackBotUserId` string
    - `contentIds` string[] — pinned content document IDs; when merging user and app configs, both lists are unioned (not replaced); validate with validateContentIds before persisting
    - `modelTier` 'HIGH' | 'MEDIUM' | 'LOW' — requested model tier for the agent; defaults to MEDIUM when not set
    - `targetedInstructions` TargetedInstruction[] — audience-scoped instruction snippets injected into the chat prompt when the filter matches the current viewer's person record; size and filter syntax are checked by AgentValidationService before persisting
      - `filter` string, required — filter expression matched against the current viewer's person record
      - `instructions` string, required — instructions injected into the chat prompt when filter matches

## Response `204`

user updated

## Other responses

- `400` — invalid data
- `401` — not authorized
- `403` — permission denied
- `404` — not found

---

[API](https://skmtc.net/charthop/apis/charthop-api.md) · [All operations](https://skmtc.net/charthop/apis/charthop-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/charthop/charthop-api/versions/50a1edd6b27e/schema)
