@lap v0.3
# Machine-readable API spec. Each @endpoint block is one API call.
@api Authentication and Identity Management
@base https://api.frontegg.com/identity
@version 1.0
@auth Bearer bearer
@endpoints 307
@hint download_for_search
@toc resources(307)

@endpoint POST /resources/auth/v2/api-token
@desc Authenticate using API token
@required {clientId: str, secret: str}
@returns(200) {access_token: str, refresh_token: str, expires_in: num, expires: str}

@endpoint POST /resources/auth/v2/api-token/token/refresh
@desc Refresh API token
@required {refreshToken: str}
@returns(200) {access_token: str, refresh_token: str, expires_in: num, expires: str}

@endpoint POST /resources/tenants/access-tokens/v1
@desc Create account (tenant) access token
@required {frontegg-tenant-id: str # The account (tenant) ID identifier}
@optional {description: str, expiresInMinutes: num # Token expiration time in minutes. In case of undefined, the token won't be expired, roleIds: [str] # Array of role IDs to attach to the token}
@returns(201) {id: str, description: str, createdAt: str(date-time), secret: str, expires: str(date-time), roleIds: [str], createdByUserId: str?}

@endpoint GET /resources/tenants/access-tokens/v1
@desc Get account (tenant) access tokens
@required {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200) {accessTokens: [map]}

@endpoint DELETE /resources/tenants/access-tokens/v1/{id}
@desc Delete account (tenant) access token
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, id: str}
@returns(200)

@endpoint POST /resources/tenants/api-tokens/v1
@desc Create client credentials token
@required {frontegg-tenant-id: str # The account (tenant) ID identifier}
@optional {metadata: map # Extra data that will be encoded as part of the JWT, description: str, roleIds: [str] # Array of role Ids. Either this or permissionIds must be provided, but not both., permissionIds: [str] # Array of permission Ids. Either this or roleIds must be provided, but not both. roleIds will override permissionIds., expiresInMinutes: num # Token expiration time in minutes. In case of undefined, the token won't be expired}
@returns(201) {clientId: str, description: str?, tenantId: str, secret: str, createdByUserId: str?, metadata: map, createdAt: str(date-time), permissionIds: [str], roleIds: [str], expires: str(date-time)}

@endpoint GET /resources/tenants/api-tokens/v1
@desc Get client credentials tokens
@required {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint DELETE /resources/tenants/api-tokens/v1/{id}
@desc Delete client credentials token
@required {id: str, frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint PATCH /resources/tenants/api-tokens/v1/{id}
@desc Update client credentials token
@required {id: str, frontegg-tenant-id: str # The account (tenant) ID identifier}
@optional {metadata: map # Extra data that will be encoded as part of the JWT, description: str, roleIds: [str] # Array of role Ids, permissionIds: [str] # Array of permission Ids}
@returns(200) {clientId: str, description: str?, tenantId: str, createdByUserId: str?, metadata: map, createdAt: str(date-time), permissionIds: [str], roleIds: [str], expires: str(date-time)}

@endpoint POST /resources/tenants/api-tokens/v2
@desc Create client credentials token
@required {frontegg-tenant-id: str # The account (tenant) ID identifier}
@optional {metadata: map # Extra data that will be encoded as part of the JWT, description: str, roleIds: [str] # Array of role Ids. Either this or permissionIds must be provided, but not both., permissionIds: [str] # Array of permission Ids. Either this or roleIds must be provided, but not both. roleIds will override permissionIds., expiresInMinutes: num # Token expiration time in minutes. In case of undefined, the token won't be expired}
@returns(201) {clientId: str, description: str?, tenantId: str, secret: str, createdByUserId: str?, metadata: map, createdAt: str(date-time), permissionIds: [str], roleIds: [str], expires: str(date-time)}

@endpoint GET /resources/tenants/invites/v1/user
@desc Get account (tenant) invite of user
@required {frontegg-user-id: str # The user ID identifier, frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200) {id: str, vendorId: str, tenantId: str, userId: str, token: str, expires: str(date-time), shouldSendEmail: bool, name: str, roleIds: [str]}

@endpoint POST /resources/tenants/invites/v1/user
@desc Create account (tenant) invite for user
@required {frontegg-user-id: str # The user ID identifier, frontegg-tenant-id: str # The account (tenant) ID identifier, expiresInMinutes: num, shouldSendEmail: bool}
@returns(201) {id: str, vendorId: str, tenantId: str, userId: str, token: str, expires: str(date-time), shouldSendEmail: bool, name: str, roleIds: [str]}

@endpoint DELETE /resources/tenants/invites/v1/user
@desc Delete account (tenant) invite of user
@required {frontegg-user-id: str # The user ID identifier, frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint PATCH /resources/tenants/invites/v1/user
@desc Update account (tenant) invite of user
@required {frontegg-user-id: str # The user ID identifier, frontegg-tenant-id: str # The account (tenant) ID identifier}
@optional {expiresInMinutes: num, shouldSendEmail: bool}
@returns(200) {id: str, vendorId: str, tenantId: str, userId: str, token: str, expires: str(date-time), shouldSendEmail: bool, name: str, roleIds: [str]}

@endpoint POST /resources/tenants/invites/v1/verify
@desc Verify account (tenant) invite
@required {token: str}
@returns(200) {id: str, vendorId: str, tenantId: str, userId: str, token: str, expires: str(date-time), shouldSendEmail: bool, name: str, roleIds: [str]}

@endpoint GET /resources/tenants/invites/v1/configuration
@desc Get account (tenant) invite configuration
@returns(200) {tenantInvitationsAllowed: bool, emailsEnabled: bool}

@endpoint POST /resources/tenants/invites/v2/user
@desc Create tenant invite with roles for user
@required {expiresInMinutes: num, shouldSendEmail: bool, roleIds: [str] # Array of role IDs to assign to invited users}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens, frontegg-user-id: str # The user identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)
@returns(201) {id: str, vendorId: str, tenantId: str, userId: str, token: str, expires: str(date-time), shouldSendEmail: bool, name: str, roleIds: [str]}

@endpoint POST /resources/tenants/invites/v1
@desc Create account (tenant) invite
@required {tenantId: str}
@optional {userId: str, expiresInMinutes: num, shouldSendEmail: bool, roleIds: [str] # Array of role IDs to assign to invited users}
@returns(201) {id: str, vendorId: str, tenantId: str, userId: str, token: str, expires: str(date-time), shouldSendEmail: bool, name: str, roleIds: [str]}

@endpoint GET /resources/tenants/invites/v1/all
@desc Get all account (tenant) invites
@returns(200)

@endpoint DELETE /resources/tenants/invites/v1/token/{id}
@desc Delete an account (tenant) invite
@required {id: str}
@returns(200)

@endpoint GET /resources/configurations/v1/activation/strategies
@desc Get activation strategies
@returns(200) {strategy: str, codeExpiration: num} # Retrieve the current account activation strategies configured in your environment.

@endpoint POST /resources/configurations/v1/activation/strategies
@desc Create or update activation strategy
@required {strategy: str(code/link)}
@optional {codeExpiration: num}
@returns(200) Create a new activation strategy or update the existing activation strategy for your environment.

@endpoint GET /resources/configurations/v1/invitation/strategies
@desc Get invitation strategies
@returns(200) {strategy: str, codeExpiration: num} # Retrieve the current invitation strategies configured in your environment.

@endpoint POST /resources/configurations/v1/invitation/strategies
@desc Create or update invitation strategy
@optional {codeExpiration: num}
@returns(200) Create a new invitation strategy or update the existing invitation strategy for your environment.

@endpoint GET /resources/roles/v2
@desc Get roles v2
@required {_sortBy: str(key/name/description/isDefault/firstUserRole/level/updatedAt/createdAt/permissions/userTenants/groups)}
@optional {_limit: num=50, _levels: [num], _tenantIds: [str], _offset: num=0 # The page number to retrieve. For example, use 0 for the first page, 1 for the second page., _order: str(ASC/DESC), _filter: str, frontegg-tenant-id: str # For relating a role to a specific account (tenant), use `get accounts (tenants)` API to find the account (tenant) Ids}
@returns(200)

@endpoint POST /resources/roles/v2
@desc Create a new role
@required {key: str, name: str, baseRoleId: str # Role level of the new role will be based on this parameter, permissionIds: [str]}
@optional {frontegg-tenant-id: str # For relating a role to a specific account (tenant), use `get accounts (tenants)` API to find the account (tenant) Ids, description: str, isDefault: bool # This role will be assigned for every user that will be added without specified roles}
@returns(200) {id: str, vendorId: str, tenantId: str, key: str, name: str, description: str, isDefault: bool, permissions: [str]}

@endpoint GET /resources/roles/v2/distinct-levels
@desc Get distinct levels of roles
@optional {frontegg-tenant-id: str # For relating a role to a specific account (tenant), use `get accounts (tenants)` API to find the account (tenant) Ids}
@returns(200)

@endpoint GET /resources/roles/v2/distinct-tenants
@desc Get distinct assigned accounts (tenants) of roles
@returns(200)

@endpoint POST /resources/approval-flows/v1
@desc Create approval flow
@required {name: str, channels: map{email!: bool, sms!: bool}, configuration: map{autoApproveInMinutes: num, reminderIntervalMinutes: num, notifyOnDecisions: bool, timeoutMinutes: num, webhookUrl: str}, steps: [map{approverSelectors!: map, configuration!: map, stepOrder!: num}]}
@optional {description: str, isActive: bool}
@returns(200) {id: str, vendorId: str, tenantId: str, name: str, description: str, isActive: bool, channels: map, configuration: map{autoApproveInMinutes: num, reminderIntervalMinutes: num, notifyOnDecisions: bool, logging: bool, timeoutMinutes: num, webhookUrl: str}, steps: [map], createdAt: str(date-time), updatedAt: str(date-time)}
@returns(201) {id: str, vendorId: str, tenantId: str, name: str, description: str, isActive: bool, channels: map, configuration: map{autoApproveInMinutes: num, reminderIntervalMinutes: num, notifyOnDecisions: bool, logging: bool, timeoutMinutes: num, webhookUrl: str}, steps: [map], createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint GET /resources/approval-flows/v1
@desc Get approval flows
@returns(200) {items: [map], total: num}

@endpoint GET /resources/approval-flows/v1/{id}
@desc Get approval flow by ID
@required {id: str}
@returns(200) {id: str, vendorId: str, tenantId: str, name: str, description: str, isActive: bool, channels: map, configuration: map{autoApproveInMinutes: num, reminderIntervalMinutes: num, notifyOnDecisions: bool, logging: bool, timeoutMinutes: num, webhookUrl: str}, steps: [map], createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint PATCH /resources/approval-flows/v1/{id}
@desc Update approval flow
@required {id: str}
@optional {name: str, description: str, isActive: bool, channels: map{email!: bool, sms!: bool}, configuration: map{autoApproveInMinutes: num, reminderIntervalMinutes: num, notifyOnDecisions: bool, timeoutMinutes: num, webhookUrl: str}, steps: [map{approverSelectors!: map, configuration!: map, stepOrder!: num}]}
@returns(200) {id: str, vendorId: str, tenantId: str, name: str, description: str, isActive: bool, channels: map, configuration: map{autoApproveInMinutes: num, reminderIntervalMinutes: num, notifyOnDecisions: bool, logging: bool, timeoutMinutes: num, webhookUrl: str}, steps: [map], createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint DELETE /resources/approval-flows/v1/{id}
@desc Delete approval flow
@required {id: str}
@returns(200)
@returns(204)

@endpoint POST /resources/approval-flows/v1/approver-action
@desc Approver action
@required {approved: bool, approvalFlowExecutionId: str, approverId: str, approvalFlowStepId: str}
@returns(200)

@endpoint GET /resources/approval-flows/v1/execution-data
@desc Get approval flow execution data
@required {approvalFlowExecutionId: str, approverId: str, approvalFlowStepId: str}
@returns(200) {approvalFlowName: str, approvalFlowDescription: str, requester: str, approvalFlowRequestDate: str(date-time), executionData: map}

@endpoint POST /resources/approval-flows/v1/{id}/execute
@desc Execute approval flow
@required {id: str, frontegg-user-id: str # The user ID}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens, executionData: map, webhookUrl: str}
@returns(200)

@endpoint POST /resources/approval-flows/v1/step-up/execute
@desc Execute step up approval flow
@required {frontegg-user-id: str # The user ID}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens, executionData: map, webhookUrl: str}
@returns(200)

@endpoint POST /resources/configurations/v1
@desc Update identity management configuration
@optional {defaultTokenExpiration: num, defaultRefreshTokenExpiration: num, cookieSameSite: str(STRICT/LAX/NONE), machineToMachineAuthStrategy: str(ClientCredentials/AccessToken), allowSignups: bool, apiTokensEnabled: bool, allowOverridePasswordComplexity: bool, allowOverridePasswordExpiration: bool, allowOverrideEnforcePasswordHistory: bool, jwtAlgorithm: str(HS256/RS256), allowNotVerifiedUsersLogin: bool, forcePermissions: bool, addSamlAttributesToJwt: bool, authStrategy: str(Code/EmailAndPassword/MagicLink/NoLocalAuthentication/SmsCode), defaultPasswordlessTokenExpiration: num, forceSameDeviceOnAuth: bool, allowTenantInvitations: bool, rotateRefreshTokens: bool, skipTenantValidation: bool, addRolesToJwt: bool, addPermissionsToJwt: bool, allowCustomLoginTenantSwitch: bool}
@returns(201) {id: str, defaultTokenExpiration: num, defaultRefreshTokenExpiration: num, publicKey: str, cookieSameSite: str, allowSignups: bool, apiTokensEnabled: bool, allowOverridePasswordComplexity: bool, allowOverridePasswordExpiration: bool, allowOverrideEnforcePasswordHistory: bool, jwtAlgorithm: str, jwtSecret: str, allowNotVerifiedUsersLogin: bool, forcePermissions: bool, authStrategy: str, defaultPasswordlessTokenExpiration: num, forceSameDeviceOnAuth: bool, allowTenantInvitations: bool, rotateRefreshTokens: bool, machineToMachineAuthStrategy: str, addRolesToJwt: bool, addPermissionsToJwt: bool, refreshTokensRotationLimit: num, addSamlAttributesToJwt: bool, allowCustomLoginTenantSwitch: bool}

@endpoint GET /resources/configurations/v1
@desc Get identity management configuration
@returns(200) {id: str, defaultTokenExpiration: num, defaultRefreshTokenExpiration: num, publicKey: str, cookieSameSite: str, allowSignups: bool, apiTokensEnabled: bool, allowOverridePasswordComplexity: bool, allowOverridePasswordExpiration: bool, allowOverrideEnforcePasswordHistory: bool, jwtAlgorithm: str, jwtSecret: str, allowNotVerifiedUsersLogin: bool, forcePermissions: bool, authStrategy: str, defaultPasswordlessTokenExpiration: num, forceSameDeviceOnAuth: bool, allowTenantInvitations: bool, rotateRefreshTokens: bool, machineToMachineAuthStrategy: str, addRolesToJwt: bool, addPermissionsToJwt: bool, refreshTokensRotationLimit: num, addSamlAttributesToJwt: bool, allowCustomLoginTenantSwitch: bool}

@endpoint POST /resources/configurations/v1/captcha-policy
@desc Create captcha policy
@required {enabled: bool, siteKey: str, secretKey: str, minScore: num}
@optional {ignoredEmails: [str] # Captcha validation will be skipped for those emails.}
@returns(201) {id: str, siteKey: str, secretKey: str, enabled: bool, minScore: num, ignoredEmails: [str], createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint PUT /resources/configurations/v1/captcha-policy
@desc Update captcha policy
@required {enabled: bool, siteKey: str, secretKey: str, minScore: num}
@optional {ignoredEmails: [str] # Captcha validation will be skipped for those emails.}
@returns(200) {id: str, siteKey: str, secretKey: str, enabled: bool, minScore: num, ignoredEmails: [str], createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint GET /resources/configurations/v1/captcha-policy
@desc Get captcha policy
@returns(200) {id: str, siteKey: str, secretKey: str, enabled: bool, minScore: num, ignoredEmails: [str], createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint GET /resources/configurations/v1/jwt-template-targeting
@desc Get JWT template targeting configuration
@returns(200) {id: str, createdAt: str(date-time), updatedAt: str(date-time), targeting: map}

@endpoint POST /resources/configurations/v1/jwt-template-targeting
@desc Create JWT template targeting configuration
@optional {rules: [map{conditionLogic!: str, conditions!: [map], treatment!: str}]}
@returns(201) {id: str, createdAt: str(date-time), updatedAt: str(date-time), targeting: map}

@endpoint PUT /resources/configurations/v1/jwt-template-targeting
@desc Update or create JWT template targeting configuration
@optional {rules: [map{conditionLogic!: str, conditions!: [map], treatment!: str}]}
@returns(200)

@endpoint PATCH /resources/configurations/v1/jwt-template-targeting/{id}
@desc Update JWT template targeting configuration by ID
@required {id: str}
@optional {rules: [map{conditionLogic!: str, conditions!: [map], treatment!: str}]}
@returns(200)

@endpoint DELETE /resources/configurations/v1/jwt-template-targeting/{id}
@desc Delete JWT template targeting configuration by ID
@required {id: str}
@returns(200)

@endpoint POST /resources/jwt-templates/v1
@desc Create JWT template
@required {key: str # Unique key for the template, name: str # Name of the template, expiration: num # Token expiration time in seconds, algorithm: str(RS256/HS256) # JWT signing algorithm, templateSchema: any # JWT template schema}
@optional {description: str # Description of the template}
@returns(201) {id: str, vendorId: str, key: str, name: str, description: str?, expiration: num, algorithm: str, templateSchema: any, createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint GET /resources/jwt-templates/v1
@desc Get all JWT templates
@optional {keys: [str] # Filter by template keys, ids: [str] # Filter by template IDs, _limit: num # Maximum number of items to return, _offset: num # The page number to retrieve. For example, use 0 for the first page, 1 for the second page., _sortBy: str(id/key/name/createdAt/updatedAt) # Field to sort by, _order: str(ASC/DESC) # Sort order}
@returns(200)

@endpoint GET /resources/jwt-templates/v1/{id}
@desc Get JWT template by ID
@required {id: str}
@returns(200) {id: str, vendorId: str, key: str, name: str, description: str?, expiration: num, algorithm: str, templateSchema: any, createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint PUT /resources/jwt-templates/v1/{id}
@desc Update JWT template
@required {id: str}
@optional {key: str # Unique key for the template, name: str # Name of the template, description: str # Description of the template, expiration: num # Token expiration time in seconds, algorithm: str(RS256/HS256) # JWT signing algorithm, templateSchema: any # JWT template schema}
@returns(200) {id: str, vendorId: str, key: str, name: str, description: str?, expiration: num, algorithm: str, templateSchema: any, createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint DELETE /resources/jwt-templates/v1/{id}
@desc Delete JWT template
@required {id: str}
@returns(204)

@endpoint GET /resources/configurations/v1/basic
@desc Get identity management configuration
@returns(200) {forcePermissions: bool, machineToMachineAuthStrategy: str}

@endpoint POST /resources/sso/custom/v1
@desc Create custom oauth provider
@required {type: str, clientId: str, secret: str, redirectUrl: str, authorizationUrl: str, tokenUrl: str, userInfoUrl: str, scopes: str, ssoLogoUrl: str, displayName: str, active: bool}
@returns(200)

@endpoint GET /resources/sso/custom/v1
@desc Get custom oauth provider
@returns(200)

@endpoint PATCH /resources/sso/custom/v1/{id}
@desc Update custom oauth provider
@required {id: str}
@optional {type: str, clientId: str, secret: str, redirectUrl: str, authorizationUrl: str, tokenUrl: str, userInfoUrl: str, scopes: str, ssoLogoUrl: str, displayName: str, active: bool}
@returns(200)

@endpoint DELETE /resources/sso/custom/v1/{id}
@desc Delete custom oauth provider
@required {id: str}
@returns(200)

@endpoint POST /resources/migrations/v1/auth0
@desc Migrate from Auth0
@required {domain: str, clientId: str, secret: str, tenantIdFieldName: str # The field name that the tenant ID will be taken from under app metadata}
@optional {isTenantIdOnUserMetadata: bool # If you would like to take tenant ID from user metadata, set this field to true}
@returns(201)

@endpoint POST /resources/migrations/v1/local
@desc Migrate a single user
@required {tenantId: str # The tenant id of the user, email: str # The email of the user. If not provided, the username is required}
@optional {name: str # The name of the user, profilePictureUrl: str # The profile picture url of the user, passwordHash: str # The password hash. For SCrypt should include the salt and key seperated by the salt separator, passwordHashType: str(bcrypt/scrypt/firebase-scrypt/pbkdf2/argon2/sha256/sha1), passwordHashConfig: str # Stringified JSON Hashing config for the migrated password. For SCrypt should be formatted as { saltSeparator, N, r, p, keyLen }. For FirebaseScrypt should be formatted as { memCost, rounds, saltSeparator, signerKey }, authenticatorAppMfaSecret: str # The authenticator app MFA secret, phoneNumber: str # phoneNumber can be used both for login with SMS and for MFA This auto-enrolls the user in MFA, prompting them at first login (regardless of tenant/vendor MFA settings). The required format is an area code + number, no spaces. For example: "+16037184056" The number must be unique, phoneNumberType: str(auth/mfa), provider: str(local/saml/google/github/facebook/microsoft/scim2/slack/apple)=local, metadata: str # Stringified JSON object, roleIds: [str]= # Role ids of the migrated users. If not provided, the user will be assigned the default roles, vendorMetadata: str # Extra vendor-only data. stringified JSON object, externalId: str # The external id of the user, username: str # The username of the user. If not provided, the email is required. Maximum length is 255 characters., verifyUser: bool=false # Whether to verify the user as part of the migration process. If this is set to false, another call is required for the verify user API}
@returns(201) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint POST /resources/migrations/v1/local/bulk
@desc Migrate users in bulk
@required {users: [map{tenantId!: str, name: str, profilePictureUrl: str, passwordHash: str, passwordHashType: str, passwordHashConfig: str, authenticatorAppMfaSecret: str, phoneNumber: str, phoneNumberType: str, provider: str, metadata: str, roleIds: [str], vendorMetadata: str, externalId: str, username: str, email!: str, verifyUser: bool}]}
@returns(202) {migrationId: str}

@endpoint GET /resources/migrations/v1/local/bulk/status/{migrationId}
@desc Check status of bulk migration
@required {migrationId: str}
@returns(200)

@endpoint POST /resources/migrations/v2/local/bulk
@desc Migrate vendor users in bulk
@required {users: [map{tenantId!: str, name: str, profilePictureUrl: str, passwordHash: str, passwordHashType: str, passwordHashConfig: str, authenticatorAppMfaSecret: str, phoneNumber: str, phoneNumberType: str, provider: str, metadata: str, roleIds: [str], vendorMetadata: str, externalId: str, username: str, emails: [map]}]}
@returns(202) {migrationId: str}

@endpoint GET /resources/configurations/v1/delegation
@desc Get delegation configuration
@returns(200) {enabled: bool}

@endpoint POST /resources/configurations/v1/delegation
@desc Create or update delegation configuration
@optional {enabled: bool # Used to enable or disable delegation for access tokens created using Token Exchange.}
@returns(200)

@endpoint POST /resources/configurations/restrictions/v1/email-domain
@desc Create domain restriction
@required {domain: str, type: str(ALLOW/BLOCK)}
@returns(201) {id: str, domain: str, type: str}

@endpoint GET /resources/configurations/restrictions/v1/email-domain
@desc Get domain restrictions
@returns(200)

@endpoint GET /resources/configurations/restrictions/v1/email-domain/config
@desc Get domain restrictions
@returns(200) {active: bool, listType: str, blockPublicDomains: bool}

@endpoint POST /resources/configurations/restrictions/v1/email-domain/config
@desc Change domain restrictions config list type and toggle it off/on
@required {active: bool}
@optional {blockPublicDomains: bool, type: str(ALLOW/BLOCK)}
@returns(201) {active: bool, listType: str, blockPublicDomains: bool}

@endpoint DELETE /resources/configurations/restrictions/v1/email-domain/{id}
@desc Delete domain restriction
@required {id: str}
@returns(200)

@endpoint POST /resources/configurations/restrictions/v1/email-domain/replace-bulk
@desc Replace bulk domain restriction
@required {type: str(ALLOW/BLOCK), domains: [str]}
@returns(201)

@endpoint POST /resources/mail/v1/configurations
@desc Create or update configuration
@required {secret: str}
@returns(200)
@returns(201)

@endpoint GET /resources/mail/v1/configurations
@desc Get configuration
@returns(200) {secret: str, createdAt: str(date-time), updatedAt: str(date-time), extension: [map], provider: str}

@endpoint DELETE /resources/mail/v1/configurations
@desc Delete configuration
@returns(200)

@endpoint POST /resources/mail/v2/configurations
@desc Create or update configuration v2
@optional {payload: any}
@returns(201)

@endpoint POST /resources/mail/v1/configs/templates
@desc Add or update template
@required {type: str(ResetPassword/ActivateUser/InviteToTenant/PwnedPassword/MagicLink/OTC/ConnectNewDevice/UserUsedInvitation/ResetPhoneNumber/BulkInvitesToTenant/MFAEnroll/MFAUnenroll/NewMFAMethod/MFARecoveryCode/RemoveMFAMethod/EmailVerification/BruteForceProtection/SuspiciousIP/MFAOTC/ImpossibleTravel/BotDetection/SmsAuthenticationEnabled/UnlockUser/UnlockUserSuccess/ActivateUserWithCode/InviteToTenantWithCode/VerifyNewEmail/EmailAddressChanged/ApprovalFlowApprove)}
@optional {senderEmail: str # Email of the sender cannot exceed 512 characters, subject: str # Subject of the email cannot exceed 512 characters, fromName: str # Name of the sender cannot exceed 512 characters, redirectURL: str # Only required for: ResetPassword, ActivateUser, InviteToTenant, MagicLink, BulkInvitesToTenant, htmlTemplate: str, successRedirectUrl: str, active: bool}
@returns(201)

@endpoint GET /resources/mail/v1/configs/templates
@desc Get template
@optional {type: str(ResetPassword/ActivateUser/InviteToTenant/PwnedPassword/MagicLink/OTC/ConnectNewDevice/UserUsedInvitation/ResetPhoneNumber/BulkInvitesToTenant/MFAEnroll/MFAUnenroll/NewMFAMethod/MFARecoveryCode/RemoveMFAMethod/EmailVerification/BruteForceProtection/SuspiciousIP/MFAOTC/ImpossibleTravel/BotDetection/SmsAuthenticationEnabled/UnlockUser/UnlockUserSuccess/ActivateUserWithCode/InviteToTenantWithCode/VerifyNewEmail/EmailAddressChanged/ApprovalFlowApprove)}
@returns(200)

@endpoint DELETE /resources/mail/v1/configs/templates/{templateId}
@desc Delete template
@required {templateId: str}
@returns(200)

@endpoint GET /resources/mail/v1/configs/{type}/default
@desc Get default template by type
@required {type: str(ResetPassword/ActivateUser/InviteToTenant/PwnedPassword/MagicLink/OTC/ConnectNewDevice/UserUsedInvitation/ResetPhoneNumber/BulkInvitesToTenant/MFAEnroll/MFAUnenroll/NewMFAMethod/MFARecoveryCode/RemoveMFAMethod/EmailVerification/BruteForceProtection/SuspiciousIP/MFAOTC/ImpossibleTravel/BotDetection/SmsAuthenticationEnabled/UnlockUser/UnlockUserSuccess/ActivateUserWithCode/InviteToTenantWithCode/VerifyNewEmail/EmailAddressChanged/ApprovalFlowApprove) # The email template type}
@returns(200) {htmlTemplate: str, senderEmail: str, redirectURL: str, successRedirectUrl: str, subject: str, fromName: str, active: bool, type: map, redirectURLPattern: str, successRedirectUrlPattern: str}

@endpoint POST /resources/auth/v1/user
@desc Authenticate user with password
@required {password: str}
@optional {frontegg-vendor-host: str # The vendor host domain, email: str # User email. Either email or username must be provided., username: str # Username. Either email or username must be provided., recaptchaToken: str, invitationToken: str}
@returns(200) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/auth/v1/user/token/refresh
@desc Refresh user JWT token
@required {frontegg-vendor-host: str}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/auth/v1/logout
@desc Logout user
@required {frontegg-vendor-host: str}
@returns(201)

@endpoint POST /resources/users/v1/signUp
@desc Signup user
@required {frontegg-vendor-host: str, frontegg-application-id: str # The application id, provider: str(local/saml/google/github/facebook/microsoft/scim2/slack/apple), email: str, companyName: str}
@optional {metadata: str # Stringified JSON object. Use the JSON.stringify() method., username: str, name: str, profilePictureUrl: str, password: str, skipInviteEmail: bool, roleIds: [str], emailMetadata: map, recaptchaToken: str, invitationToken: str, phoneNumber: str}
@returns(200)
@returns(201) {provider: str, metadata: str, email: str, username: str, name: str, profilePictureUrl: str, password: str, skipInviteEmail: bool, roleIds: [str], emailMetadata: map, companyName: str, recaptchaToken: str, invitationToken: str, phoneNumber: str}

@endpoint POST /resources/users/v1/signUp/username
@desc Signup user with username
@required {frontegg-vendor-host: str, frontegg-application-id: str # The application ID, provider: str(local/saml/google/github/facebook/microsoft/scim2/slack/apple), username: str, companyName: str}
@optional {metadata: str # Stringified JSON object. Use the JSON.stringify() method., name: str, profilePictureUrl: str, password: str, skipInviteEmail: bool, roleIds: [str], emailMetadata: map, recaptchaToken: str, invitationToken: str, email: str, phoneNumber: str}
@returns(200)
@returns(201) {shouldActivate: bool, userId: str, tenantId: str, authResponse: map{tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}, activationToken: str}

@endpoint POST /resources/configurations/v1/restrictions/ip/config
@desc Create or update IP restriction configuration (ALLOW/BLOCK)
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens, strategy: str(ALLOW/BLOCK), isActive: bool}
@returns(201)

@endpoint GET /resources/configurations/v1/restrictions/ip/config
@desc Get IP restriction configuration (ALLOW/BLOCK)
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint GET /resources/configurations/v1/restrictions/ip
@desc Get all IP restrictions
@optional {_limit: num, _offset: num # The page number to retrieve. For example, use 0 for the first page, 1 for the second page., _filter: str, frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint POST /resources/configurations/v1/restrictions/ip
@desc Create IP restriction
@required {ip: str # IP or CIDR (v4 and v6 are supported), strategy: str(ALLOW/BLOCK)}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens, description: str, isActive: bool}
@returns(201)

@endpoint POST /resources/configurations/v1/restrictions/ip/verify
@desc Test Current IP
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(201)

@endpoint POST /resources/configurations/v1/restrictions/ip/verify/allow
@desc Test current IP is in allow list
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(201)

@endpoint DELETE /resources/configurations/v1/restrictions/ip/{id}
@desc Delete IP restriction by IP
@required {id: str}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint POST /resources/configurations/v1/lockout-policy
@desc Create lockout policy
@required {enabled: bool # Determine whether the Lockout Policy is enabled, maxAttempts: num # The number of the maximum login attempts user can do}
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(201) {id: str, enabled: bool, maxAttempts: num, createdAt: str(date-time), updatedAt: str(date-time)}
@errors {409: Lockout Policy already exists}

@endpoint PATCH /resources/configurations/v1/lockout-policy
@desc Update lockout policy
@required {enabled: bool # Determine whether the Lockout Policy is enabled, maxAttempts: num # The number of the maximum login attempts user can do}
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200) {id: str, enabled: bool, maxAttempts: num, createdAt: str(date-time), updatedAt: str(date-time)}
@errors {404: Lockout Policy not found. Try to use the Create Lockout Policy API}

@endpoint GET /resources/configurations/v1/lockout-policy
@desc Get lockout policy
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200) {id: str, enabled: bool, maxAttempts: num, createdAt: str(date-time), updatedAt: str(date-time)}
@errors {404: Lockout policy is not defined}

@endpoint GET /resources/vendor-only/users/access-tokens/v1/active
@desc Get active access tokens list
@required {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint GET /resources/vendor-only/users/access-tokens/v1/{id}
@desc Get user access token data
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, id: str}
@returns(200) {userId: str, id: str, tenantId: str, permissions: [str], roles: [str], expires: str(date-time)}

@endpoint GET /resources/vendor-only/tenants/access-tokens/v1/{id}
@desc Get account (tenant) access token data
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, id: str}
@returns(200) {id: str, tenantId: str, permissions: [str], roles: [str], expires: str(date-time)}

@endpoint POST /resources/auth/v1/user/mfa/recover
@desc Recover MFA
@required {recoveryCode: str, email: str}
@returns(200)

@endpoint POST /resources/users/v1/mfa/disable
@desc Disable authenticator app MFA
@required {frontegg-user-id: str # The user ID identifier}
@optional {token: str}
@returns(200)

@endpoint POST /resources/users/v1/mfa/authenticator/{deviceId}/disable/verify
@desc Disable authenticator app MFA
@required {deviceId: str, frontegg-user-id: str # The user ID identifier}
@optional {token: str}
@returns(200)

@endpoint POST /resources/users/v1/mfa/sms/{deviceId}/disable
@desc Pre-disable SMS MFA
@required {deviceId: str, frontegg-user-id: str # The user ID identifier, frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint POST /resources/users/v1/mfa/sms/{deviceId}/disable/verify
@desc Disable SMS MFA
@required {deviceId: str, frontegg-user-id: str # The user ID identifier, otcToken: str, code: str}
@returns(200)

@endpoint POST /resources/auth/v1/user/mfa/verify
@desc Verify MFA using code from authenticator app
@required {value: str, mfaToken: str}
@optional {rememberDevice: bool}
@returns(201)

@endpoint POST /resources/auth/v1/user/mfa/emailcode
@desc Request verify MFA using email code
@required {mfaToken: str}
@returns(201)

@endpoint POST /resources/auth/v1/user/mfa/emailcode/verify
@desc Verify MFA using email code
@required {otcToken: str, code: str, mfaToken: str}
@optional {rememberDevice: bool}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/auth/v1/user/mfa/authenticator/enroll
@desc Pre enroll MFA using Authenticator App
@required {mfaToken: str}
@returns(201) {qrCode: str}

@endpoint POST /resources/auth/v1/user/mfa/authenticator/enroll/verify
@desc Enroll MFA using Authenticator App
@required {token: str, mfaToken: str}
@optional {rememberDevice: bool}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/auth/v1/user/mfa/authenticator/{deviceId}/verify
@desc Verify MFA using authenticator app
@required {deviceId: str, value: str, mfaToken: str}
@optional {rememberDevice: bool}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/auth/v1/user/mfa/sms/enroll
@desc Pre-enroll MFA using sms
@required {phoneNumber: str}
@returns(201)

@endpoint POST /resources/auth/v1/user/mfa/sms/enroll/verify
@desc Enroll MFA using sms
@required {otcToken: str, code: str}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/auth/v1/user/mfa/sms/{deviceId}
@desc Request to verify MFA using sms
@required {deviceId: str, mfaToken: str}
@returns(201)

@endpoint POST /resources/auth/v1/user/mfa/sms/{deviceId}/verify
@desc Verify MFA using sms
@required {deviceId: str, otcToken: str, code: str, mfaToken: str}
@optional {rememberDevice: bool}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/auth/v1/user/mfa/webauthn/enroll
@desc Pre enroll MFA using WebAuthN
@required {mfaToken: str}
@returns(201) {options: map}

@endpoint POST /resources/auth/v1/user/mfa/webauthn/enroll/verify
@desc Enroll MFA using WebAuthN
@required {deviceType: str(Platform/CrossPlatform), webauthnToken: str, options: map{id!: str, response!: map, deviceType: str}, mfaToken: str}
@optional {rememberDevice: bool}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/auth/v1/user/mfa/webauthn/{deviceId}
@desc Request verify MFA using WebAuthN
@required {deviceId: str, mfaToken: str}
@returns(201)

@endpoint POST /resources/auth/v1/user/mfa/webauthn/{deviceId}/verify
@desc Verify MFA using webauthn
@required {deviceId: str, webauthnToken: str, options: map{id!: str, response!: map, recaptchaToken: str, invitationToken: str}, mfaToken: str}
@optional {rememberDevice: bool}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint GET /resources/configurations/v1/mfa-policy/allow-remember-device
@desc Check if remember device allowed
@required {mfaToken: str # MFA token from the response body of the first factor authentication}
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint POST /resources/users/v1/mfa/enroll
@desc Enroll authenticator app MFA
@required {frontegg-user-id: str # The user ID identifier}
@returns(200) {qrCode: str}

@endpoint POST /resources/users/v1/mfa/authenticator/enroll
@desc Enroll authenticator app MFA
@required {frontegg-user-id: str # The user ID identifier}
@returns(200) {qrCode: str}

@endpoint POST /resources/users/v1/mfa/enroll/verify
@desc Verify authenticator app MFA enrollment
@required {frontegg-user-id: str # The user ID identifier, token: str}
@returns(200) {recoveryCode: str}

@endpoint POST /resources/users/v1/mfa/authenticator/enroll/verify
@desc Verify authenticator app MFA enrollment
@required {frontegg-user-id: str # The user ID identifier, token: str}
@returns(200) {recoveryCode: str}

@endpoint POST /resources/users/v1/mfa/sms/enroll
@desc Enroll SMS MFA
@required {frontegg-user-id: str # The user ID identifier, phoneNumber: str}
@returns(200)

@endpoint POST /resources/users/v1/mfa/sms/enroll/verify
@desc Verify MFA enrollment
@required {frontegg-user-id: str # The user ID identifier, otcToken: str, code: str}
@returns(200)

@endpoint POST /resources/configurations/v1/mfa
@desc Update MFA configuration
@optional {authenticationApp: map{active!: bool, serviceName!: str}, sms: map{active!: bool, tokenLifetimeSeconds!: num}, email: map{active!: bool, tokenLifetimeSeconds!: num, sender!: str}}
@returns(201) {authenticationApp: map{active: bool, serviceName: str}, sms: map{active: bool, tokenLifetimeSeconds: num}, email: map{active: bool, tokenLifetimeSeconds: num, sender: str}}

@endpoint GET /resources/configurations/v1/mfa
@desc Get MFA configuration
@returns(200) {authenticationApp: map{active: bool, serviceName: str}, sms: map{active: bool, tokenLifetimeSeconds: num}, email: map{active: bool, tokenLifetimeSeconds: num, sender: str}}

@endpoint POST /resources/configurations/v1/mfa-policy
@desc Create MFA policy
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier, enforceMFAType: str(DontForce/Force/ForceExceptSAML)=Force # Determine whether MFA should be enforced., allowRememberMyDevice: bool=false # Determine whether devices can be remembered and authentication can be skipped., mfaDeviceExpiration: num=1209600 # Expiration time of device in seconds}
@returns(201) {id: str, enforceMFAType: str, allowRememberMyDevice: bool, mfaDeviceExpiration: num, createdAt: str(date-time), updatedAt: str(date-time)}
@errors {409: MFA Policy already exists. Try to use the Update MFA Policy API}

@endpoint PATCH /resources/configurations/v1/mfa-policy
@desc Update security policy
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier, enforceMFAType: str(DontForce/Force/ForceExceptSAML)=Force # Determine whether MFA should be enforced., allowRememberMyDevice: bool=false # Determine whether devices can be remembered and authentication can be skipped., mfaDeviceExpiration: num=1209600 # Expiration time of device in seconds}
@returns(200) {id: str, enforceMFAType: str, allowRememberMyDevice: bool, mfaDeviceExpiration: num, createdAt: str(date-time), updatedAt: str(date-time)}
@errors {400: Missing parameters to update, 404: Security policy not found}

@endpoint PUT /resources/configurations/v1/mfa-policy
@desc Upsert security policy
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier, enforceMFAType: str(DontForce/Force/ForceExceptSAML)=Force # Determine whether MFA should be enforced., allowRememberMyDevice: bool=false # Determine whether devices can be remembered and authentication can be skipped., mfaDeviceExpiration: num=1209600 # Expiration time of device in seconds}
@returns(200) {id: str, enforceMFAType: str, allowRememberMyDevice: bool, mfaDeviceExpiration: num, createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint GET /resources/configurations/v1/mfa-policy
@desc Get security policy
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200) {id: str, enforceMFAType: str, allowRememberMyDevice: bool, mfaDeviceExpiration: num, createdAt: str(date-time), updatedAt: str(date-time)}
@errors {404: Security Policy not found. MFA is disabled}

@endpoint GET /resources/configurations/v1/mfa/strategies
@desc Get MFA strategies
@returns(200) {strategies: [map]}

@endpoint POST /resources/configurations/v1/mfa/strategies
@desc Create or update MFA strategy
@required {isActive: bool, strategy: str(AuthenticatorApp/WebAuthnPlatform/WebAuthnCrossPlatform/SMS/EmailCode)}
@returns(201)

@endpoint POST /resources/configurations/v1/password
@desc Create or update password configuration
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier, allowPassphrases: bool, maxLength: num, minLength: num, minPhraseLength: num, minOptionalTestsToPass: num, blockPwnedPasswords: bool, optionalTests: map{requireLowercase: bool, requireUppercase: bool, requireNumbers: bool, requireSpecialChars: bool}, requiredTests: map{checkThreeRepeatedChars: bool}}
@returns(201) {allowPassphrases: bool, maxLength: num, minLength: num, minPhraseLength: num, minOptionalTestsToPass: num, blockPwnedPasswords: bool, optionalTests: map, requiredTests: map}

@endpoint GET /resources/configurations/v1/password
@desc Get password policy configuration
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200) {allowPassphrases: bool, maxLength: num, minLength: num, minPhraseLength: num, minOptionalTestsToPass: num, blockPwnedPasswords: bool, optionalTests: map, requiredTests: map}

@endpoint POST /resources/configurations/v1/password-history-policy
@desc Create password history policy
@required {enabled: bool=false # Detemine whether the history policy is enbaled., historySize: num=1 # Number of passwords per user to remember in the history.}
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(201) {id: str, enabled: bool, historySize: num, createdAt: str(date-time), updatedAt: str(date-time)}
@errors {409: Policy already exists. Use the Update Password History Policy API.}

@endpoint PATCH /resources/configurations/v1/password-history-policy
@desc Update password history policy
@required {enabled: bool=false # Detemine whether the history policy is enbaled., historySize: num=1 # Number of passwords per user to remember in the history.}
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200) {id: str, enabled: bool, historySize: num, createdAt: str(date-time), updatedAt: str(date-time)}
@errors {404: History size must to be between 1 to 10}

@endpoint GET /resources/configurations/v1/password-history-policy
@desc Get password history policy
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200) {id: str, enabled: bool, historySize: num, createdAt: str(date-time), updatedAt: str(date-time)}
@errors {404: Password History Policy not found. Policy is disabled}

@endpoint POST /resources/users/v1/passwords/reset
@desc Reset password
@required {identifier: str # User identifier (phone number or email), identifierType: str(email/phoneNumber/username) # Type of the identifier}
@optional {emailMetadata: map}
@returns(201)

@endpoint POST /resources/users/v1/passwords/reset/verify
@desc Verify password
@required {userId: str, token: str, password: str}
@returns(201)

@endpoint POST /resources/users/v1/passwords/change
@desc Change password
@required {frontegg-user-id: str # The user ID identifier, password: str, newPassword: str}
@returns(201)

@endpoint GET /resources/users/v1/passwords/config
@desc Get strictest password configuration
@optional {userId: str}
@returns(200) {allowPassphrases: bool, maxLength: num, minLength: num, minPhraseLength: num, minOptionalTestsToPass: num, blockPwnedPasswords: bool, optionalTests: map, requiredTests: map}

@endpoint POST /resources/users/v2/passwords/reset/email
@desc Reset password via email
@required {identifier: str # User identifier (phone number or email), identifierType: str(email/phoneNumber/username) # Type of the identifier}
@optional {emailMetadata: map}
@returns(200) {sessionId: str}

@endpoint POST /resources/users/v2/passwords/reset/sms
@desc Reset password via SMS
@required {identifier: str # User identifier (phone number or email), identifierType: str(email/phoneNumber/username) # Type of the identifier}
@optional {emailMetadata: map}
@returns(200) {sessionId: str}

@endpoint POST /resources/users/v2/passwords/reset/sms/verify
@desc Verify password reset code sent via SMS
@required {otcToken: str, sessionId: str}
@returns(200) {userId: str, token: str}

@endpoint GET /resources/configurations/v1/password-rotation
@desc Get password expiration period configuration
@returns(200) {createdAt: str(date-time), updatedAt: str(date-time), isActive: bool, rotationPeriod: num, notificationPeriod: num, tenantId: str}
@errors {404: Password rotation configuration not found}

@endpoint POST /resources/configurations/v1/password-rotation
@desc Manage password expiration
@optional {isActive: bool=false # Indicates whether password expiration is enabled, rotationPeriod: num=129600 # The password expiration period, in minutes, notificationPeriod: num=10080 # Notification period before password expiration, in minutes}
@returns(200)

@endpoint GET /resources/configurations/v1/password-rotation/vendor
@desc Get environment configuration for password expiration period.
@returns(200) {createdAt: str(date-time), updatedAt: str(date-time), isActive: bool, rotationPeriod: num, notificationPeriod: num, tenantId: str}
@errors {404: Password rotation configuration not found}

@endpoint POST /resources/auth/v1/passwordless/smscode/prelogin
@desc SMS code prelogin
@required {email: str, userId: str, username: str, phoneNumber: str}
@optional {recaptchaToken: str, invitationToken: str}
@returns(201) {phoneNumber: str, resetPhoneNumberToken: str}
@errors {400: User does not have a phone number}

@endpoint POST /resources/auth/v1/passwordless/smscode/postlogin
@desc SMS code postlogin
@required {token: str # One time code to login with - get it from the email sent after prelogin request}
@optional {recaptchaToken: str, invitationToken: str}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/auth/v1/passwordless/magiclink/prelogin
@desc Magic link prelogin
@required {email: str, userId: str, username: str}
@optional {recaptchaToken: str, invitationToken: str}
@returns(200)
@errors {400: Invalid authentication type, magic link authentication should be enabled}

@endpoint POST /resources/auth/v1/passwordless/magiclink/postlogin
@desc Magic link postlogin
@required {token: str # One time code to login with - get it from the email sent after prelogin request}
@optional {recaptchaToken: str, invitationToken: str}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/auth/v1/passwordless/code/prelogin
@desc OTC (One-Time Code) prelogin
@required {email: str, userId: str, username: str}
@optional {recaptchaToken: str, invitationToken: str}
@returns(201)
@errors {400: Invalid authentication type, OTC (One-Time Code) authentication should be enabled}

@endpoint POST /resources/auth/v1/passwordless/code/postlogin
@desc OTC (One-Time Code) postlogin
@required {token: str # One time code to login with - get it from the email sent after prelogin request}
@optional {recaptchaToken: str, invitationToken: str}
@returns(201) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint GET /resources/permissions/v1
@desc Get permissions
@returns(200)

@endpoint POST /resources/permissions/v1
@desc Create permissions
@returns(201)

@endpoint DELETE /resources/permissions/v1/{permissionId}
@desc Delete permission
@required {permissionId: str}
@returns(204)

@endpoint PATCH /resources/permissions/v1/{permissionId}
@desc Update permission
@required {permissionId: str}
@optional {key: str, name: str, description: str, categoryId: str}
@returns(200) {id: str, key: str, name: str, description: str, createdAt: str(date-time), updatedAt: str(date-time), roleIds: [str], categoryId: str, fePermission: bool}

@endpoint PUT /resources/permissions/v1/{permissionId}/roles
@desc Set a permission to multiple roles
@required {permissionId: str, roleIds: [str] # The permission will be assigned to the specified roles}
@returns(200) {id: str, key: str, name: str, description: str, createdAt: str(date-time), updatedAt: str(date-time), roleIds: [str], categoryId: str, fePermission: bool}

@endpoint PUT /resources/permissions/v1/classification
@desc Set permissions classification
@required {permissionIds: [str], type: str(NEVER/ALWAYS/ASSIGNABLE)}
@returns(200) {id: str, key: str, name: str, description: str, createdAt: str(date-time), updatedAt: str(date-time), roleIds: [str], categoryId: str, fePermission: bool}

@endpoint GET /resources/permissions/v1/categories
@desc Get permissions categories
@returns(200)

@endpoint POST /resources/permissions/v1/categories
@desc Create category
@required {name: str}
@optional {description: str, id: str}
@returns(201) {id: str, name: str, description: str?, createdAt: str(date-time), feCategory: bool}

@endpoint PATCH /resources/permissions/v1/categories/{categoryId}
@desc Update category
@required {categoryId: str}
@optional {name: str, description: str}
@returns(200)

@endpoint DELETE /resources/permissions/v1/categories/{categoryId}
@desc Delete category
@required {categoryId: str}
@returns(200)

@endpoint POST /resources/users/access-tokens/v1
@desc Create user access token
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, frontegg-user-id: str # The user ID identifier}
@optional {description: str, expiresInMinutes: num # Token expiration time in minutes. In case of undefined, the token won't be expired}
@returns(201) {id: str, description: str, createdAt: str(date-time), secret: str, expires: str(date-time)}

@endpoint GET /resources/users/access-tokens/v1
@desc Get user access tokens
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, frontegg-user-id: str # The user ID identifier}
@returns(200) {accessTokens: [map]}

@endpoint DELETE /resources/users/access-tokens/v1/{id}
@desc Delete user access token by token ID
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, frontegg-user-id: str # The user ID identifier, id: str}
@returns(200)

@endpoint POST /resources/users/api-tokens/v1
@desc Create user client credentials token
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, frontegg-user-id: str # The user ID identifier}
@optional {metadata: map # Extra data that will be encoded as part of the JWT, description: str, expiresInMinutes: num # Token expiration time in minutes. In case of undefined, the token won't be expired}
@returns(201) {clientId: str, description: str, metadata: map, createdAt: str(date-time), secret: str, expires: str(date-time)}

@endpoint GET /resources/users/api-tokens/v1
@desc Get user client credentials tokens
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, frontegg-user-id: str # The user ID identifier}
@returns(200)

@endpoint DELETE /resources/users/api-tokens/v1/{id}
@desc Delete user client credentials token by token ID
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, frontegg-user-id: str # The user ID identifier, id: str}
@returns(200)

@endpoint GET /resources/roles/v1
@desc Get roles
@optional {frontegg-tenant-id: str # For relating a role to a specific account (tenant), use `get accounts (tenants)` API to find the account (tenant) Ids}
@returns(200)

@endpoint POST /resources/roles/v1
@desc Create roles
@optional {frontegg-tenant-id: str # For relating a role to a specific account (tenant), use `get accounts (tenants)` API to find the account (tenant) Ids}
@returns(201)

@endpoint DELETE /resources/roles/v1/{roleId}
@desc Delete role
@required {roleId: str}
@optional {frontegg-tenant-id: str # For relating a role to a specific account (tenant), use `get accounts (tenants)` API to find the account (tenant) Ids}
@returns(204)

@endpoint PATCH /resources/roles/v1/{roleId}
@desc Update role
@required {roleId: str}
@optional {frontegg-tenant-id: str # For relating a role to a specific account (tenant), use `get accounts (tenants)` API to find the account (tenant) Ids, isDefault: bool # This role will be assigned for every user that will be added without specified roles, firstUserRole: bool # This role will be assigned to the first user of a tenant (new tenants only), migrateRole: bool # Set this property to `true` together with `isDefault` in order to assign this role to all users, level: num # Role level for roles elevation, lower level means stronger role., key: str, name: str, description: str}
@returns(200) {id: str, vendorId: str, tenantId: str, key: str, name: str, description: str, isDefault: bool, firstUserRole: bool, level: num, createdAt: str(date-time), updatedAt: str(date-time), permissions: [str]}

@endpoint PUT /resources/roles/v1/{roleId}/permissions
@desc Assign permissions to a role
@required {roleId: str, permissionIds: [str] # Set permission Ids to attach to the role}
@optional {frontegg-tenant-id: str # For relating a role to a specific account (tenant), use `get accounts (tenants)` API to find the account (tenant) Ids}
@returns(200) {id: str, vendorId: str, tenantId: str, key: str, name: str, description: str, isDefault: bool, firstUserRole: bool, level: num, createdAt: str(date-time), updatedAt: str(date-time), permissions: [str]}

@endpoint PUT /resources/roles/v1/{roleId}/tenant
@desc Update role tenant
@required {roleId: str, tenantId: str}
@returns(200) {id: str, vendorId: str, tenantId: str, key: str, name: str, description: str, isDefault: bool, firstUserRole: bool, level: num, createdAt: str(date-time), updatedAt: str(date-time), permissions: [str]}

@endpoint GET /resources/users/phone-numbers/v1
@desc Get all phone numbers
@optional {_limit: num, _offset: num # The page number to retrieve. For example, use 0 for the first page, 1 for the second page., _sortBy: str(userId/phoneNumber), _order: str(ASC/DESC), _phoneNumber: str}
@returns(200)

@endpoint POST /resources/users/phone-numbers/v1
@desc Set phone number for a user
@required {phoneNumber: str # New phone number}
@optional {verify: bool=true # Should send verification code, default is true}
@returns(201)

@endpoint POST /resources/users/phone-numbers/v1/preverify
@desc Pre-verify user's phone number
@required {phoneNumber: str # New phone number}
@returns(200)

@endpoint POST /resources/users/phone-numbers/v1/verify
@desc Verify creation of phone number for user
@required {otcToken: str # OTC token, code: str # Code that was sent to the user}
@returns(200)

@endpoint DELETE /resources/users/phone-numbers/v1/{id}
@desc Delete user's phone number
@required {id: str}
@returns(200)

@endpoint POST /resources/users/phone-numbers/v1/{id}/delete/verify
@desc Verify delete user's phone number
@required {id: str, otcToken: str # OTC token, code: str # Code that was sent to the user}
@returns(200)

@endpoint GET /resources/users/phone-numbers/v1/me
@desc Get current user's phone numbers
@required {frontegg-user-id: str # The user id}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint GET /resources/users/phone-numbers/v2
@desc Get all phone numbers v2
@optional {_limit: num, _offset: num # The page number to retrieve. For example, use 0 for the first page, 1 for the second page., _sortBy: str(userId/phoneNumber), _order: str(ASC/DESC), _phoneNumber: str, userIds: [str]}
@returns(200)

@endpoint POST /resources/configurations/v1/sms
@desc Creates or updates a vendor SMS config
@optional {senderName: str # The sender name will be used only when alphanumeric sender is supported in the recipient country. This is usually a phone number or the name of the sender, dependeing on what is configured on your Twilio account, accountId: str # account ID, token: str # token, serviceId: str # service ID, provider: str # provider, channel: str # channel}
@returns(200)
@returns(201)

@endpoint DELETE /resources/configurations/v1/sms
@desc Deletes a vendor SMS config
@returns(200)

@endpoint GET /resources/configurations/v1/sms
@desc Gets a vendor SMS config
@returns(200)

@endpoint GET /resources/configurations/v1/sms/templates
@desc Gets vendor SMS templates
@returns(200)

@endpoint GET /resources/configurations/v1/sms/templates/{type}
@desc Gets vendor SMS template by type
@required {type: str}
@returns(200)

@endpoint DELETE /resources/configurations/v1/sms/templates/{type}
@desc Deletes vendor SMS template by type
@required {type: str}
@returns(200)

@endpoint POST /resources/configurations/v1/sms/templates/{type}
@desc Create or update a vendor SMS template
@required {type: str}
@returns(200)
@returns(201)

@endpoint GET /resources/configurations/v1/sms/templates/{type}/default
@desc Gets vendor default SMS template by type
@required {type: str}
@returns(200)

@endpoint GET /resources/configurations/v1/sms/templates/default/all
@desc Gets all vendor default SMS templates
@returns(200)

@endpoint GET /resources/configurations/sessions/v1/vendor
@desc Get environment session configuration
@returns(200)

@endpoint GET /resources/configurations/sessions/v1
@desc Get account (tenant) or vendor default session configuration
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint POST /resources/configurations/sessions/v1
@desc Create or update account (tenant) or vendor default session configuration
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier, sessionIdleTimeoutConfiguration: map{isActive!: bool, timeout!: num}, sessionTimeoutConfiguration: map{isActive!: bool, timeout!: num}, sessionConcurrentConfiguration: map{isActive!: bool, maxSessions!: num}}
@returns(201)

@endpoint GET /resources/configurations/v1/user-emails-policy
@desc Get user emails policy
@returns(200) {allowEmailChange: bool}

@endpoint POST /resources/configurations/v1/user-emails-policy
@desc Create or update user emails policy
@optional {allowEmailChange: bool # Used to enable or disable email change for users.}
@returns(200)

@endpoint GET /resources/groups/v1
@desc Get all groups
@optional {_groupsRelations: str(roles/users/rolesAndUsers), frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200) {groups: [map]}

@endpoint POST /resources/groups/v1
@desc Create group
@required {name: str # Group unique name}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens, color: str # Color for group display, description: str # Group description, metadata: str # Stringified JSON object}
@returns(201) {id: str, name: str, color: str, description: str, metadata: str, roles: [map], users: [map], managedBy: str, createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint POST /resources/groups/v1/bulkGet
@desc Get groups by Ids
@required {groupsIds: [str] # Group IDs}
@optional {_groupsRelations: str(roles/users/rolesAndUsers), frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(201) {groups: [map]}

@endpoint PATCH /resources/groups/v1/{id}
@desc Update group
@required {id: str}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens, color: str # Color for group display, description: str # Group description, metadata: str # Stringified JSON object, name: str # Group unique name}
@returns(200) {id: str, name: str, color: str, description: str, metadata: str, roles: [map], users: [map], managedBy: str, createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint DELETE /resources/groups/v1/{id}
@desc Delete group
@required {id: str}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint GET /resources/groups/v1/{id}
@desc Get group by ID
@required {id: str}
@optional {_groupsRelations: str(roles/users/rolesAndUsers), frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200) {id: str, name: str, color: str, description: str, metadata: str, roles: [map], users: [map], managedBy: str, createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint GET /resources/groups/v1/config
@desc Get groups configuration
@returns(200) {enabled: bool, rolesEnabled: bool}

@endpoint POST /resources/groups/v1/config
@desc Create or update groups configuration
@optional {enabled: bool=true # Determine whether groups are enabled/disabled. Default value is true., rolesEnabled: bool=true # Determine whether groups can have roles or not. Default value is true.}
@returns(201)

@endpoint POST /resources/groups/v1/{groupId}/roles
@desc Add roles to group
@required {groupId: str, roleIds: [str] # Will add / remove requested roles from the group}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(201)

@endpoint DELETE /resources/groups/v1/{groupId}/roles
@desc Remove roles from group
@required {groupId: str, roleIds: [str] # Will add / remove requested roles from the group}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint POST /resources/groups/v1/{groupId}/users
@desc Add users to group
@required {groupId: str, userIds: [str] # An array of User IDs to add / remove existing users to / from the group.}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(201)

@endpoint DELETE /resources/groups/v1/{groupId}/users
@desc Remove users from group
@required {groupId: str, userIds: [str] # An array of User IDs to add / remove existing users to / from the group.}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint GET /resources/groups/v2
@desc Get all groups paginated
@optional {_groupsRelations: str(roles/users/rolesAndUsers), _limit: num, _offset: num # The page number to retrieve. For example, use 0 for the first page, 1 for the second page., _sortBy: str(id/name/createdAt/updatedAt), _order: str(ASC/DESC), frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint POST /resources/tenants/users/v1/{userId}/disable
@desc Disable user account (tenant)
@required {userId: str}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)
@returns(201)
@errors {403}

@endpoint POST /resources/tenants/users/v1/{userId}/enable
@desc Enable user account (tenant)
@required {userId: str}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)
@returns(201)
@errors {403}

@endpoint PUT /resources/users/temporary/v1/{userId}
@desc Sets a permanent user to temporary
@required {userId: str, expirationInSeconds: num}
@returns(201) {expirationInSeconds: num}

@endpoint DELETE /resources/users/temporary/v1/{userId}
@desc Sets a temporary user to permanent
@required {userId: str}
@returns(200)

@endpoint GET /resources/users/temporary/v1/configuration
@desc Gets temporary users configuration
@returns(200) {enabled: bool}

@endpoint PUT /resources/users/temporary/v1/configuration
@desc Set temporary users configuration
@required {enabled: bool}
@returns(200) {enabled: bool}

@endpoint GET /resources/users/emails/v1
@desc Get all user emails
@optional {_limit: num, _offset: num # The page number to retrieve. For example, use 0 for the first page, 1 for the second page., _sortBy: str(userId/email), _order: str(ASC/DESC), _email: str, userIds: str, frontegg-tenant-id: str # The tenant ID identifier}
@returns(200)

@endpoint POST /resources/users/emails/v1
@desc Create a user email
@required {email: str # New email}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200) {id: str, userId: str, email: str, verified: bool, isPrimary: bool, createdAt: str(date-time), updatedAt: str(date-time)}
@returns(201) {id: str, userId: str, email: str, verified: bool, isPrimary: bool, createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint POST /resources/users/emails/v1/verify
@desc Verify user email
@required {code: str # The code for the user to verify their email, email: str # The email for the user to verify their email}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint DELETE /resources/users/emails/v1/{emailId}
@desc Delete a user email
@required {emailId: str, frontegg-user-id: str # The user ID}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint POST /resources/users/emails/v1/vendor/{userId}
@desc Create a user email for vendor
@required {userId: str, email: str # New email}
@optional {isVerified: bool # Is user email verified}
@returns(200) {id: str, userId: str, email: str, verified: bool, isPrimary: bool, createdAt: str(date-time), updatedAt: str(date-time)}
@returns(201) {id: str, userId: str, email: str, verified: bool, isPrimary: bool, createdAt: str(date-time), updatedAt: str(date-time)}

@endpoint DELETE /resources/users/emails/v1/vendor/{userId}/{emailId}
@desc Delete a user email for vendor
@required {userId: str, emailId: str}
@returns(200)

@endpoint POST /resources/users/emails/v1/vendor/{userId}/primary
@desc Mark email as primary for vendor
@required {userId: str, email: str # Email to mark as primary}
@returns(200)

@endpoint POST /resources/users/emails/v1/me/primary
@desc Mark email as primary
@required {email: str # Email to mark as primary}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint GET /resources/users/emails/v1/me
@desc Get current user`s emails
@required {frontegg-user-id: str # The user ID}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint PUT /resources/sub-tenants/users/v1/{userId}/access
@desc Set sub-account access for a user
@required {userId: str, allowAccess: bool}
@returns(200)

@endpoint POST /resources/users/v1/activate/reset
@desc Reset user activation token
@required {email: str(email), emailMetadata: map}
@returns(201)

@endpoint POST /resources/users/v1/invitation/reset
@desc Reset invitation
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, email: str}
@returns(200)

@endpoint POST /resources/users/v1/invitation/reset/all
@desc Reset all invitation tokens
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, email: str}
@returns(200)

@endpoint GET /resources/users/v3
@desc Get users
@optional {_limit: num # The default limit is 50 users per request, the maximum is 200, _identifier: str # Filter users by username prefix match. Must be provided together with _identifierType, _identifierType: str(email/phoneNumber/username) # Filter users by username. Must be provided together with _identifier, _includeSubTenants: bool=true # when passing a user id, gives the option to include or not include sub accounts (tenants) when searching users, _namePrefix: str # Filter users by prefix name match, _offset: num # The page number to retrieve. For example, use 0 for the first page, 1 for the second page., _email: str, _tenantId: str, ids: str, _sortBy: str(createdAt/name/email/id/verified/isLocked/provider/tenantId), _order: str(ASC/DESC), _externalIds: str, frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint GET /resources/users/v3/roles
@desc Get users roles
@required {ids: [str]}
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint GET /resources/users/v3/groups
@desc Get users groups
@required {ids: [str]}
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint POST /resources/users/v3/me/unlock
@desc Unlock user
@required {token: str}
@returns(200)

@endpoint POST /resources/users/v2
@desc Invite user
@required {frontegg-tenant-id: str # The account (tenant) ID identifier}
@optional {email: str(email) # The email of the user. If not provided, the username is required, username: str # The username of the user. If not provided, the email is required. Maximum length is 255 characters., name: str, profilePictureUrl: str, password: str, phoneNumber: str, provider: str(local/saml/google/github/facebook/microsoft/scim2/slack/apple)=local, metadata: str # Stringified JSON object, skipInviteEmail: bool, roleIds: [str], emailMetadata: map, expirationInSeconds: num # Temporary user expiration in seconds}
@returns(201) {id: str, email: str, verified: bool, name: str, profilePictureUrl: str, roles: [str], permissions: [str], metadata: str, createdAt: str(date-time), lastLogin: str(date-time), activatedForTenant: bool, temporaryExpirationDate: str(date-time)}

@endpoint PUT /resources/users/v2/me
@desc Update user profile
@optional {phoneNumber: str, profilePictureUrl: str, metadata: str # Stringified JSON object, name: str}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint GET /resources/users/v2/me
@desc Get user profile
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint POST /resources/users/v1
@desc Create user
@required {frontegg-tenant-id: str # The account (tenant) ID identifier}
@optional {email: str(email) # The email of the user. If not provided, the username is required, username: str # The username of the user. If not provided, the email is required. Maximum length is 255 characters., name: str, profilePictureUrl: str, password: str, phoneNumber: str, provider: str(local/saml/google/github/facebook/microsoft/scim2/slack/apple)=local, metadata: str # Stringified JSON object, skipInviteEmail: bool, roleIds: [str], emailMetadata: map, expirationInSeconds: num # Temporary user expiration in seconds}
@returns(201) {id: str, email: str, verified: bool, name: str, profilePictureUrl: str, roles: [str], permissions: [str], metadata: str, createdAt: str(date-time), lastLogin: str(date-time), activatedForTenant: bool, temporaryExpirationDate: str(date-time)}

@endpoint PUT /resources/users/v1
@desc Update user
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, frontegg-user-id: str # The user ID identifier}
@optional {phoneNumber: str, profilePictureUrl: str, metadata: str # Stringified JSON object, name: str}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint DELETE /resources/users/v1/{userId}
@desc Remove user
@required {userId: str}
@optional {frontegg-tenant-id: str # The account (tenant) ID identifier (optional)}
@returns(200)

@endpoint PUT /resources/users/v1/{userId}
@desc Update user (global)
@required {userId: str}
@optional {phoneNumber: str, profilePictureUrl: str, metadata: str # Stringified JSON object, vendorMetadata: str # Extra vendor-only data. stringified JSON object, mfaBypass: bool # Indicates whether MFA should be bypassed for this user, externalId: str # The external id of the user, name: str}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint POST /resources/users/v1/{userId}/roles
@desc Assign roles to user
@required {userId: str, frontegg-tenant-id: str # The account (tenant) ID identifier, roleIds: [str]}
@returns(201) {tenantId: str, userId: str, roles: [map]}

@endpoint DELETE /resources/users/v1/{userId}/roles
@desc Unassign roles from user
@required {userId: str, frontegg-tenant-id: str # The account (tenant) ID identifier, roleIds: [str]}
@returns(200) {tenantId: str, userId: str, roles: [map]}

@endpoint PUT /resources/users/v1/tenant
@desc Update user's active account (tenant)
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, frontegg-user-id: str # The user ID identifier, tenantId: str # Desired tenant to set as active tenant for user}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint GET /resources/users/v1/query/phrase
@desc Get users with fuzzy search
@optional {_limit: num # The default limit is 50 users per request, the maximum is 200, _identifier: str # Filter users by username prefix match. Must be provided together with _identifierType, _identifierType: str(email/phoneNumber/username) # Filter users by username. Must be provided together with _identifier, _includeSubTenants: bool=true # when passing a user id, gives the option to include or not include sub accounts (tenants) when searching users, _namePrefix: str # Filter users by prefix name match, _phraseSearchContains: [str] # Pass a list of strings, separated by comma, to search for users that contain all of the strings in the list, _phraseSearchExcludes: [str] # Pass a list of strings, separated by comma, to search for users that do not contain any of the strings in the list, _phraseSearchOptional: [str] # Pass a list of strings, separated by comma, to search for users that contain at least one of the strings in the list, _phraseSearchApproximate: bool=false # When true, the search will be approximate (fuzzy), meaning it will include similar characters to the ones in the search string, _offset: num # The page number to retrieve. For example, use 0 for the first page, 1 for the second page., _email: str, _tenantId: str, ids: str, _sortBy: str(createdAt/name/email/id/verified/isLocked/provider/tenantId), _order: str(ASC/DESC), _externalIds: str, frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200)

@endpoint GET /resources/usernames/v1
@desc Get usernames for users
@optional {_limit: num, _offset: num # The page number to retrieve. For example, use 0 for the first page, 1 for the second page., _sortBy: str(userId/username), _order: str(ASC/DESC), _usernamePrefix: str, userIds: [str], usernames: [str]}
@returns(200) {username: str, userId: str}

@endpoint POST /resources/usernames/v1
@desc Create a username for user
@required {username: str # The username to create. Allowed characters: alphanumeric (a-z, 0-9), ^, $, ., !, -, #, +, ', ~, _ (no spaces, no accents, automatically converted to lowercase). Max length: 128 characters.}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)
@returns(201)

@endpoint DELETE /resources/usernames/v1/{username}
@desc Delete a username for user
@required {username: str}
@returns(200)

@endpoint GET /resources/usernames/v1/me
@desc Get authenticated user's username
@required {frontegg-user-id: str # The user id}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200) {username: str, userId: str}

@endpoint POST /resources/users/v1/email/me
@desc Update user email
@required {email: str # The email to update to}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint POST /resources/users/v1/email/me/verify
@desc Verify user email
@required {code: str # The code for the user to verify their email, email: str # The email for the user to verify their email}
@optional {frontegg-tenant-id: str # The tenant identifier. Required for requests to api.frontegg.com (or your region) when using a management token. Parsed from the token when using user or API tokens}
@returns(200)

@endpoint POST /resources/users/v1/activate
@desc Activate user
@required {frontegg-vendor-host: str, userId: str, token: str}
@optional {password: str, recaptchaToken: str, lastTermsCheck: str}
@returns(200) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint POST /resources/users/v1/activate/code
@desc Activate user with code
@required {frontegg-vendor-host: str, userId: str, token: str, code: str}
@optional {password: str, recaptchaToken: str, lastTermsCheck: str}
@returns(200) {tokenType: str, otcToken: str, mfaRequired: bool, mfaToken: str, resetPasswordToken: str, passwordExpiresIn: num, notificationPeriod: num, mfaEnrolled: bool, mfaDevices: map{webauthn: [map], phones: [map], authenticators: [map], emails: [map]}, mfaStrategies: map, qrCode: str, recoveryCode: str, accessToken: str, refreshToken: str, expiresIn: num, expires: str, userId: str, userEmail: str, emailVerified: bool, isBreachedPassword: bool}

@endpoint GET /resources/users/v1/activate/strategy
@desc Get user activation strategy
@required {userId: str, token: str}
@returns(200) {shouldSetPassword: bool}

@endpoint POST /resources/users/v1/invitation/accept
@desc Accept invitation
@required {userId: str, token: str}
@returns(200)
@returns(201)

@endpoint POST /resources/users/v1/invitation/accept/code
@desc Accept invitation with code
@required {userId: str, token: str, code: str}
@returns(200)

@endpoint GET /resources/users/v3/me
@desc Get user profile
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), subAccountAccessAllowed: bool, managedBy: str}

@endpoint GET /resources/users/v2/me/tenants
@desc Get user accounts (tenants)
@required {frontegg-user-id: str # The user ID identifier}
@returns(200)

@endpoint GET /resources/users/v2/me/hierarchy
@desc Get user accounts (tenants) hierarchy
@returns(200)

@endpoint GET /resources/users/v1/me/authorization
@desc Get user permissions and roles
@returns(200) {roles: [map], permissions: [map]}

@endpoint GET /resources/users/v1/me/tenants
@desc Get user accounts (tenants)
@returns(200)

@endpoint GET /resources/user-sources/v1
@desc Get vendor user sources
@returns(200)

@endpoint GET /resources/user-sources/v1/{id}
@desc Get vendor user source
@required {id: str}
@returns(200) {id: str, name: str, type: str, description: str, appIds: [str], index: num, configuration: map}

@endpoint DELETE /resources/user-sources/v1/{id}
@desc Delete user source
@required {id: str}
@returns(200)

@endpoint POST /resources/user-sources/v1/external/auth0
@desc Create Auth0 external user source
@required {name: str # The user source name, configuration: any # User source configuration, index: num # The user source index}
@optional {appIds: [str] # The application Ids to assign to this user source, description: str # The user source description}
@returns(201) {id: str, name: str, type: str, appIds: [str], description: str, index: num}

@endpoint POST /resources/user-sources/v1/external/cognito
@desc Create Cognito external user source
@required {name: str # The user source name, configuration: any # User source configuration, index: num # The user source index}
@optional {appIds: [str] # The application Ids to assign to this user source, description: str # The user source description}
@returns(201) {id: str, name: str, type: str, appIds: [str], description: str, index: num}

@endpoint POST /resources/user-sources/v1/external/firebase
@desc Create Firebase external user source
@required {name: str # The user source name, configuration: any # User source configuration, index: num # The user source index}
@optional {appIds: [str] # The application Ids to assign to this user source, description: str # The user source description}
@returns(201) {id: str, name: str, type: str, appIds: [str], description: str, index: num}

@endpoint POST /resources/user-sources/v1/external/custom-code
@desc Create Custom-Code external user source
@required {name: str # The user source name, configuration: any # User source configuration, index: num # The user source index}
@optional {appIds: [str] # The application Ids to assign to this user source, description: str # The user source description}
@returns(201) {id: str, name: str, type: str, appIds: [str], description: str, index: num}

@endpoint POST /resources/user-sources/v1/federation
@desc Create Federation user source
@required {name: str # The user source name, configuration: any # User source configuration, index: num # The user source index}
@optional {appIds: [str] # The application Ids to assign to this user source, description: str # The user source description}
@returns(201) {id: str, name: str, type: str, appIds: [str], description: str, index: num}

@endpoint PUT /resources/user-sources/v1/external/auth0/{id}
@desc Update Auth0 external user source
@required {id: str}
@optional {name: str # The user source name, configuration: any # User source configuration, index: num # The user source index, description: str # The user source description}
@returns(200)

@endpoint PUT /resources/user-sources/v1/external/cognito/{id}
@desc Update Cognito external user source
@required {id: str}
@optional {name: str # The user source name, configuration: any # User source configuration, index: num # The user source index, description: str # The user source description}
@returns(200)

@endpoint PUT /resources/user-sources/v1/external/firebase/{id}
@desc Update Firebase external user source
@required {id: str}
@optional {name: str # The user source name, configuration: any # User source configuration, index: num # The user source index, description: str # The user source description}
@returns(200)

@endpoint PUT /resources/user-sources/v1/external/custom-code/{id}
@desc Update Custom-Code external user source
@required {id: str}
@optional {name: str # The user source name, configuration: any # User source configuration, index: num # The user source index, description: str # The user source description}
@returns(200)

@endpoint PUT /resources/user-sources/v1/federation/{id}
@desc Update Federation user source
@required {id: str}
@optional {name: str # The user source name, configuration: any # User source configuration, index: num # The user source index, description: str # The user source description}
@returns(200)

@endpoint POST /resources/user-sources/v1/assign
@desc Assign applications to a user source
@required {appIds: [str] # The application Ids to assign to this user source, userSourceId: str # The user source id}
@returns(201)

@endpoint POST /resources/user-sources/v1/unassign
@desc Unassign applications from a user source
@required {appIds: [str] # The application Ids to assign to this user source, userSourceId: str # The user source id}
@returns(201)

@endpoint GET /resources/user-sources/v1/{id}/users
@desc Get user source users
@required {id: str}
@returns(200)

@endpoint GET /resources/users/sessions/v1/me
@desc Get user's active sessions
@required {frontegg-user-id: str # The user ID identifier}
@returns(200)

@endpoint DELETE /resources/users/sessions/v1/me/all
@desc Delete all user sessions
@required {frontegg-user-id: str # The user ID identifier}
@returns(200)

@endpoint DELETE /resources/users/sessions/v1/me/{id}
@desc Delete single user's session
@required {id: str, frontegg-user-id: str # The user ID identifier}
@returns(200)

@endpoint GET /resources/vendor-only/users/v1/{userId}
@desc Get user
@required {userId: str}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint POST /resources/vendor-only/users/v1/{userId}/mfa/unenroll
@desc Unenroll user from MFA globally
@required {userId: str}
@returns(200)

@endpoint POST /resources/vendor-only/users/v1/passwords/verify
@desc Verify user's password
@required {email: str, password: str}
@returns(200)

@endpoint POST /resources/vendor-only/users/v1
@desc Create user
@required {tenantId: str}
@optional {email: str # The email of the user. If not provided, the username is required, username: str # The username of the user. If not provided, the email is required. Maximum length is 255 characters., name: str, password: str, phoneNumber: str, metadata: str # Stringified JSON object, vendorMetadata: str # Extra vendor-only data. stringified JSON object, roleIds: [str] # Role IDs to assign to the user, expirationInSeconds: num # Temporary user expiration in seconds, mfaBypass: bool # Bypass MFA for this user, externalId: str # The external id of the user}
@returns(201) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint GET /resources/tenants/users/v1/statuses
@desc Get users account (tenant) statuses
@required {userIds: [str] # User IDs}
@optional {userTenantStatuses: [str] # Account (tenant) Statuses}
@returns(200) {userId: str, tenantsStatuses: [map]}

@endpoint POST /resources/users/phone-numbers/v1/vendor/{userId}
@desc Create user phone number verified by default
@required {userId: str, phoneNumber: str # New phone number}
@returns(201)

@endpoint DELETE /resources/users/phone-numbers/v1/vendor/{userId}/{phoneId}
@desc Delete user phone number on an environment
@required {phoneId: str, userId: str}
@returns(200)

@endpoint POST /resources/users/bulk/v1/invite
@desc Invite users to an account (tenant) in bulk
@required {frontegg-tenant-id: str # The account (tenant) ID identifier, users: [map{email: str(email), username: str, name: str, profilePictureUrl: str, password: str, phoneNumber: str, provider: str, metadata: str, skipInviteEmail: bool, roleIds: [str], emailMetadata: map, expirationInSeconds: num, verified: bool}]}
@returns(202)

@endpoint GET /resources/users/bulk/v1/status/{id}
@desc Get status of bulk invite task
@required {id: str}
@returns(200)

@endpoint PATCH /resources/vendor-only/users/v1/{userId}/roles/bulk
@desc Bulk update user roles across all tenants
@required {userId: str}
@optional {addRoleIds: [str] # Role IDs to add across tenants, removeRoleIds: [str] # Role IDs to remove across tenants, tenantIds: [str] # Specific tenant IDs to update. If not provided, all tenants the user belongs to will be updated.}
@returns(200) {userId: str, affectedTenants: num, rolesAdded: [str], rolesRemoved: [str]} # Roles updated successfully (sync) or task queued (async)

@endpoint GET /resources/vendor-only/users/v1/bulk-roles/status/{taskId}
@desc Get status of bulk roles update task
@required {taskId: str}
@returns(200) {id: str, userId: str, status: str, totalTenants: num, processedTenants: num, addedRoleIds: [str], removedRoleIds: [str], errors: [map]} # Task status

@endpoint GET /resources/users/v1/email
@desc Get user by email
@required {email: str}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), subAccountAccessAllowed: bool, managedBy: str}

@endpoint GET /resources/users/v1/{id}
@desc Get user by ID
@required {id: str, frontegg-tenant-id: str # The account (tenant) ID identifier}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint POST /resources/users/v1/{userId}/verify
@desc Verify user
@required {userId: str}
@returns(200)

@endpoint PUT /resources/users/v1/{userId}/invisible
@desc Make user invisible
@required {userId: str, invisible: bool}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint PUT /resources/users/v1/{userId}/superuser
@desc Make user super-user
@required {userId: str, superUser: bool}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint PUT /resources/users/v1/{userId}/tenant
@desc Set user's account (tenant)
@required {userId: str, tenantId: str # Desired tenant to set as active tenant for user}
@optional {validateTenantExist: bool}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint POST /resources/users/v1/{userId}/tenant
@desc Add user to account (tenant)
@required {userId: str, tenantId: str}
@optional {validateTenantExist: bool, skipInviteEmail: bool}
@returns(201) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint PUT /resources/users/v1/{userId}/email
@desc Update user email
@required {userId: str, email: str(email)}
@returns(200) {id: str, email: str, name: str, profilePictureUrl: str, sub: str, verified: bool, mfaEnrolled: bool, mfaBypass: bool, phoneNumber: str, roles: [map], permissions: [map], provider: str, tenantId: str, tenantIds: [str], activatedForTenant: bool, isLocked: bool, tenants: [map], invisible: bool, superUser: bool, metadata: str, vendorMetadata: str, externalId: str, createdAt: str(date-time), lastLogin: str(date-time), groups: [map], subAccountAccessAllowed: bool, managedBy: str}

@endpoint POST /resources/users/v1/{userId}/links/generate-activation-token
@desc Generate activation token
@required {userId: str}
@returns(201) {link: str, token: str, userId: str}

@endpoint POST /resources/users/v1/{userId}/links/generate-password-reset-token
@desc Generate password reset token
@required {userId: str}
@returns(201) {link: str, token: str, userId: str}

@endpoint POST /resources/users/v1/{userId}/unlock
@desc Unlock user
@required {userId: str}
@returns(200)

@endpoint POST /resources/users/v1/{userId}/lock
@desc Lock user
@required {userId: str}
@returns(200)

@endpoint PUT /resources/users/v1/tenants/migrate
@desc Move all users from one account (tenant) to another
@required {srcTenantId: str, targetTenantId: str}
@returns(200)

@endpoint GET /resources/applications/v1/{appId}/users
@desc Get users for application
@required {appId: str}
@returns(200)

@endpoint GET /resources/applications/v1/{userId}/apps
@desc Get applications for user
@required {userId: str}
@returns(200)

@endpoint POST /resources/applications/v1
@desc Assign users to application
@required {appId: str, tenantId: str, userIds: [str]}
@returns(201)

@endpoint DELETE /resources/applications/v1
@desc Unassign users from application
@required {appId: str, tenantId: str, userIds: [str]}
@returns(200)

@endpoint GET /resources/applications/user-tenants/active/v1
@desc Get user active accounts (tenants) in applications
@required {frontegg-user-id: str # The user ID identifier}
@returns(200) {applicationActiveTenants: [map]}

@endpoint PUT /resources/applications/user-tenants/active/v1
@desc Switch users active account (tenant) in applications
@required {frontegg-user-id: str # The user ID identifier, activeApplicationTenants: [map{applicationId!: str, tenantId!: str}] # List of applications and tenants to set as active, for user}
@returns(200)

@end
