---
title: "Return a particular user by email"
method: GET
path: "/v1/user/email/{email}"
tags: ["user"]
---

# Return a particular user by email

`GET /v1/user/email/{email}`

## Path parameters

- `email` string, required

## Response `200`

successful operation

- User
  - `id` string, required — globally unique id
  - `appId` string — if the user is an app user, the id of the app
  - `name` Name, required
    - `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
  - `password` string — password of user (encrypted)
  - `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
  - `type` 'USER' | 'APP' — type 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
  - `bundleInstall` BundleInstall
    - `entities` BundleInstallEntity[], required
      - `entityType` 'ACTION' | 'CALENDAR' | 'CALENDAR_ENTRY' | 'CATEGORY' | 'FIELD' | 'FORM' | 'GROUP' | 'PROFILE_TAB' | 'QUESTION' | 'REPORT' | 'REPORT_CHART' | 'TASK_CONFIG' | 'TEMPLATE' | 'TIME_OFF_POLICY' | 'CONTENT', required
      - `entityId` string, required
      - `originalId` string, required
  - `secrets` object — write-only secrets; the content of these secrets are not retrievable via the external-facing API
  - `activeAt` string — last activity timestamp
  - `loginAt` string — last login timestamp
  - `appRunCheckAt` string — for apps, last time the app was checked for a scheduled sync
  - `loginCount` integer — number of lifetime successful logins
  - `sessionCount` integer — number of lifetime sessions
  - `loginFailCount` integer — number of consecutive failed logins
  - `title` string — job title, if available
  - `remoteIp` string — last IP address used
  - `createId` string — created by user id
  - `createBehalfId` string — created on behalf of user id
  - `createAttribution` Attribution
    - `principalUserId` string
    - `agentUserIds` string[]
    - `eventId` string
    - `aiChatId` string
    - `aiToolUseId` string
    - `channel` 'WEB' | 'MOBILE' | 'SLACK' | 'TEAMS' | 'MCP'
  - `createAt` string — created timestamp
  - `updateId` string — last updated by user id
  - `updateBehalfId` string — last updated on behalf of user id
  - `updateAttribution` Attribution
    - `principalUserId` string
    - `agentUserIds` string[]
    - `eventId` string
    - `aiChatId` string
    - `aiToolUseId` string
    - `channel` 'WEB' | 'MOBILE' | 'SLACK' | 'TEAMS' | 'MCP'
  - `updateAt` string — last updated timestamp
  - `verifyAt` string — email verified timestamp, if the email has been verified
  - `mfas` WebRegisteredCredential[] — list of registered 2FA registered credentials
    - `credentialId` string, required — Credential id
    - `publicKeyBase64` string, required — The public key we're saving
    - `userHandleBase64` string, required — The user handle - a random 64 bits of data
    - `signatureCount` integer, required — This is used to protect against duplicated key attacks
    - `createdAt` string, required — When was this created
  - `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

## Other responses

- `400` — bad request
- `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)
