swagger: '2.0' info: description: REST API for ChartHop version: V1.0.0 title: ChartHop access user API contact: name: ChartHop url: https://www.charthop.com email: support@charthop.com host: localhost schemes: - https - http consumes: - application/json produces: - application/json tags: - name: user paths: /v1/user: get: tags: - user summary: Return all users within an org or across orgs operationId: findUsers consumes: - application/json produces: - application/json parameters: - name: orgId in: query description: Org id to search within required: false type: string - name: ids in: query description: List of user ids to look up required: false type: string - name: from in: query description: User id to start from required: false type: string - name: limit in: query description: Number of results to return required: false type: integer format: int32 - name: sort in: query description: 'Sort by: id, name, email, inviteStatus, activeAt, updateAt. Prepend - for descending (e.g. -activeAt). Without orgId (cross-org admin only), ''activeAt'' takes the legacy iterateAllActive path.' required: false type: string - name: q in: query description: Substring search across name (first/last/preferred) and email required: false type: string - name: inviteStatus in: query description: 'Filter by invite status: JOINED (user has logged in) or INVITED (not yet logged in). NOT_INVITED is not valid here — by definition findUsers returns only users with accounts.' required: false type: string enum: - INVITED - JOINED - NOT_INVITED - name: roleId in: query description: Custom role id to filter by. Requires orgId. required: false type: string - name: returnAccess in: query description: Return access information -- pass a comma-separated list of actions to check (e.g. update,delete). Requires orgId. required: false type: string responses: '200': description: successful operation schema: $ref: '#/definitions/ResultsUser' '400': description: bad request '404': description: not found post: tags: - user summary: Create a new user operationId: createUser consumes: - application/json produces: - application/json parameters: - name: body in: body description: User data to create required: true schema: $ref: '#/definitions/CreateUser' responses: '201': description: user created schema: $ref: '#/definitions/User' '400': description: invalid data '401': description: not authorized '403': description: permission denied /v1/user/assign: patch: tags: - user summary: Assign or remove multiple users a role within an org operationId: assignUsers consumes: - application/json produces: - application/json parameters: - name: body in: body description: User data required: true schema: type: object additionalProperties: $ref: '#/definitions/UpdateUser' responses: '400': description: invalid data '401': description: not authorized '403': description: permission denied '404': description: not found /v1/user/count: get: tags: - user summary: Count users matching the same filters as findUsers, broken down by invite status operationId: countUsers consumes: - application/json produces: - application/json parameters: - name: orgId in: query description: Org id to count within required: true type: string - name: q in: query description: Substring search across name (first/last/preferred) and email required: false type: string - name: inviteStatus in: query description: 'Filter by invite status: JOINED or INVITED. NOT_INVITED is not valid.' required: false type: string enum: - INVITED - JOINED - NOT_INVITED - name: roleId in: query description: Custom role id to filter by required: false type: string responses: '200': description: successful operation schema: $ref: '#/definitions/UserCount' '400': description: bad request '403': description: permission denied '404': description: not found /v1/user/email/{email}: get: tags: - user summary: Return a particular user by email operationId: getUserByEmail consumes: - application/json produces: - application/json parameters: - name: email in: path description: Email required: true type: string responses: '200': description: successful operation schema: $ref: '#/definitions/User' '400': description: bad request '404': description: not found /v1/user/invite: post: tags: - user summary: Create/invite multiple new users operationId: createUsers consumes: - application/json produces: - application/json parameters: - name: body in: body description: User data to create required: true schema: type: array items: $ref: '#/definitions/CreateUser' responses: '201': description: users created schema: type: array uniqueItems: true items: $ref: '#/definitions/User' '400': description: invalid data '401': description: not authorized '403': description: permission denied '404': description: not found /v1/user/login/{email}: get: tags: - user summary: Return the login options for a user operationId: getUserLoginOption consumes: - application/json produces: - application/json parameters: - name: email in: path description: User email required: true type: string - name: orgSlug in: query description: Org slug required: false type: string responses: '200': description: login options returned schema: type: object additionalProperties: {} /v1/user/me: get: tags: - user summary: Return the currently logged in user operationId: getMe consumes: - application/json produces: - application/json responses: '200': description: successful operation schema: $ref: '#/definitions/User' '401': description: unauthorized /v1/user/me/view: get: tags: - user summary: Return the user the user is currently viewing as operationId: getMeView consumes: - application/json produces: - application/json responses: '200': description: successful operation schema: $ref: '#/definitions/User' '401': description: unauthorized /v1/user/person/{personId}: get: tags: - user summary: Return a particular user by its corresponding person id operationId: getUserByPersonId consumes: - application/json produces: - application/json parameters: - name: personId in: path description: Person id to fetch user for required: true type: string - name: orgId in: query description: Org id to search within required: true type: string responses: '200': description: successful operation schema: $ref: '#/definitions/User' '400': description: bad request '404': description: not found /v1/user/sendreset: post: tags: - user summary: Send a password reset email operationId: sendResetEmail consumes: - application/json produces: - application/json parameters: - name: body in: body description: User email address required: true schema: $ref: '#/definitions/EmailRequest' responses: '204': description: email sent '400': description: email not found /v1/user/token: delete: tags: - user summary: Revoke multiple user's access tokens operationId: revokeUsersTokens consumes: - application/json produces: - application/json parameters: - name: body in: body description: User ids required: true schema: type: array items: type: string example: 588f7ee98f138b19220041a7 responses: '400': description: invalid data '401': description: not authorized '403': description: permission denied '404': description: not found /v1/user/{userId}: get: tags: - user summary: Return a particular user by id operationId: getUser consumes: - application/json produces: - application/json parameters: - name: userId in: path description: User id required: true type: string responses: '200': description: successful operation schema: $ref: '#/definitions/User' '400': description: bad request '404': description: not found patch: tags: - user summary: Update an existing user operationId: updateUser consumes: - application/json produces: - application/json parameters: - name: userId in: path description: User id required: true type: string - name: body in: body description: User data to update required: true schema: $ref: '#/definitions/UpdateUser' responses: '204': description: user updated '400': description: invalid data '401': description: not authorized '403': description: permission denied '404': description: not found /v1/user/{userId}/password: post: tags: - user summary: Change a user's password, or switch a user to SSO operationId: changePassword consumes: - application/json produces: - application/json parameters: - name: userId in: path description: User id required: true type: string - name: body in: body required: true schema: $ref: '#/definitions/ChangePasswordRequest' responses: '204': description: password changed '400': description: invalid data '401': description: not authorized '403': description: permission denied '404': description: not found /v1/user/{userId}/token: delete: tags: - user summary: Revoke a user's access token operationId: revokeUserToken consumes: - application/json produces: - application/json parameters: - name: userId in: path description: User id required: true type: string responses: '401': description: unauthorized '404': description: not found /v2/user/invite: post: tags: - user summary: Create/invite multiple new users operationId: inviteUsersToOrg consumes: - application/json produces: - application/json parameters: - name: body in: body required: true schema: $ref: '#/definitions/InviteUsersRequest' responses: '200': description: users created schema: type: array uniqueItems: true items: $ref: '#/definitions/User' '400': description: invalid data '401': description: not authorized '403': description: permission denied '404': description: not found definitions: OrgAccess: type: object required: - orgId - access properties: orgId: type: string description: org id example: 5887a7718f138b6a2a0041a7 personId: type: string description: person id, if this user directly corresponds with a person example: 5887a7718f138b6a2a0041a7 access: type: string description: legacy access permission level enum: - 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 groupIds: type: array description: group ids that the above access applies to uniqueItems: true items: type: string example: 588f7ee98f138b19220041a7 expr: type: string description: expression that the above access applies to expireAt: type: string description: timestamp that this org access will expire roleId: type: string description: the role id that defines the users access example: 5887a7718f138b6a2a0041a7 status: type: string description: Onboarding status of the user in this org enum: - INACTIVE - PREBOARDING - ACTIVATION - ACTIVE - OFFBOARDED homeEmail: type: string description: Personal email address of user, while they are preboarding example: bob@example.com minItems: 0 maxItems: 120 workEmail: type: string description: Work email address of user, once they have started example: robert.doe@example.com minItems: 0 maxItems: 120 workRoleId: type: string description: Active role ID that defines the user's access once they have started example: 67c851da3dd1668c2fdd7e44 TargetedInstruction: type: object required: - filter - instructions properties: filter: type: string description: filter expression matched against the current viewer's person record instructions: type: string description: instructions injected into the chat prompt when filter matches PolicyRuleTarget: type: object properties: userId: type: string personId: type: string example: 588f7ee98f138b19220041a7 channel: type: string email: type: string ResultsUser: type: object required: - data properties: data: type: array items: $ref: '#/definitions/User' next: type: string access: type: array items: $ref: '#/definitions/ResultsAccess' User: type: object required: - id - name properties: id: type: string description: globally unique id example: 588f7ee98f138b19220041a7 appId: type: string description: if the user is an app user, the id of the app example: 588f7ee98f138b19220041a7 name: description: full name of user $ref: '#/definitions/Name' email: type: string description: email address of user example: bob@example.com minItems: 0 maxItems: 120 password: type: string description: password of user (encrypted) minItems: 0 maxItems: 120 orgs: type: array description: list of member orgs with permission levels uniqueItems: true items: $ref: '#/definitions/OrgAccess' imagePath: type: string description: path to full-sized profile image in storage pattern: ^[a-zA-Z0-9._/-]+$ status: type: string description: current status of user enum: - SUPERUSER - NORMAL - INACTIVE - UNINSTALLED type: type: string description: type of user enum: - USER - APP options: type: object description: for apps, options (specific options are specific to the particular app); for users, user-set preferences internalOptions: type: object description: internal (ChartHop controlled) options bundleInstall: description: if this user represents an installed bundle, details on what was installed $ref: '#/definitions/BundleInstall' secrets: type: object description: write-only secrets; the content of these secrets are not retrievable via the external-facing API activeAt: type: string description: last activity timestamp example: '2017-01-24T13:57:52Z' loginAt: type: string description: last login timestamp example: '2017-01-24T13:57:52Z' appRunCheckAt: type: string description: for apps, last time the app was checked for a scheduled sync example: '2024-02-29T09:30:00Z' loginCount: type: integer format: int32 description: number of lifetime successful logins example: '3' sessionCount: type: integer format: int32 description: number of lifetime sessions example: '3' loginFailCount: type: integer format: int32 description: number of consecutive failed logins example: '3' title: type: string description: job title, if available example: CEO remoteIp: type: string description: last IP address used example: 127.0.0.1 createId: type: string description: created by user id example: 588f7ee98f138b19220041a7 createBehalfId: type: string description: created on behalf of user id example: 588f7ee98f138b19220041a7 createAttribution: $ref: '#/definitions/Attribution' createAt: type: string description: created timestamp example: '2017-01-24T13:57:52Z' updateId: type: string description: last updated by user id example: 588f7ee98f138b19220041a7 updateBehalfId: type: string description: last updated on behalf of user id example: 588f7ee98f138b19220041a7 updateAttribution: $ref: '#/definitions/Attribution' updateAt: type: string description: last updated timestamp example: '2017-01-24T13:57:52Z' verifyAt: type: string description: email verified timestamp, if the email has been verified example: '2017-01-24T13:57:52Z' mfas: type: array description: list of registered 2FA registered credentials items: $ref: '#/definitions/WebRegisteredCredential' emailSettings: type: array description: Email settings for the user items: $ref: '#/definitions/UserEmailSetting' sensitive: type: string description: sensitivity level of the user's configuration; only applicable to APP users enum: - GLOBAL - ORG - SENSITIVE - PERSONAL - MANAGER - HIGH - PRIVATE shareAccess: type: array description: users and groups who have access to configure this user; only applicable to APP users items: $ref: '#/definitions/ShareAccess' agentConfig: description: per-user agent configuration overrides $ref: '#/definitions/AiAgentConfig' AiAgentConfig: type: object properties: personality: type: string instructions: type: string guardrails: type: string enableMemory: type: boolean enableMcpServer: type: boolean description: whether this agent exposes an MCP server endpoint for per-user OAuth access enableMcpWrite: type: boolean description: '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: type: boolean description: '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: type: array items: $ref: '#/definitions/PolicyRule' approvalGuidelines: type: string managerJobId: type: string example: 588f7ee98f138b19220041a7 messagingConfig: $ref: '#/definitions/MessagingConfig' contentIds: type: array description: pinned content document IDs; when merging user and app configs, both lists are unioned (not replaced); validate with validateContentIds before persisting items: type: string example: 588f7ee98f138b19220041a7 modelTier: type: string description: requested model tier for the agent; defaults to MEDIUM when not set enum: - HIGH - MEDIUM - LOW targetedInstructions: type: array description: 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 items: $ref: '#/definitions/TargetedInstruction' BundleInstallEntity: type: object required: - entityType - entityId - originalId properties: entityType: type: string enum: - ACTION - CALENDAR - CALENDAR_ENTRY - CATEGORY - FIELD - FORM - GROUP - PROFILE_TAB - QUESTION - REPORT - REPORT_CHART - TASK_CONFIG - TEMPLATE - TIME_OFF_POLICY - CONTENT entityId: type: string example: 588f7ee98f138b19220041a7 originalId: type: string example: 588f7ee98f138b19220041a7 AccessAction: type: object required: - action properties: action: type: string fields: type: array uniqueItems: true items: type: string types: type: array uniqueItems: true items: type: string InviteUsersRequest: type: object required: - createUsers properties: createUsers: type: array items: $ref: '#/definitions/CreateUser' emailSettings: $ref: '#/definitions/WelcomeEmailSettings' ChangePasswordRequest: type: object required: - newPassword properties: newPassword: type: string description: password to change to oldPassword: type: string description: password to change from UpdateUser: type: object properties: appId: type: string description: if the user is an app user, the id of the app example: 588f7ee98f138b19220041a7 name: description: full name of user $ref: '#/definitions/Name' email: type: string description: email address of user example: bob@example.com minItems: 0 maxItems: 120 orgs: type: array description: list of member orgs with permission levels uniqueItems: true items: $ref: '#/definitions/OrgAccess' imagePath: type: string description: path to full-sized profile image in storage pattern: ^[a-zA-Z0-9._/-]+$ status: type: string description: current status of user enum: - SUPERUSER - NORMAL - INACTIVE - UNINSTALLED options: type: object description: for apps, options (specific options are specific to the particular app); for users, user-set preferences internalOptions: type: object description: internal (ChartHop controlled) options secrets: type: object description: write-only secrets; the content of these secrets are not retrievable via the external-facing API emailSettings: type: array description: Email settings for the user items: $ref: '#/definitions/UserEmailSetting' sensitive: type: string description: sensitivity level of the user's configuration; only applicable to APP users enum: - GLOBAL - ORG - SENSITIVE - PERSONAL - MANAGER - HIGH - PRIVATE shareAccess: type: array description: users and groups who have access to configure this user; only applicable to APP users items: $ref: '#/definitions/ShareAccess' agentConfig: description: per-user agent configuration overrides $ref: '#/definitions/AiAgentConfig' Attribution: type: object properties: principalUserId: type: string example: 588f7ee98f138b19220041a7 agentUserIds: type: array items: type: string example: 588f7ee98f138b19220041a7 eventId: type: string example: 588f7ee98f138b19220041a7 aiChatId: type: string example: 588f7ee98f138b19220041a7 aiToolUseId: type: string channel: type: string enum: - WEB - MOBILE - SLACK - TEAMS - MCP BundleInstall: type: object required: - entities properties: entities: type: array items: $ref: '#/definitions/BundleInstallEntity' ResultsAccess: type: object required: - allowed properties: ids: type: array uniqueItems: true items: type: string example: 588f7ee98f138b19220041a7 allowed: type: array uniqueItems: true items: $ref: '#/definitions/AccessAction' EmailRequest: type: object required: - email properties: email: type: string description: email address example: example@example.com MessagingConfig: type: object properties: slackAppId: type: string slackClientId: type: string slackBotUserId: type: string WebRegisteredCredential: type: object required: - credentialId - publicKeyBase64 - userHandleBase64 - signatureCount - createdAt properties: credentialId: type: string description: Credential id publicKeyBase64: type: string description: The public key we're saving userHandleBase64: type: string description: The user handle - a random 64 bits of data signatureCount: type: integer format: int64 description: This is used to protect against duplicated key attacks createdAt: type: string description: When was this created UserEmailSetting: type: object required: - category - subscribed properties: category: type: string description: Category of emails example: ADMINISTRATIVE enum: - ADMINISTRATIVE - BILLING - DATA_IMPORT_AND_SYNC_STATUS - TRIAL_REMINDERS - APPROVAL_NOTIFICATIONS subscribed: type: boolean description: Is user subscribed to the category of emails CreateUser: type: object required: - orgs properties: appId: type: string description: if the user is an app user, the id of the app example: 588f7ee98f138b19220041a7 name: description: full name of user $ref: '#/definitions/Name' email: type: string description: email address of user example: bob@example.com minItems: 0 maxItems: 120 orgs: type: array description: list of member orgs with permission levels uniqueItems: true items: $ref: '#/definitions/OrgAccess' imagePath: type: string description: path to full-sized profile image in storage pattern: ^[a-zA-Z0-9._/-]+$ status: type: string description: current status of user enum: - SUPERUSER - NORMAL - INACTIVE - UNINSTALLED type: type: string description: type of user enum: - USER - APP options: type: object description: for apps, options (specific options are specific to the particular app); for users, user-set preferences internalOptions: type: object description: internal (ChartHop controlled) options secrets: type: object description: write-only secrets; the content of these secrets are not retrievable via the external-facing API emailSettings: type: array description: Email settings for the user items: $ref: '#/definitions/UserEmailSetting' sensitive: type: string description: sensitivity level of the user's configuration; only applicable to APP users enum: - GLOBAL - ORG - SENSITIVE - PERSONAL - MANAGER - HIGH - PRIVATE shareAccess: type: array description: users and groups who have access to configure this user; only applicable to APP users items: $ref: '#/definitions/ShareAccess' agentConfig: description: per-user agent configuration overrides $ref: '#/definitions/AiAgentConfig' ShareAccess: type: object required: - access properties: access: type: string description: access permission level enum: - NONE - LIMITED_READ - LIMITED_WRITE - STANDARD_READ - STANDARD_WRITE - COMPENSATION_READ - FULL_READ - COMP_PLANNING_PARTICIPANT - COMPENSATION_WRITE - WRITE - COMPENSATION_OWNER - OWNER userId: type: string description: user id example: 5887a7718f138b6a2a0041a7 groupId: type: string description: group id example: 5887a7718f138b6a2a0041a7 fields: type: string description: fields example: name,image,title WelcomeEmailSettings: type: object required: - isEnabled - welcomeEmailSubject - welcomeEmailButtonLabel - welcomeEmailBody properties: isEnabled: type: boolean description: Whether to send a welcome email welcomeEmailSubject: type: string description: Subject welcomeEmailButtonLabel: type: string description: Button label welcomeEmailBody: type: string description: Body PolicyRule: type: object properties: allow: type: array description: allow rules example: '[''job:read'', ''person.read'']' items: type: string deny: type: array description: deny rules example: '[''job:read'', ''person.read'']' items: type: string categories: type: array description: categories the rule is limited to example: '[''Compensation'', ''Stock Grants'']' items: type: string fields: type: array description: fields the rule is limited to example: '[''base'']' items: type: string departmentIds: type: array description: departments the rule is limited to uniqueItems: true items: type: string example: 588f7ee98f138b19220041a7 filter: type: string description: custom filter the rule is limited to example: department:engineering and under:me directions: type: array description: directions that the rule applies to -- either self or under items: type: string types: type: array description: types that the rule applies to items: type: string targets: type: array description: targets allowed for messaging (email addresses, chat channels, user ids) items: $ref: '#/definitions/PolicyRuleTarget' visibleSensitive: type: array description: if specified, controls visibility of sensitive entities -- for example, ['Manager Shared', 'Manager Only'] items: type: string fieldsSensitive: type: array description: if specified, controls applicability of fields by sensitivity -- for example, ['Manager Shared', 'Manager Only'] items: type: string Name: type: object required: - last properties: first: type: string description: first name example: Jane minItems: 0 maxItems: 80 middle: type: string description: middle name example: Quidditch minItems: 0 maxItems: 80 last: type: string description: last name example: Public minItems: 0 maxItems: 80 pref: type: string description: preferred first name example: JQ minItems: 0 maxItems: 80 prefLast: type: string description: preferred last name example: Smith minItems: 0 maxItems: 80 UserCount: type: object required: - totalCount - joinedCount - invitedCount properties: totalCount: type: integer format: int64 joinedCount: type: integer format: int64 invitedCount: type: integer format: int64