Skip to main content
An account is one identity’s presence in an app. An identity is a person, a role, or a service, and a user in your organization is one kind of identity. A user with a GitHub seat has an account on your GitHub app. The same user with an Okta profile has a separate account on your Okta app. Lumos discovers accounts when it syncs an app, and entitlements are attached to accounts. Not every account belongs to a person. account_type names the kind: user for a human seat, role for a role that others assume, such as in AWS, and service for a non-human service identity, such as in GCP.
The Account object

Attributes

List Entitlement Accounts returns a smaller shape: only id, app_id, account_type, and status. The full object comes from List Accounts and List User Accounts.

The expanded app

app is absent unless you pass expand=app. It then carries the app’s base fields: id, label, app_class_id, instance_id, logo_url, website_url, category, description, status, and disconnected. It isn’t the full App object. It omits the workflow fields, appstore_settings, sync_status, and the other admin fields, so fetch the app by app_id when you need them.

Lifecycle status

status is the account’s lifecycle state, not a health check. Eleven values are possible. Read the removal states closely, because they differ in whether access is recoverable and whether the license is removed. Four of these look interchangeable and aren’t. deprovisioned is terminal and unrecoverable. suspended and archived are recoverable. access-removed means the license may still cost you money even though the account can no longer log in. If you’re reclaiming spend rather than revoking access, branch on access-removed. status is nullable. Null means Lumos has no lifecycle state recorded, so treat it as unknown rather than as inactive.

Sources

sources lists how Lumos found the account. Each value is one of okta, onelogin, jumpcloud, atlassian, google-cloud, google-workspace-oauth, google-workspace-quick-inbox, google-workspace-deep-inbox, microsoft-oauth, microsoft-gcc, microsoft-deep-inbox, integration, custom, mcp, native, or manual. An entitlement’s source takes the same values. mcp marks an account that MCP Governance found when someone used an MCP server’s tools. For these, the MCP server is the app, and its tools are entitlements.

Finding accounts

v1 has no endpoint that fetches one account by ID. Use these lists instead:
  • List Accounts returns every account in your organization. Filter it with app_id, status, sources, email, has_user, discovered_after, and discovered_before. status and sources take the values above. Any other value, such as ACTIVE, returns 400.
  • List User Accounts returns every account one Lumos user has, across apps.
  • List Entitlement Accounts returns the accounts that hold one entitlement.
  • List Account Entitlements returns the entitlements that one account holds.
The last two are inverses of each other, and between them they answer the questions v1 is built for: who has this access, and what access does this identity have. Every list returns results in pages, as Pagination describes. The account ID that List Account Entitlements takes is the id above. It’s the account’s own identifier, not its user_id and not its unique_identifier. Identifiers explains which id each path parameter takes.

Unmatched accounts

List Accounts returns accounts that Lumos hasn’t matched to a user, such as a contractor’s or a shared login that you uploaded. Their user_id is null. Send has_user=true to list only accounts matched to a user, or has_user=false to list only the rest.

Uploading accounts

Lumos has no integration for a custom app, so it can’t discover the app’s accounts. Send them with Upload Accounts. Pass the app’s id as app_id and at least one account in accounts. Each account needs a unique_identifier, and can also carry email, first_name, last_name, status, last_login, last_activity, entitlements, and attributes. status takes the same values as the account’s status. A request with an unknown field returns 400.
The upload runs in the background. The call returns 202 with an operation. Poll Get Operation until done is true, as Long-running operations describes. A failed upload ends with error.code set to account_upload.failed. A cancelled upload ends with error.code set to account_upload.cancelled.

Endpoints