> ## 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 Access Request object

> An access request is someone asking for access to an app or its entitlements. This page covers who can see a request, how to file one, which IDs it takes, and when you can cancel it.

An access request is someone asking for access to an app, and optionally to specific entitlements
on it. The user who asks is the requester, and the identity the access is for is the target. They
can be the same user. Filing a request starts its
[approval workflow](https://docs.lumos.com/reference/v1/objects/workflow.md). The request's `status` tracks the workflow
through approval and provisioning. For time-based access, it also tracks removal. Approvals and
manual provisioning steps appear as [tasks](https://docs.lumos.com/reference/v1/objects/task.md) on the request.

```json The Access Request object theme={null}
{
  "id": "9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d",
  "app_id": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
  "app_name": "GitHub",
  "requester_user": {
    "id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
    "email": "jane.doe@acme.com",
    "given_name": "Jane",
    "family_name": "Doe",
    "status": "active"
  },
  "target_user": {
    "id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
    "email": "jane.doe@acme.com",
    "given_name": "Jane",
    "family_name": "Doe",
    "status": "active"
  },
  "supporter_user": null,
  "status": "pending-approval",
  "notes": {},
  "expires_at": null,
  "expiration_in_seconds": null,
  "requested_at": "2026-09-01T17:02:10.905133Z",
  "entitlements": [
    { "id": "4d5e6f70-8192-4a3b-8c4d-5e6f70819203", "label": "Maintainer" }
  ]
}
```

## Attributes

| Field | Type | Description |
| - | - | - |
| `id` | string | Unique identifier for the request. Always present. |
| `app_id` | string | The [app](https://docs.lumos.com/reference/v1/objects/app.md) the request is for. Always present. |
| `app_name` | string | The app's display name. Always present. |
| `requester_user` | object or null | The [user](https://docs.lumos.com/reference/v1/objects/user.md) who asked. `null` for requests Lumos filed itself, such as those from an Access Policy. |
| `target_user` | object | The identity the access is for, as a user object. Always present. |
| `supporter_user` | object or null | The last approver, other than a manager, who approved or denied the request. `null` until such an approver acts. |
| `status` | string | Where the request stands. See [Statuses](#statuses). Always present. |
| `notes` | object | Notes people left when they acted on the request, keyed by the status they moved it to. |
| `expires_at` | string or null | For time-based access, when the granted access ends. `null` for permanent access. |
| `expiration_in_seconds` | integer or null | For time-based access, how long after provisioning the access lasts. `null` for permanent access. |
| `requested_at` | string or null | When the requester filed the request. |
| `entitlements` | array | The entitlements requested, each `{id, label}`. See [Entitlements on a request](#entitlements-on-a-request). |
| `tasks` | array | The request's tasks that you can see. Only present with `expand=tasks`. |
| `custom_fields` | array | The requester's answers to the app's custom intake fields, each `{reference_key, prompt, response}`. `reference_key` is `null` when the field was deleted after the request was filed. Only present with `expand=custom_fields`. |

## Who can see a request

You can see requests you filed and requests where you're the target. Of the built-in roles, Admin,
Read Only Admin, AppStore Read Only Admin, and App Admin can see every request in your organization.
A custom role can also grant this access.

[Get Access Request](https://docs.lumos.com/api-reference/v1/access-requests/get-access-request.md),
[List Access Requests](https://docs.lumos.com/api-reference/v1/access-requests/list-access-requests.md), and
[Cancel Access Request](https://docs.lumos.com/api-reference/v1/access-requests/cancel-access-request.md) act only on
requests you can see. List Access Requests applies this whatever filters you pass.

The approver of a request's current stage can also get the request with Get Access Request, until
the request no longer waits on them. List Access Requests doesn't return it for them.

## Statuses

`status` is one of the values below. The statuses marked cancellable are the ones a request holds
while it's still in progress. [Cancelling](#cancelling) returns `409` for the others.

| Status | Meaning | Cancellable |
| - | - | - |
| `pending` | Just filed. Nothing has been decided yet. | Yes |
| `pending-manager-approval` | Waiting for a manager to approve it. | Yes |
| `manager-approved` | A manager approved it. It can still need another approval. | Yes |
| `manager-denied` | A manager denied it. | No |
| `pending-approval` | Waiting for an approver. | Yes |
| `approved` | An approver approved it, or it needed no approval. Provisioning comes next. | Yes |
| `denied` | Denied during approval. | No |
| `expired` | Nobody approved or denied it in time. | No |
| `cancelled` | Cancelled before it finished. | No |
| `pending-provisioning` | Being provisioned. A request can also stay in this status while a manual provisioning task is open. Check its tasks rather than waiting for the next status. | Yes |
| `pending-manual-provisioning` | Waiting for someone to grant the access by hand. | Yes |
| `denied-provisioning` | Someone declined to grant the access at provisioning time. | No |
| `provisioned` | The access is in place, and Lumos is finishing the request. | Yes |
| `completed` | Finished, with nothing more pending. | No |
| `pending-deprovisioning` | Time-based access ended, and Lumos is removing it. | Yes |
| `pending-manual-deprovisioning` | Time-based access ended, and someone has to remove it by hand. | Yes |
| `time-based-expired` | Time-based access ended, and the access was removed. | No |
| `time-based-expired-failed` | Removing the time-based access failed, and the removal is unresolved. | No |
| `time-based-expired-cancelled` | The removal was cancelled before it removed the access, for example because a newer request renewed the access. | No |
| `reverting` | Someone chose to undo the request, and the undo hasn't finished. | Yes |
| `reverted` | The undo finished. | No |

## Filing a request

[Create Access Request](https://docs.lumos.com/api-reference/v1/access-requests/create-access-request.md) needs an `app_id`
and a `business_justification`:

```json theme={null}
{
  "app_id": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
  "entitlement_ids": ["4d5e6f70-8192-4a3b-8c4d-5e6f70819203"],
  "business_justification": "Maintaining the release pipeline this quarter.",
  "access_length": "30 days"
}
```

* **The justification is required.** A call without `business_justification` returns `400`.
  Create Access Request still accepts the deprecated `note` field in its place.
* **The target** is you unless you send `target_user_id`.
* **The requester** is you. Only an Admin can send `requester_user_id` to file on someone else's
  behalf. If anyone else sends it, the call returns `403`.
* **`access_length`** must be one of the time-based access options the app offers. When you name
  entitlements, it must be an option that all of them offer. Any other value returns `400`. Omit it
  for permanent access, which works only if the app offers `Unlimited`. The possible options are:

  `2 hours`, `4 hours`, `8 hours`, `12 hours`, `1 day`, `2 days`, `3 days`, `7 days`, `14 days`,
  `30 days`, `90 days`, and `Unlimited`.
* **`custom_fields`** answers the app's
  [custom intake fields](https://docs.lumos.com/reference/v1/objects/app.md#custom-intake-fields), keyed by
  `reference_key`, such as `{"environment": "Production"}`. Every required field needs an answer
  that isn't blank. An answer can be up to 500 characters, and a dropdown answer must match one of
  its options exactly. A missing answer, an unknown key, or an answer that breaks these rules
  returns `400` with `code` set to `access_request.custom_fields_invalid`. `errors` lists each
  problem, with `field` set to `custom_fields.<reference_key>`.

A successful call returns `201` with an `access_requests` list. One call can create more than one
request, so read the list rather than assuming a single item.

An `app_id`, `target_user_id`, or `requester_user_id` that doesn't exist in your organization
returns `404`. If the requester isn't allowed to file the request, the call returns `403` with
`code` set to `access_request.forbidden`. Lumos can refuse a request for other reasons, such as a
webhook that rejects it. These return `400` with `code` set to `access_request.` followed by the
reason: `invalid`, `not_requestable`, `entitlement_invalid`, `access_length_invalid`,
`expiration_invalid`, `itsm_ticket_id_required`, `missing_fields`, or `rejected_by_webhook`.

## Entitlements on a request

`entitlement_ids` takes entitlement IDs, the IDs that
[List Entitlements](https://docs.lumos.com/api-reference/v1/entitlements/list-entitlements.md) returns. To see what an app
offers a requester, call
[Get App Entitlement AppStore Catalog](https://docs.lumos.com/api-reference/v1/apps/get-app-entitlement-appstore-catalog.md).
Omit `entitlement_ids` to request the app itself.

Each entitlement must be one you can request on the app in `app_id`. Otherwise the call fails:

| Response | When |
| - | - |
| `404` with `code` `access_request.entitlement_not_found` | No entitlement with that ID exists in your organization. |
| `400` with `code` `access_request.entitlement_not_requestable` | The entitlement exists, but you can't request it on this app. |

[Get Access Request](https://docs.lumos.com/api-reference/v1/access-requests/get-access-request.md) and
[List Access Requests](https://docs.lumos.com/api-reference/v1/access-requests/list-access-requests.md) return
`entitlements` as `{id, label}` objects. Each entitlement appears once. If you're moving from
requestable permissions, see
[Migrate requestable permissions to entitlements](https://docs.lumos.com/reference/v1/migrate/permissions-to-entitlements.md).

## Time-based access

Send `access_length` to request access that ends. Lumos turns it into seconds when you file, and
two fields track it:

* `expiration_in_seconds` is the length, for example `2592000` for `30 days`.
* `expires_at` is `null` until the access is granted. After that, it's the time the access ends,
  which is the time of the grant plus `expiration_in_seconds`.

When that time comes, Lumos runs the app's deprovisioning workflow, which removes the access or
creates a manual deprovisioning task. The request moves through `pending-deprovisioning` or
`pending-manual-deprovisioning` to `time-based-expired`. An `access_length` of `Unlimited`, or none
at all, means permanent access, and both fields stay `null`.

## Cancelling

[Cancel Access Request](https://docs.lumos.com/api-reference/v1/access-requests/cancel-access-request.md) takes an optional
reason and returns `204`:

```json theme={null}
{ "reason": "No longer needed." }
```

You can cancel a request while [Statuses](#statuses) marks its status as cancellable. In any other
status, the call returns `409`.

The requester, the target, and an Admin can cancel a request. Anyone else who can see the request,
such as an App Admin or the approver of its current stage, gets `403`.

## Expanding a request

* `expand=tasks` adds the request's tasks that you can see. Each task has the same shape that
  [Get Task](https://docs.lumos.com/api-reference/v1/tasks/get-task.md) returns when you send no `expand`.
* `expand=custom_fields` adds the requester's answers to the app's custom intake fields.

## Listing

| Parameter | Effect |
| - | - |
| `user_id` | Requests where this user is the requester or the target. |
| `requester_user_id` | Requests this user filed. |
| `target_user_id` | Requests where this user is the target. |
| `statuses` | Requests in any of these statuses. Repeat the parameter for more than one. |
| `order_by` | `created_at` (the default, oldest first) or `created_at desc` (newest first), by when the request was filed. |

`statuses` takes the labels in [Statuses](#statuses). Any other value, such as `PENDING_APPROVAL`,
returns `400`.

A user ID that doesn't exist in your organization returns `404`. A page token works only with the
same filters and `order_by` as the call that returned it. [Pagination](https://docs.lumos.com/reference/v1/pagination.md)
covers page tokens.

## Endpoints

| Endpoint | Path |
| - | - |
| [List Access Requests](https://docs.lumos.com/api-reference/v1/access-requests/list-access-requests.md) | `GET /v1/access-requests` |
| [Create Access Request](https://docs.lumos.com/api-reference/v1/access-requests/create-access-request.md) | `POST /v1/access-requests` |
| [Get Access Request](https://docs.lumos.com/api-reference/v1/access-requests/get-access-request.md) | `GET /v1/access-requests/{id}` |
| [Cancel Access Request](https://docs.lumos.com/api-reference/v1/access-requests/cancel-access-request.md) | `POST /v1/access-requests/{id}:cancel` |
