---
title: "List access requests (admin queue, or your own)"
method: GET
path: "/access-request"
tags: ["Access requests"]
---

# List access requests (admin queue, or your own)

`GET /access-request`

## Request

- Base URL: `https://api.elaichi.ai`
- URL: `https://api.elaichi.ai/access-request`
- Auth: HTTP bearer

Lists access requests, for two audiences on one route. **Without `mine`** it is the org-wide admin queue and requires `member:manage`; a caller without it gets `403`, never an empty page. Rows are the admin view (`requester`, `resolved_by`, `can_resolve`).

**With `mine=true`** it returns only the caller’s own requests and needs no permission, so the person who filed a request can find it again. Rows are the narrower self view (`can_withdraw`, and a bare `resolved_by_user_id` rather than a resolved name) for every caller, admins included.

`limit`, `cursor`, `q` and `status` apply to both. `q` matches the requested tool name or the requester’s note, not the requester themselves; to find requests by person, list members and filter on `requester_user_id`. It does not match `tool_label`.

## Query parameters

- `limit` integer
- `cursor` string
- `q` string
- `status` 'pending' | 'approved' | 'denied' | 'withdrawn' | 'all'
- `mine` 'true' | 'false' | '1' | '0'

## Headers

- `X-Organization-Id` string

## Response `200`

OK

- object
  - `result` union[], required
    - union: Admin view by default; self view when `mine=true`.
      - object: The admin queue’s row shape — returned by `GET /access-request`, `GET /access-request/{id}` when the caller holds `member:manage`, and `POST /access-request/{id}/resolve`.
        - `id` string: Access request id (`areq_…`).
        - `requester_user_id` string: User id (`usr_…`) of whoever filed the request.
        - `tool` string: What was asked for: a tool name, or a connector slug when `resource_type` is `"connector"`.
        - `resource_type` 'tool' | 'connector'
        - `connector_slug` string, nullable: On a `"tool"` request, the connector the tool lives on when the request named one — what makes approving it able to lift the restriction on that tool. Always null on a `"connector"` request.
        - `connector_label` string: Display name of `connector_slug` (or, on a `"connector"` request, of `tool` itself), falling back to the slug. Present on every view: the requester reads it in the self view exactly as an admin does in the queue.
        - `connector_logo` string, nullable: The connector’s logo for the slug `connector_label` names. `null` when the catalog has no logo for the slug; present under the same conditions as `connector_label`.
        - `reason` 'permission' | 'restriction': What kind of refusal this request is asking to be reconsidered.
        - `permission` string, nullable: Present only when `reason` is `"permission"` — never populated for a `"restriction"`-reason request, on either write or read. That is the disclosure rule: a restriction refusal never names the rule that blocked the caller, so this field must not become a second channel for the same fact.
        - `note` string, nullable: Optional free text from the requester, ≤ 2000 characters.
        - `status` 'pending' | 'approved' | 'denied' | 'withdrawn'
        - `created_at` string, date-time
        - `resolved_at` string, date-time, nullable
        - `resolved_by_user_id` string, nullable: User id (`usr_…`) of the admin who resolved it.
        - `resolution_note` string, nullable
        - `restriction_lifted` boolean, nullable: What an approval did to the requester’s access, on every view: `true` when it wrote a grant, `false` when the request was approved and nothing was lifted (a `resolution: "policy"` approval, access that was already open, or a shape no grant can open), `null` when the question does not apply (not approved, a `permission` request, a tool request with no `connector_slug`). It never says why; the connector’s own `restricted`, `restricted_by` and `restricted_inherited_from` do, within what the caller may be told. An older approval may read `false` for access it did give, so read the connector’s `restricted` for the live answer. It is the outcome at resolve time: a later revoke, expiry or replacement does not change it.
        - `updated_at` string, date-time
        - `requester` object: Resolved member profile. Falls back to `{ id }` alone when the profile row no longer resolves.
          - `id` string: User id (`usr_…`).
          - `name` string, nullable
          - `email` string, email
          - `avatar_url` string, nullable: The person's picture: their stored profile picture, else a Gravatar URL (`d=404`, 96px) derived from their email (the address itself is not sent), else null. Draw initials when it is null or the image fails to load.
        - `resolved_by` object, nullable: Resolved member profile. Falls back to `{ id }` alone when the profile row no longer resolves.
          - `id` string: User id (`usr_…`).
          - `name` string, nullable
          - `email` string, email
          - `avatar_url` string, nullable: The person's picture: their stored profile picture, else a Gravatar URL (`d=404`, 96px) derived from their email (the address itself is not sent), else null. Draw initials when it is null or the image fails to load.
        - `can_resolve` boolean: True while `status` is still `pending` **and** the row is not the caller’s own — the two preconditions `resolve` itself enforces (`409` and `403` respectively).
        - `can_withdraw` boolean: True when the caller is the requester and `status` is still `pending`. Present on this shape as well as on the self view: an admin’s own request sits in their own queue, and withdrawing it is the one verb on that row that is theirs.
        - `will_lift_restriction` boolean: On a pending restriction-reason request approving could act on (a connector request, or a tool request naming its `connector_slug`): whether approving it would actually lift anything. Absent on every other row.
        - `connector_restricted_for_requester` boolean: On the same rows, for a TOOL request only: true when approving lifts nothing because the requester’s WHOLE connector is restricted — one tool cannot be carved out of a connector restricted whole, and an approval never opens the whole connector for a one-tool ask. Their connector access is what an admin would have to grant instead.
        - `lifts_inherited_restriction` boolean: On the same rows, for a CONNECTOR or TOOL request: true when approving opens this FORK (or, for a tool request, that one tool on it) by lifting a block it inherits from the connector it was forked from — through the requester’s role OR through a rule written about them personally. A request for a fork is its own ask: approving it opens THAT FORK for THAT PERSON and nothing else; the original stays restricted for them, a rule naming the fork itself is not overridden, a connector approval never lifts their personal tool rules, and the exception is standing and tied to the fork (revoking the grant re-blocks it).
        - `lifts_inherited_member_rule` boolean: With `lifts_inherited_restriction`: true when the block it lifts is a rule written about the requester personally rather than their role’s. Only then does the grant carry the marker that keeps lifting it while the grant is active — for the originals that blocked it when it was approved, so a block written later on a different ancestor is not bypassed. A lift of a role-layer block alone does not carry it, so a personal block written later on the original is not overridden by it.
        - `inherited_from_member_rule` boolean: On the same rows, for a CONNECTOR request only: true when approving lifts nothing even though the connector is a fork blocked through its original in the requester’s own restrictions. This is now rare: most such forks are covered by `lifts_inherited_restriction` instead.
        - `inherited_from_connector_label` string, nullable: With `lifts_inherited_restriction` or `inherited_from_member_rule`: the display name of the connector it was forked from, or `null` when it cannot be named to this caller (private to someone else, deleted, or the catalog did not answer). Never a slug or id.
      - object: The requester’s own view, returned by `POST /access-request`, `POST /access-request/{id}/withdraw`, and `GET /access-request/{id}` when the caller is the request’s own requester. `resolved_by_user_id` stays a bare id here, because resolving it into a name and email is a member-directory lookup this view does not hand a plain member.
        - `id` string: Access request id (`areq_…`).
        - `requester_user_id` string: User id (`usr_…`) of whoever filed the request.
        - `tool` string: What was asked for: a tool name, or a connector slug when `resource_type` is `"connector"`.
        - `resource_type` 'tool' | 'connector'
        - `connector_slug` string, nullable: On a `"tool"` request, the connector the tool lives on when the request named one — what makes approving it able to lift the restriction on that tool. Always null on a `"connector"` request.
        - `connector_label` string: Display name of `connector_slug` (or, on a `"connector"` request, of `tool` itself), falling back to the slug. Present on every view: the requester reads it in the self view exactly as an admin does in the queue.
        - `connector_logo` string, nullable: The connector’s logo for the slug `connector_label` names. `null` when the catalog has no logo for the slug; present under the same conditions as `connector_label`.
        - `reason` 'permission' | 'restriction': What kind of refusal this request is asking to be reconsidered.
        - `permission` string, nullable: Present only when `reason` is `"permission"` — never populated for a `"restriction"`-reason request, on either write or read. That is the disclosure rule: a restriction refusal never names the rule that blocked the caller, so this field must not become a second channel for the same fact.
        - `note` string, nullable: Optional free text from the requester, ≤ 2000 characters.
        - `status` 'pending' | 'approved' | 'denied' | 'withdrawn'
        - `created_at` string, date-time
        - `resolved_at` string, date-time, nullable
        - `resolved_by_user_id` string, nullable: User id (`usr_…`) of the admin who resolved it.
        - `resolution_note` string, nullable
        - `restriction_lifted` boolean, nullable: What an approval did to the requester’s access, on every view: `true` when it wrote a grant, `false` when the request was approved and nothing was lifted (a `resolution: "policy"` approval, access that was already open, or a shape no grant can open), `null` when the question does not apply (not approved, a `permission` request, a tool request with no `connector_slug`). It never says why; the connector’s own `restricted`, `restricted_by` and `restricted_inherited_from` do, within what the caller may be told. An older approval may read `false` for access it did give, so read the connector’s `restricted` for the live answer. It is the outcome at resolve time: a later revoke, expiry or replacement does not change it.
        - `updated_at` string, date-time
        - `can_withdraw` boolean: True when the caller is the requester and `status` is still `pending`.
  - `next_cursor` string, nullable, required
  - `prev_cursor` string, nullable, required

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not found
- `429`: Rate limited

---

[API](https://skmtc.dev/elaichi/apis/elaichi-api.md) · [All operations](https://skmtc.dev/elaichi/apis/elaichi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/elaichi/apis/elaichi-api/revisions/b22cfb7b6d15?raw)
