---
title: "Get an access request"
method: GET
path: "/access-request/{id}"
tags: ["Access requests"]
---

# Get an access request

`GET /access-request/{id}`

## Request

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

Returns one access request. What the caller sees depends on who they are: an admin (`member:manage`) sees any request as the admin view, the request’s own requester sees it as the self view, and anyone else gets `404`, because a request’s existence is not for a bystander to learn.

## Path parameters

- `id` string, required

## Headers

- `X-Organization-Id` string

## Response `200`

OK

- union: Self view for the requester; admin view (`member:manage`) otherwise.
  - 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`.
  - 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.

## 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)
