> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lumos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The Account object

> What an account represents, the fields v1 returns, and how to find and upload accounts.

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](https://docs.lumos.com/reference/v1/objects/app.md). 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](https://docs.lumos.com/reference/v1/objects/entitlement.md) 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.

```json The Account object theme={null}
{
  "id": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
  "app_id": "2b3c4d5e-6f70-8901-bcde-f12345678901",
  "account_type": "user",
  "status": "active",
  "unique_identifier": "jane.smith",
  "email": "jane.smith@example.com",
  "user_id": "3c4d5e6f-7081-9012-cdef-123456789012",
  "discovered_at": "2026-03-02T17:41:09Z",
  "last_login": "2026-09-21T14:03:55Z",
  "last_activity": "2026-09-23T09:12:40Z",
  "sources": ["okta"]
}
```

## Attributes

| Field | Type | Description |
| - | - | - |
| `id` | string | Unique identifier for the account. Always present. |
| `app_id` | string | The app that owns this account. Always present. |
| `account_type` | string | One of `user`, `role` (for example AWS), or `service` (for example GCP). Always present. |
| `status` | string or null | Where the account sits in its lifecycle. See [Lifecycle status](#lifecycle-status). |
| `unique_identifier` | string | The account's stable identifier in the app, as the app reports it. Always present. |
| `email` | string or null | The account's email, as the app reports it. |
| `user_id` | string or null | The Lumos [user](https://docs.lumos.com/reference/v1/objects/user.md) this account belongs to. Pass it to [Get User](https://docs.lumos.com/api-reference/v1/users/get-user.md). `null` for an account Lumos hasn't matched to a user. See [Unmatched accounts](#unmatched-accounts). |
| `discovered_at` | string or null | When Lumos first discovered the account, in ISO 8601 format. |
| `last_login` | string or null | When the account last logged in to the app, in ISO 8601 format. |
| `last_activity` | string or null | When the account last did something Lumos tracks, in ISO 8601 format. |
| `sources` | array | How Lumos found the account. See [Sources](#sources). Always present. |
| `app` | object | The app's base fields. Only present with `expand=app`. See [The expanded app](#the-expanded-app). |

> [!NOTE]
>
> [List Entitlement Accounts](https://docs.lumos.com/api-reference/v1/entitlements/list-entitlement-accounts.md) returns a
> smaller shape: only `id`, `app_id`, `account_type`, and `status`. The full object comes from
> [List Accounts](https://docs.lumos.com/api-reference/v1/accounts/list-accounts.md) and
> [List User Accounts](https://docs.lumos.com/api-reference/v1/users/list-user-accounts.md).

## 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](https://docs.lumos.com/reference/v1/objects/app.md). 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.

| Status | Meaning |
| - | - |
| `discovered` | Inferred by Lumos account discovery, for example from Google sign-in grants or email in a connected inbox, rather than read from the app. Can include accounts that don't exist, so it doesn't prove the account is real or in use. |
| `staged` | Queued for provisioning but not provisioned yet. Applies where provisioning is asynchronous. |
| `access-created` | Provisioned, but never accessed. |
| `active` | Live and accessible. |
| `suspended` | Access revoked, recoverable. The license may or may not have been removed. |
| `archived` | The same as `suspended`, except the account was archived rather than suspended. Only Google Workspace archives accounts today. |
| `deprovisioned` | Access revoked, license removed, and not recoverable. |
| `manually-removed` | Access revoked by hand, outside Lumos. Lumos presumes the license is removed. |
| `access-removed` | Access revoked upstream, such as through Okta, but a license may still exist on the app. |
| `non-corporate` | The account doesn't exist, or is an employee's personal account. |
| `waiting-manual-removal` | Lumos asked someone to remove the access by hand, and is waiting for the answer. |

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](https://docs.lumos.com/api-reference/v1/accounts/list-accounts.md) 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](https://docs.lumos.com/api-reference/v1/users/list-user-accounts.md) returns every account one Lumos
  user has, across apps.
* [List Entitlement Accounts](https://docs.lumos.com/api-reference/v1/entitlements/list-entitlement-accounts.md) returns the
  accounts that hold one entitlement.
* [List Account Entitlements](https://docs.lumos.com/api-reference/v1/accounts/list-account-entitlements.md) returns the
  entitlements that one account holds.

```bash theme={null}
curl -s 'https://api.lumos.com/v1/accounts?app_id=2b3c4d5e-6f70-8901-bcde-f12345678901&status=active&expand=app' \
  --header 'Authorization: Bearer lsk_your_token'
```

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](https://docs.lumos.com/reference/v1/pagination.md) 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](https://docs.lumos.com/reference/v1/identifiers.md) explains which `id` each path parameter takes.

### Unmatched accounts

[List Accounts](https://docs.lumos.com/api-reference/v1/accounts/list-accounts.md) 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](https://docs.lumos.com/api-reference/v1/accounts/upload-accounts.md). 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`](#lifecycle-status). A request with an unknown field returns `400`.

```bash theme={null}
curl -s -X POST 'https://api.lumos.com/v1/accounts:upload' \
  --header 'Authorization: Bearer lsk_your_token' \
  --header 'Content-Type: application/json' \
  --data '{
    "app_id": "2b3c4d5e-6f70-8901-bcde-f12345678901",
    "accounts": [
      {
        "unique_identifier": "jane.smith",
        "email": "jane.smith@example.com",
        "status": "active",
        "entitlements": [{ "unique_identifier": "role-admin", "type": "Role", "name": "Admin" }]
      }
    ]
  }'
```

The upload runs in the background. The call returns `202` with an operation. Poll
[Get Operation](https://docs.lumos.com/api-reference/v1/operations/get-operation.md) until `done` is `true`, as
[Long-running operations](https://docs.lumos.com/reference/v1/long-running-operations.md) 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

| Endpoint | Path |
| - | - |
| [List Accounts](https://docs.lumos.com/api-reference/v1/accounts/list-accounts.md) | `GET /v1/accounts` |
| [List Account Entitlements](https://docs.lumos.com/api-reference/v1/accounts/list-account-entitlements.md) | `GET /v1/accounts/{account_uuid}/entitlements` |
| [Upload Accounts](https://docs.lumos.com/api-reference/v1/accounts/upload-accounts.md) | `POST /v1/accounts:upload` |
| [List Entitlement Accounts](https://docs.lumos.com/api-reference/v1/entitlements/list-entitlement-accounts.md) | `GET /v1/entitlements/{entitlement_uuid}/accounts` |
| [List User Accounts](https://docs.lumos.com/api-reference/v1/users/list-user-accounts.md) | `GET /v1/users/{user_id}/accounts` |
