Skip to main content

Operation Approval API

Require approval before a user performs a sensitive operation, and manage those approvals through the Permit Elements API. This page is for developers who build a custom approval flow on top of Permit Elements, the embeddable UI components. A user requests approval for an operation on a resource, 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. If you already added a login route for the Access Request API, skip to Operation approval endpoints.

Related resources

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

Operation approval 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/operation_approvalCreate an operation approvalRequesting user
GET/operation_approval/{operation_approval_id}Get an operation approvalReviewer
GET/operation_approvalList operation approvalsReviewer, or a user for their own approvals
PATCH/operation_approval/{operation_approval_id}/reviewerUpdate the reviewer commentReviewer
PUT/operation_approval/{operation_approval_id}/approveApprove an operation approvalReviewer
PUT/operation_approval/{operation_approval_id}/denyDeny an operation approvalReviewer
PUT/operation_approval/{operation_approval_id}/cancelCancel an operation approvalRequesting user

An operation approval has one of these status values: pending, approved, denied, or canceled.

Create an operation approval

Send a POST request to /operation_approval with the details of the operation.

FieldRequiredDescription
access_request_details.tenantYesID or key of the tenant the operation runs in
access_request_details.resourceYesID or key of the resource the operation applies to
access_request_details.resource_instanceNoID or key of the resource instance the operation 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}/operation_approval' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-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"
},
"reason": "I need to make transfer for my client"
}'

The API returns the created operation approval, with type set to operation_approval:

{
"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"
},
"reason": "I need to make transfer for my client",
"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",
"status": "pending",
"reviewer_user_id": null,
"reviewed_at": null,
"reviewer_comment": null,
"type": "operation_approval"
}

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

Reviewer actions

Get an operation approval

Send a GET request to /operation_approval/{operation_approval_id}.

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

The API returns the operation approval:

{
"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"
},
"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",
"status": "approved",
"reviewer_user_id": "1b287364-14ff-4b72-8953-b40399093a6f",
"reviewed_at": "2019-08-24T14:15:22Z",
"reviewer_comment": "transfer for a new client",
"type": "operation_approval"
}

List operation approvals

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

Query parameterDescription
statusOnly approvals with this status: pending, approved, denied, or canceled
resourceOnly approvals for this resource
resource_instanceOnly approvals for this resource instance
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}/operation_approval' \
-H 'cookie: <COOKIE FROM LOGIN>' \
--data-urlencode 'status=pending' \
--data-urlencode 'resource=<RESOURCE_KEY>' \
--data-urlencode 'resource_instance=<RESOURCE_INSTANCE_KEY>' \
--data-urlencode 'page=1' \
--data-urlencode 'per_page=30'

The API returns a page of operation approvals. Each item also includes the requesting user's email, first name, and last name, and the resource and resource instance keys:

{
"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"
},
"reason": "I need to make transfer for my client",
"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",
"status": "approved",
"reviewer_user_id": "1b287364-14ff-4b72-8953-b40399093a6f",
"reviewed_at": "2019-08-24T14:15:22Z",
"reviewer_comment": "transfer for a new client",
"type": "operation_approval",
"requesting_user_email": "john@permit.io",
"requesting_user_first_name": "John",
"requesting_user_last_name": "Doe",
"resource_key": "transfer",
"resource_instance_key": "transfer-1"
}
],
"total_count": 1,
"page_count": 1
}
Visibility for non-reviewers

Users who are not reviewers see only their own operation approvals in the list.

Update the reviewer comment

Send a PATCH request to /operation_approval/{operation_approval_id}/reviewer. The body is optional and accepts reviewer_comment.

curl -X PATCH \
'https://api.permit.io/v2/elements/{proj_id}/{env_id}/config/{elements_config_id}/operation_approval/{operation_approval_id}/reviewer' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-H 'Content-Type: application/json' \
--data-raw '{
"reviewer_comment": "transfer for a new client"
}'

The API returns the updated operation approval:

{
"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"
},
"reason": "I need to make transfer for my client",
"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",
"status": "approved",
"reviewer_user_id": "1b287364-14ff-4b72-8953-b40399093a6f",
"reviewed_at": "2019-08-24T14:15:22Z",
"reviewer_comment": "transfer for a new client",
"type": "operation_approval"
}

Approve an operation approval

Send a PUT request to /operation_approval/{operation_approval_id}/approve. 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}/operation_approval/{operation_approval_id}/approve' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-H 'Content-Type: application/json' \
--data-raw '{
"reviewer_comment": "transfer for a new client"
}'

The API returns the approved operation approval 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"
},
"reason": "I need to make transfer for my client",
"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",
"status": "approved",
"reviewer_user_id": "1b287364-14ff-4b72-8953-b40399093a6f",
"reviewed_at": "2019-08-24T14:15:22Z",
"reviewer_comment": "transfer for a new client",
"type": "operation_approval"
}

Deny an operation approval

Send a PUT request to /operation_approval/{operation_approval_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}/operation_approval/{operation_approval_id}/deny' \
-H 'cookie: <COOKIE FROM LOGIN>' \
-H 'Content-Type: application/json' \
--data-raw '{
"reviewer_comment": "need more info"
}'

The API returns the denied operation approval:

{
"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"
},
"reason": "I need to make transfer for my client",
"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",
"status": "denied",
"reviewer_user_id": "1b287364-14ff-4b72-8953-b40399093a6f",
"reviewed_at": "2019-08-24T14:15:22Z",
"reviewer_comment": "need more info",
"type": "operation_approval"
}

Requesting user actions

Cancel an operation approval

Send a PUT request to /operation_approval/{operation_approval_id}/cancel. The request has no body.

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

The API returns the canceled operation approval:

{
"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"
},
"reason": "I need to make transfer for my client",
"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",
"status": "canceled",
"reviewer_user_id": null,
"reviewed_at": null,
"reviewer_comment": null,
"type": "operation_approval"
}