---
title: "Withdraw an access request"
method: POST
path: "/access-request/{id}/withdraw"
tags: ["Access requests"]
---

# Withdraw an access request

`POST /access-request/{id}/withdraw`

## Request

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

Withdraws an access request. Only the request’s own requester may withdraw it, and only while it is still `pending`. No body, and no permission beyond membership. Someone else’s request id is `404`; a request that already left `pending` is `409`.

## Path parameters

- `id` string, required

## Headers

- `X-Organization-Id` string

## Response `200`

Withdrawn (self view, `can_withdraw: false`)

- 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`.

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