---
title: "Deny an access request"
method: POST
path: "/api/v1/access_requests/{access_request_id}/deny"
tags: ["access_requests"]
---

# Deny an access request

`POST /api/v1/access_requests/{access_request_id}/deny`

## Request

- Base URL: `https://app.accessowl.io`
- URL: `https://app.accessowl.io/api/v1/access_requests/{access_request_id}/deny`
- Auth: HTTP bearer

Denies an access request that is still in approval, with a required reason. The token user is usually not an assigned approver, so the caller names the approver to deny on behalf of via `on_behalf_of_user_id`; the acting token user is then persisted as the deputy (replacement). Omit it only when the acting user is themselves a current approver. A single denial terminates the request; an already-closed request returns a validation error.

## Path parameters

- `access_request_id` string, uuid, required

## Headers

- `Idempotency-Key` string

## Request body

- DenyAccessRequest: Request body for denying an access request
  - `on_behalf_of_user_id` string, uuid: The approver (user) to deny on behalf of, recording the acting token user as deputy. Required unless the acting user is themselves a current approver.
  - `reason` string, required: Reason for denying the request

## Response `200`

Access request denied

- AccessRequest: An access request
  - `application_id` string, uuid, required: Application ID
  - `approval_steps` ApprovalStep[]: The ordered approval steps with their approvers and decisions. Empty for auto-approved requests.
    - `approvers` ApprovalStepApprover[], required: The approvers resolved for this step
      - `decided_at` string, date-time, nullable: When this approver approved or denied; null while pending or skipped
      - `decided_by_user_id` string, uuid, nullable: User ID of the person who recorded the decision — the approver themselves, or the user who approved or denied on their behalf; null while the approver hasn't decided
      - `status` 'pending' | 'approved' | 'denied' | 'skipped', required: Whether this approver approved, denied, is still pending, or was skipped (the step or request was decided without them)
      - `user_id` string, uuid, required: User ID of the approver
    - `decided_at` string, date-time, nullable: When the step was decided; null while pending or skipped
    - `status` 'pending' | 'approved' | 'denied' | 'skipped', required: State of the step: pending (current or upcoming), approved, denied, or skipped (a prior step's denial ended the request)
    - `step` integer, required: 1-based position of the step
    - `strategy` 'first_to_respond' | 'all', required: How many approvers must approve the step: any single one (first_to_respond) or every one (all)
  - `duration` string, nullable: Duration of time-based access as an ISO 8601 duration (e.g. "PT1H", "P7D"); null for permanent access
  - `expires_at` string, date-time, nullable: When the time-based access expires; null for permanent access or a time-based request that has not been granted yet
  - `grantee_user_id` string, uuid: User ID of the grantee
  - `id` string, uuid, required: Access request ID
  - `inserted_at` string, date-time: Creation timestamp
  - `permission_ids` string[], required: Requested permission IDs
  - `provisioning_type` 'application_admin' | 'automatic', nullable: Provisioning type
  - `request_reason` string, required: Request reason
  - `requestor_user_id` string, uuid: User ID of the requestor
  - `resource_id` string, uuid, required: Resource ID
  - `status` 'pending_approval' | 'pending_permissions_assignment' | 'access_granted' | 'denied' | 'rejected' | 'processing_access' | 'scheduled' | 'pending_dependency', required: Current status of the access request
  - `termination_reason` string, nullable: Reason the request was ended: the denial reason when denied, the provisioner's rejection reason when rejected; null otherwise. The status field says which kind it was.

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden: the caller lacks the deny permission; being an approver of the request is not enough
- `404`: Not found
- `409`: Conflict
- `422`: Validation error
- `429`: Too many requests

## Changes

- **2026-10-31** `5a1f071e40d8`: 2 breaking, 4 warning, 3 info
  - response property `errors/additionalProperties/items/` list-of-types was widened by adding types `object` to media type `application/json` of response `422`
  - removed the required property `message` from the response with the `401` status
  - removed the optional property `errors` from the response with the `401` status
  - removed the optional property `errors` from the response with the `403` status
  - …5 more
- **2026-09-22** `1dba1160cea4`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/accessowl/apis/accessowl-api/changes/api/v1/access_requests/:access_request_id/deny/post.md)

---

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