> ## 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 Entitlement object

> What an entitlement represents, every field it returns, and how its settings override the app's.

An entitlement is one grantable unit of access on an [app](https://docs.lumos.com/reference/v1/objects/app.md), such as a
role, a license, a group membership, or an access right. When someone requests access in Lumos, they
request an entitlement. The result is an [account](https://docs.lumos.com/reference/v1/objects/account.md) that holds that
entitlement.

Each entitlement belongs to exactly one app. `entitlement_type_label` names the kind of
entitlement, such as `Role`, `License`, or `Group`. The app sets this label, so the values vary by
app. Lumos has no fixed list of values.

```json The Entitlement object theme={null}
{
  "id": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
  "app_id": "2b3c4d5e-6f70-8901-bcde-f12345678901",
  "label": "Billing Admin",
  "entitlement_type_label": "Role",
  "source": "okta",
  "description": "Full access to invoices and payment methods.",
  "description_override": "Full access to invoices and payment methods.",
  "approval_workflow_override": { "id": "3c4d5e6f-7081-9012-cdef-123456789012" },
  "provisioning_workflow": { "id": "4d5e6f70-8192-0123-def1-234567890123" },
  "deprovisioning_workflow": null,
  "custom_approval_message_override": null
}
```

## Attributes

| Field | Type | Description |
| - | - | - |
| `id` | string | Unique identifier for the entitlement. Always present. |
| `app_id` | string | The app that owns this entitlement. Always present. |
| `label` | string | Human-readable name, such as a role or license name. Always present. |
| `entitlement_type_label` | string | What kind of entitlement this is, as the app describes it, such as `Role`, `License`, or `Group`. Always present. |
| `source` | string | How Lumos found it. `manual` means someone created it in Lumos. Any other value names the system Lumos found it in, such as `okta`. [Sources](https://docs.lumos.com/reference/v1/objects/account.md#sources) lists the values. |
| `description` | string or null | The description requesters see. It's `description_override` when that's set, and the integration's description otherwise. Read-only. |
| `description_override` | string or null | The description set in Lumos, kept across syncs. `null` when none is set. Always present. |
| `approval_workflow_override` | object or null | Approval workflow that overrides the app's. See [Overrides and inheritance](#overrides-and-inheritance). |
| `provisioning_workflow` | object or null | The workflow that grants this entitlement. |
| `deprovisioning_workflow` | object or null | The workflow that removes this entitlement. |
| `custom_approval_message_override` | string or null | This entitlement's own post-approval message. Null means it inherits the app's. |
| `appstore_settings` | object or null | AppStore catalog settings. See [AppStore settings](#appstore-settings). |

## Overrides and inheritance

An entitlement belongs to an app, and several of its fields override the app's settings. For the
fields that inherit, **`null` means the entitlement uses the app's value, and a value overrides
it.** [AppStore settings](#appstore-settings) names two fields that don't inherit.

`custom_approval_message_override` is the clearest case. Null means requesters see the app's
`post_approval_message`. If you set it, this entitlement's message replaces the app's message for
this entitlement only.

The three workflow fields follow the same rule, but their names differ:

* `approval_workflow_override` is explicitly an override of the app's `approval_workflow`.
* `provisioning_workflow` and `deprovisioning_workflow` are the entitlement's own bindings. They
  take precedence over the app's `default_provisioning_workflow` and
  `default_deprovisioning_workflow`. The word "default" in the app's field names marks the app's
  workflows as the fallback.

Each workflow field returns `{ "id": … }` by default. Name it in `expand` to get the full
[workflow](https://docs.lumos.com/reference/v1/objects/workflow.md) inline:

```bash theme={null}
curl -s 'https://api.lumos.com/v1/entitlements/1a2b3c4d-5e6f-7890-abcd-ef1234567890?expand=provisioning_workflow' \
  --header 'Authorization: Bearer lsk_your_token'
```

Each workflow field also has its own read and write endpoints, listed under
[Endpoints](#endpoints). Use those endpoints to change which workflow is bound.

To make the entitlement use its app's approval workflow again, call
[Remove Entitlement Approval Workflow Override](https://docs.lumos.com/api-reference/v1/entitlements/remove-entitlement-approval-workflow-override.md).
It returns `204` whether or not an override was bound, and it doesn't delete the workflow.

## AppStore settings

`appstore_settings` appears only when you expand it. Even then, the response **omits it** when the
parent app isn't in the AppStore or the entitlement has no AppStore settings. Every entitlement
made with [Create Entitlement](https://docs.lumos.com/api-reference/v1/entitlements/create-entitlement.md) has AppStore
settings. A synced entitlement has them only if Lumos can grant and remove it through the app's
integration.

Expanded, it has four fields, and two of them inherit:

| Field | Inherits from the app? |
| - | - |
| `visible_in_appstore` | No. Always a concrete boolean on the entitlement. |
| `allowed_requester_group_uuids_override` | Yes. Null means the app's allowed requester groups apply. An empty list means anyone can request it. |
| `time_based_access_override` | Yes. Null means the app's time-based access options apply. |
| `request_validation_webhook_uuid` | **No.** Set directly on the entitlement. Null means no webhook. |

`request_validation_webhook_uuid` looks like the two override fields, but it doesn't inherit. When
it's `null`, no webhook validates requests for this entitlement. The app's webhook doesn't apply.

These settings also have their own endpoints.
[Get Entitlement AppStore Settings](https://docs.lumos.com/api-reference/v1/entitlements/get-entitlement-appstore-settings.md)
returns the full object, so you don't need to expand the entitlement.
[Update Entitlement AppStore Settings](https://docs.lumos.com/api-reference/v1/entitlements/update-entitlement-appstore-settings.md)
is the only way to change the settings. It takes the fields that a read returns, and a field you
omit keeps its value:

| Field | What it does |
| - | - |
| `visible_in_appstore` | Whether the entitlement appears in the catalog. |
| `allowed_requester_group_uuids_override` | The groups whose members can request this entitlement, instead of the app's, as group `id`s. `null` makes the entitlement use the app's groups again. An empty list lets anyone request the entitlement, even when the app restricts who can request it. A group outside your organization returns `422` with `code` set to `group.not_found`. |
| `time_based_access_override` | This entitlement's own durations, as `{ "options": [...] }` with at least one label. `null` makes the entitlement use the app's options again. A label your organization doesn't offer returns `422` with `code` set to `time_based_access.unknown_option`. |
| `request_validation_webhook_uuid` | The inline webhook that checks requests for this entitlement. `null` removes it. It must be a `request-validation` webhook. A webhook of another type returns `422` with `code` set to `request_validation_webhook.wrong_type`. |

## Creating, updating, and deleting

[Create Entitlement](https://docs.lumos.com/api-reference/v1/entitlements/create-entitlement.md) takes `app_id` and `label`,
and creates a requestable entitlement on that app, which people can request from the AppStore. It
also takes `description_override` and `custom_approval_message_override`, which set the
entitlement's description and post-approval message in the same call:

```bash theme={null}
curl -s -X POST 'https://api.lumos.com/v1/entitlements' \
  --header 'Authorization: Bearer lsk_your_token' \
  --header 'Content-Type: application/json' \
  --data '{
    "app_id": "2b3c4d5e-6f70-8901-bcde-f12345678901",
    "label": "Billing Admin"
  }'
```

Configure everything else after you create the entitlement. Set its workflows with the workflow
endpoints, and its AppStore settings with
[Update Entitlement AppStore Settings](https://docs.lumos.com/api-reference/v1/entitlements/update-entitlement-appstore-settings.md).

An entitlement created with `POST` has `visible_in_appstore` set to `true`. If its app is in the
AppStore, everyone allowed to request that app sees the entitlement in the catalog and can request
it immediately. `POST` doesn't accept `visible_in_appstore`, so you can't create an entitlement
hidden. To keep it out of the catalog, set `visible_in_appstore` to `false` with
[Update Entitlement AppStore Settings](https://docs.lumos.com/api-reference/v1/entitlements/update-entitlement-appstore-settings.md)
right after you create it. While the app isn't in the AppStore, that endpoint returns `404`, so
hide the entitlement after you add the app to the AppStore.

Entitlements that a sync imports can start hidden or visible, so check `visible_in_appstore` rather
than assuming either.

[Update Entitlement](https://docs.lumos.com/api-reference/v1/entitlements/update-entitlement.md) changes `label`,
`description_override`, and `custom_approval_message_override`. A field you omit keeps its value,
and any other field, including the read-only `description`, returns `400`.

* `label` changes only for entitlements created in Lumos (`source` is `manual`). For any other
  entitlement, a different `label` returns `400`. Its current `label` is accepted and changes
  nothing.
* `description_override` is shown to requesters as `description`, up to 2,000 characters. Lumos
  stores it as sent and keeps it through syncs. `null` removes it, and the integration's
  description returns on the next sync.
* `custom_approval_message_override` takes up to 511 characters. `null` makes the entitlement use
  the app's `post_approval_message`. A message for an entitlement that can't be requested returns
  `422` with `code` set to `entitlement.not_requestable`. `null` for that entitlement is accepted
  and changes nothing.

Change workflows with the workflow endpoints, and change AppStore visibility with Update
Entitlement AppStore Settings.

[Delete Entitlement](https://docs.lumos.com/api-reference/v1/entitlements/delete-entitlement.md) fails while any account
holds the entitlement. It returns `409` with `code` set to `entitlement_in_use`, and `errors` has
one entry for `active_accounts`, whose `message` is the number of accounts that still hold it.
Revoke that access first, then retry.

Only entitlements from a manual source can be deleted. Any other entitlement returns `422` with
`code` set to `entitlement.not_manual`.

`DELETE` returns `409` with `code` set to `entitlement.delete_blocked`, and `detail` naming the
reason, while any of these block the delete:

* It has pending access requests.
* It has time-based access scheduled for removal.
* A draft or published Access Policy references it.

## Finding entitlements

[List Entitlements](https://docs.lumos.com/api-reference/v1/entitlements/list-entitlements.md) returns every entitlement in
your organization, across all apps. When you already have the app or the account, start from it
instead:

* [List App Entitlements](https://docs.lumos.com/api-reference/v1/apps/list-app-entitlements.md): everything grantable on
  one app.
* [List Account Entitlements](https://docs.lumos.com/api-reference/v1/accounts/list-account-entitlements.md): everything one
  account currently holds.

List Entitlements and List App Entitlements take the same two filters. `search` is a
case-insensitive substring match on `label`. `visible_in_appstore=true` returns the entitlements
visible in the AppStore catalog, and `visible_in_appstore=false` returns the hidden ones. Either
value excludes entitlements with no AppStore settings. An entitlement on an app that isn't in the
AppStore counts as hidden. [AppStore settings](#appstore-settings) covers which entitlements have
them.

All three lists return results in pages, so read [Pagination](https://docs.lumos.com/reference/v1/pagination.md) before you
assume that a single call returned everything.

## Endpoints

| Endpoint | Path |
| - | - |
| [List Entitlements](https://docs.lumos.com/api-reference/v1/entitlements/list-entitlements.md) | `GET /v1/entitlements` |
| [Create Entitlement](https://docs.lumos.com/api-reference/v1/entitlements/create-entitlement.md) | `POST /v1/entitlements` |
| [Get Entitlement](https://docs.lumos.com/api-reference/v1/entitlements/get-entitlement.md) | `GET /v1/entitlements/{entitlement_uuid}` |
| [Update Entitlement](https://docs.lumos.com/api-reference/v1/entitlements/update-entitlement.md) | `PATCH /v1/entitlements/{entitlement_uuid}` |
| [Delete Entitlement](https://docs.lumos.com/api-reference/v1/entitlements/delete-entitlement.md) | `DELETE /v1/entitlements/{entitlement_uuid}` |
| [List Entitlement Accounts](https://docs.lumos.com/api-reference/v1/entitlements/list-entitlement-accounts.md) | `GET /v1/entitlements/{entitlement_uuid}/accounts` |
| [Get Entitlement Approval Workflow Override](https://docs.lumos.com/api-reference/v1/entitlements/get-entitlement-approval-workflow-override.md) | `GET /v1/entitlements/{entitlement_uuid}/approval-workflow-override` |
| [Set Entitlement Approval Workflow Override](https://docs.lumos.com/api-reference/v1/entitlements/set-entitlement-approval-workflow-override.md) | `PUT /v1/entitlements/{entitlement_uuid}/approval-workflow-override` |
| [Remove Entitlement Approval Workflow Override](https://docs.lumos.com/api-reference/v1/entitlements/remove-entitlement-approval-workflow-override.md) | `DELETE /v1/entitlements/{entitlement_uuid}/approval-workflow-override` |
| [Get Entitlement Provisioning Workflow](https://docs.lumos.com/api-reference/v1/entitlements/get-entitlement-provisioning-workflow.md) | `GET /v1/entitlements/{entitlement_uuid}/provisioning-workflow` |
| [Set Entitlement Provisioning Workflow](https://docs.lumos.com/api-reference/v1/entitlements/set-entitlement-provisioning-workflow.md) | `PUT /v1/entitlements/{entitlement_uuid}/provisioning-workflow` |
| [Get Entitlement Deprovisioning Workflow](https://docs.lumos.com/api-reference/v1/entitlements/get-entitlement-deprovisioning-workflow.md) | `GET /v1/entitlements/{entitlement_uuid}/deprovisioning-workflow` |
| [Set Entitlement Deprovisioning Workflow](https://docs.lumos.com/api-reference/v1/entitlements/set-entitlement-deprovisioning-workflow.md) | `PUT /v1/entitlements/{entitlement_uuid}/deprovisioning-workflow` |
| [Get Entitlement AppStore Settings](https://docs.lumos.com/api-reference/v1/entitlements/get-entitlement-appstore-settings.md) | `GET /v1/entitlements/{entitlement_uuid}/appstore-settings` |
| [Update Entitlement AppStore Settings](https://docs.lumos.com/api-reference/v1/entitlements/update-entitlement-appstore-settings.md) | `PATCH /v1/entitlements/{entitlement_uuid}/appstore-settings` |
