Skip to main content

Access Request API

Manage access requests through the Permit Elements API from your own interface. This page is for developers who build a custom access request flow on top of Permit Elements, the embeddable UI components. A user asks for a role on a tenant, resource, or resource instance, and a reviewer approves or denies the request.

The requests on this page run as a user signed in to an element, with the session that your server-side login route creates. To call the same operations from a backend with your API key and no element user session, see Access Request API with an API key.

Prerequisites

Sign in the element user

Initialize the Permit SDK

1Server-side

Initialize one instance of the Permit SDK in your backend. The same instance serves your permission checks and Permit Elements. Pass your environment API key to the Permit constructor.

const { Permit } = require("permitio");
const permit = new Permit(
{token: permit_key_SECRET}
);

Add a server-side login route

Create a route in your backend that signs the current user in to the element with loginAs. Match the route to the authentication method your application uses, such as a bearer token or cookies.

The loginAs method takes the unique ID of the user, usually read from the user's JSON Web Token (JWT), and the key or ID of the tenant:

permit.elements.loginAs({ userId, tenantId });
The user must belong to the tenant

If the user is not a member of the tenant passed to loginAs, the login fails with the error USER_NOT_FOUND.

The session applies to one tenant. To switch a user to a different tenant, sign the user out and call loginAs again with the other tenant.

Passing the tenant is required for a server-side login.

Using CookiesServer-side

Access request endpoints

All paths start with https://api.permit.io/v2/elements/{proj_id}/{env_id}/config/{elements_config_id}. Replace <COOKIE FROM LOGIN> in the examples with the session cookie from the login route.

MethodPath suffixOperationWho calls it
POST/access_requestsCreate an access requestRequesting user
GET/access_requests/{access_request_id}Get an access requestReviewer
GET/access_requestsList access requestsReviewer, or a user for their own requests
PATCH/access_requests/{access_request_id}/reviewerUpdate the reviewer comment or roleReviewer
PUT/access_requests/{access_request_id}/approveApprove an access requestReviewer
PUT/access_requests/{access_request_id}/denyDeny an access requestReviewer
PUT/access_requests/{access_request_id}/cancelCancel an access requestRequesting user

Reviewers are users with the permission level that the element allows to manage requests, such as an admin. See Permission levels.

An access request has one of these status values: pending, approved, denied, or canceled.

Create an access request

Send a POST request to /access_requests with the details of the requested access.

FieldRequiredDescription
access_request_details.tenantYesID or key of the tenant the user requests access in
access_request_details.roleYesID or key of the requested role
access_request_details.resourceNoID or key of the resource the role applies to
access_request_details.resource_instanceNoID or key of the resource instance the role applies to
reasonNoBusiness justification from the requesting user
curl -X POST 'https://api.permit.io/v2/elements/{proj_id}/{env_id}/config/{elements_config_id}/access_requests' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-H 'origin: https://api.permit.io' \
-H 'Content-Type: application/json' \
--data-raw '{
"access_request_details": {
"tenant": "34f5c98e-f430-457b-a812-92637d0c6fd0",
"resource": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"resource_instance": "2d98d9f8-e1b7-4f1d-baad-2edbf6fa6c66",
"role": "ac4e70c8-d5be-48af-93eb-760f58fc91a9"
},
"reason": "done onboarding"
}'

The API returns the created access request:

{
"id": "b7a6cfc2-6a4e-4d0f-9d0a-3f0f1f0b6a11",
"requesting_user_id": "1c1e4ada-f282-40e6-b3b7-20b3a51c93b5",
"access_request_details": {
"tenant": "34f5c98e-f430-457b-a812-92637d0c6fd0",
"resource": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"resource_instance": "2d98d9f8-e1b7-4f1d-baad-2edbf6fa6c66",
"role": "ac4e70c8-d5be-48af-93eb-760f58fc91a9"
},
"reason": "done onboarding",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
"environment_id": "40ef0e48-a11f-4963-a229-e396c9f7e7c4",
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "access_request",
"status": "pending",
"reviewer_user_id": null,
"reviewed_at": null,
"reviewer_comment": null
}

The response includes the request's id, which you pass as {access_request_id} in the other calls.

Tenant membership

The user who creates the access request must be a member of the tenant that the request is for.

Reviewer actions

Get an access request

Send a GET request to /access_requests/{access_request_id}.

curl 'https://api.permit.io/v2/elements/{proj_id}/{env_id}/config/{elements_config_id}/access_requests/{access_request_id}' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-H 'origin: https://api.permit.io'

The API returns the access request:

{
"id": "b7a6cfc2-6a4e-4d0f-9d0a-3f0f1f0b6a11",
"requesting_user_id": "1c1e4ada-f282-40e6-b3b7-20b3a51c93b5",
"access_request_details": {
"tenant": "34f5c98e-f430-457b-a812-92637d0c6fd0",
"resource": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"resource_instance": "2d98d9f8-e1b7-4f1d-baad-2edbf6fa6c66",
"role": "ac4e70c8-d5be-48af-93eb-760f58fc91a9"
},
"reason": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
"environment_id": "40ef0e48-a11f-4963-a229-e396c9f7e7c4",
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "access_request",
"status": "approved",
"reviewer_user_id": "1b287364-14ff-4b72-8953-b40399093a6f",
"reviewed_at": "2019-08-24T14:15:22Z",
"reviewer_comment": "new employee"
}

List access requests

Send a GET request to /access_requests. Filter and paginate the list with these query parameters:

Query parameterDescription
statusOnly requests with this status: pending, approved, denied, or canceled
tenantOnly requests in this tenant
roleOnly requests for this role
resourceOnly requests for this resource
resource_instance_idFor ReBAC elements, only requests for this resource instance ID or key
pagePage number, starting at 1. Default 1.
per_pageResults per page, maximum 100. Default 30.
curl -G 'https://api.permit.io/v2/elements/{proj_id}/{env_id}/config/{elements_config_id}/access_requests' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-H 'origin: https://api.permit.io' \
--data-urlencode 'status=pending' \
--data-urlencode 'tenant=<TENANT_KEY>' \
--data-urlencode 'role=<ROLE_KEY>' \
--data-urlencode 'resource=<RESOURCE_KEY>' \
--data-urlencode 'resource_instance_id=<RESOURCE_INSTANCE_KEY>' \
--data-urlencode 'page=1' \
--data-urlencode 'per_page=30'

The API returns a page of access requests:

{
"data": [
{
"id": "b7a6cfc2-6a4e-4d0f-9d0a-3f0f1f0b6a11",
"requesting_user_id": "1c1e4ada-f282-40e6-b3b7-20b3a51c93b5",
"access_request_details": {
"tenant": "34f5c98e-f430-457b-a812-92637d0c6fd0",
"resource": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"resource_instance": "2d98d9f8-e1b7-4f1d-baad-2edbf6fa6c66",
"role": "ac4e70c8-d5be-48af-93eb-760f58fc91a9"
},
"reason": "done onboarding",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
"environment_id": "40ef0e48-a11f-4963-a229-e396c9f7e7c4",
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "access_request",
"status": "approved",
"reviewer_user_id": "1b287364-14ff-4b72-8953-b40399093a6f",
"reviewed_at": "2019-08-24T14:15:22Z",
"reviewer_comment": "new employee"
}
],
"total_count": 1,
"page_count": 1
}
Visibility for non-reviewers

Users who are not reviewers see only their own access requests in the list.

Update the reviewer comment or role

Send a PATCH request to /access_requests/{access_request_id}/reviewer. Both body fields are optional:

FieldDescription
reviewer_commentComment from the reviewer
roleID or key of the role for the access request
curl -X PATCH 'https://api.permit.io/v2/elements/{proj_id}/{env_id}/config/{elements_config_id}/access_requests/{access_request_id}/reviewer' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-H 'origin: https://api.permit.io' \
-H 'Content-Type: application/json' \
--data-raw '{
"reviewer_comment": "new employee",
"role": "ac4e70c8-d5be-48af-93eb-760f58fc91a9"
}'

The API returns the updated access request:

{
"id": "b7a6cfc2-6a4e-4d0f-9d0a-3f0f1f0b6a11",
"requesting_user_id": "1c1e4ada-f282-40e6-b3b7-20b3a51c93b5",
"access_request_details": {
"tenant": "34f5c98e-f430-457b-a812-92637d0c6fd0",
"resource": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"resource_instance": "2d98d9f8-e1b7-4f1d-baad-2edbf6fa6c66",
"role": "ac4e70c8-d5be-48af-93eb-760f58fc91a9"
},
"reason": "done onboarding",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
"environment_id": "40ef0e48-a11f-4963-a229-e396c9f7e7c4",
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "access_request",
"status": "approved",
"reviewer_user_id": "1b287364-14ff-4b72-8953-b40399093a6f",
"reviewed_at": "2019-08-24T14:15:22Z",
"reviewer_comment": "new employee"
}

Approve an access request

Send a PUT request to /access_requests/{access_request_id}/approve. The body is optional and accepts reviewer_comment and role.

curl -X PUT 'https://api.permit.io/v2/elements/{proj_id}/{env_id}/config/{elements_config_id}/access_requests/{access_request_id}/approve' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-H 'origin: https://api.permit.io' \
-H 'Content-Type: application/json' \
--data-raw '{
"reviewer_comment": "new employee"
}'

The API returns the approved access request with status set to approved:

{
"id": "b7a6cfc2-6a4e-4d0f-9d0a-3f0f1f0b6a11",
"requesting_user_id": "1c1e4ada-f282-40e6-b3b7-20b3a51c93b5",
"access_request_details": {
"tenant": "34f5c98e-f430-457b-a812-92637d0c6fd0",
"resource": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"resource_instance": "2d98d9f8-e1b7-4f1d-baad-2edbf6fa6c66",
"role": "ac4e70c8-d5be-48af-93eb-760f58fc91a9"
},
"reason": "done onboarding",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
"environment_id": "40ef0e48-a11f-4963-a229-e396c9f7e7c4",
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "access_request",
"status": "approved",
"reviewer_user_id": "1b287364-14ff-4b72-8953-b40399093a6f",
"reviewed_at": "2019-08-24T14:15:22Z",
"reviewer_comment": "new employee"
}

Deny an access request

Send a PUT request to /access_requests/{access_request_id}/deny. The body is optional and accepts reviewer_comment.

curl -X PUT 'https://api.permit.io/v2/elements/{proj_id}/{env_id}/config/{elements_config_id}/access_requests/{access_request_id}/deny' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-H 'origin: https://api.permit.io' \
-H 'Content-Type: application/json' \
--data-raw '{
"reviewer_comment": "need more info"
}'

The API returns the denied access request:

{
"id": "b7a6cfc2-6a4e-4d0f-9d0a-3f0f1f0b6a11",
"requesting_user_id": "1c1e4ada-f282-40e6-b3b7-20b3a51c93b5",
"access_request_details": {
"tenant": "34f5c98e-f430-457b-a812-92637d0c6fd0",
"resource": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"resource_instance": "2d98d9f8-e1b7-4f1d-baad-2edbf6fa6c66",
"role": "ac4e70c8-d5be-48af-93eb-760f58fc91a9"
},
"reason": "done onboarding",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
"environment_id": "40ef0e48-a11f-4963-a229-e396c9f7e7c4",
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "access_request",
"status": "denied",
"reviewer_user_id": "1b287364-14ff-4b72-8953-b40399093a6f",
"reviewed_at": "2019-08-24T14:15:22Z",
"reviewer_comment": "need more info"
}

Requesting user actions

Cancel an access request

Send a PUT request to /access_requests/{access_request_id}/cancel. The request has no body.

curl -X PUT 'https://api.permit.io/v2/elements/{proj_id}/{env_id}/config/{elements_config_id}/access_requests/{access_request_id}/cancel' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-H 'origin: https://api.permit.io'

The API returns the canceled access request:

{
"id": "b7a6cfc2-6a4e-4d0f-9d0a-3f0f1f0b6a11",
"requesting_user_id": "1c1e4ada-f282-40e6-b3b7-20b3a51c93b5",
"access_request_details": {
"tenant": "34f5c98e-f430-457b-a812-92637d0c6fd0",
"resource": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"resource_instance": "2d98d9f8-e1b7-4f1d-baad-2edbf6fa6c66",
"role": "ac4e70c8-d5be-48af-93eb-760f58fc91a9"
},
"reason": "done onboarding",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
"environment_id": "40ef0e48-a11f-4963-a229-e396c9f7e7c4",
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "access_request",
"status": "canceled",
"reviewer_user_id": null,
"reviewed_at": null,
"reviewer_comment": null
}