Skip to content
Hexel StudioDocs

Access reviews

Record periodic reviews of who has access, with a decision per item. Records only for now.

On this page

What works today

  • Reviews, items and schedules are stored in your organization.
  • Each decision records who made it (reviewed_by_user_id) and when (reviewed_at).
  • Nobody can decide an item about themselves.

Use it as a log of a review you run yourself. To find what to review, list policy attachments, group members and service users and their keys.

Permissions

ActionWhat it allows
iam:review:readRead reviews, items and schedules.
iam:review:writeCreate reviews, items and schedules, change a review's status and delete schedules.
iam:review:manageDecide items.

Reviews

FieldTypeDescription
review_typestringUSER_ACCESS, ROLE_MEMBERS, WORKSPACE or FULL_ORG.
scope_type, scope_idstringOptional. What the review covers, for example a workspace. Stored only.
reviewer_user_idstringThe person expected to do the review. Stored only.
due_datestringTimestamp the review is due.

The response adds id (ar_...), organization_id, status (starts as PENDING), completed_at, created_at and updated_at.

Bash
curl -X POST https://api.hexelstudio.com/v1/reviews \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "review_type": "USER_ACCESS",
    "reviewer_user_id": "<user-id>",
    "due_date": "2026-11-30T00:00:00Z"
  }'
JSON
{
  "id": "ar_...",
  "organization_id": "<org-id>",
  "review_type": "USER_ACCESS",
  "status": "PENDING",
  "reviewer_user_id": "<user-id>",
  "due_date": "2026-11-30T00:00:00Z",
  "created_at": "2026-10-20T09:00:00Z",
  "updated_at": "2026-10-20T09:00:00Z"
}
CallPermissionResponse
POST /v1/reviewsiam:review:write201 with the review
GET /v1/reviewsiam:review:readArray of your organization's reviews, earliest due first. Filter with ?status=.
GET /v1/reviews/{review_id}iam:review:readThe review, or 404
PATCH /v1/reviews/{review_id}/statusiam:review:write{"status": "..."}

Change a review's status

Send {"status": "..."} with PENDING, IN_PROGRESS, COMPLETED or CANCELLED. Any status can follow any other. COMPLETED also sets completed_at. Another value answers 400.

Bash
curl -X PATCH https://api.hexelstudio.com/v1/reviews/<review-id>/status \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "COMPLETED"}'

Items

An item is one piece of access to review, such as "this member has this policy".

FieldTypeDescription
subject_typestringWho has the access, for example USER or SERVICE_USER.
subject_idstringID of that member or service user. They cannot decide this item.
access_typestringKind of access, for example POLICY or GROUP.
access_valuestringThe access itself, for example a policy or group ID.

These fields are stored as given and not checked against your organization.

Bash
curl -X POST https://api.hexelstudio.com/v1/reviews/<review-id>/items \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "subject_type": "USER",
    "subject_id": "<user-id>",
    "access_type": "POLICY",
    "access_value": "<policy-id>"
  }'

The response is 201 Created with the item: id (ari_...), review_id, the four fields above, current_status (PENDING) and created_at.

CallPermissionResponse
POST /v1/reviews/{review_id}/itemsiam:review:write201 with the item
GET /v1/reviews/{review_id}/itemsiam:review:readArray of the review's items
PATCH /v1/reviews/{review_id}/items/{item_id}iam:review:manageThe decided item

Decide an item

FieldTypeDescription
decisionstringRequired. APPROVE, REVOKE or FLAG.
commentstringOptional.
Bash
curl -X PATCH https://api.hexelstudio.com/v1/reviews/<review-id>/items/<item-id> \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"decision": "REVOKE", "comment": "No longer on the team"}'
JSON
{
  "id": "ari_...",
  "review_id": "<review-id>",
  "subject_type": "USER",
  "subject_id": "<user-id>",
  "access_type": "POLICY",
  "access_value": "<policy-id>",
  "current_status": "REVOKED",
  "reviewer_decision": "REVOKE",
  "reviewer_comment": "No longer on the team",
  "reviewed_by_user_id": "<your-user-id>",
  "reviewed_at": "2026-10-20T09:10:00Z",
  "created_at": "2026-10-20T09:00:00Z",
  "decision": "REVOKE"
}

current_status becomes APPROVED, REVOKED or FLAGGED. decision repeats reviewer_decision. A later decision replaces an earlier one.

StatusWhen
400decision is not APPROVE, REVOKE or FLAG.
403You are the item's subject (the subject of a review item cannot decide it), or you lack iam:review:manage.
404No such review in your organization, or no such item in the review.

Schedules

A schedule describes a recurring review. Schedules are stored but nothing runs them.

FieldTypeDescription
review_typestringUSER_ACCESS, ROLE_MEMBERS, WORKSPACE or FULL_ORG.
frequency_daysintegerHow often the review should happen.
scope_type, scope_idstringOptional.
reviewer_user_idstringThe person expected to do the review.
next_review_datestringTimestamp of the next review.
is_enabledbooleanDefault true.

The response adds id (ars_...), organization_id, last_review_date, created_at and updated_at.

Bash
curl -X POST https://api.hexelstudio.com/v1/reviews/schedules \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "review_type": "FULL_ORG",
    "frequency_days": 90,
    "reviewer_user_id": "<user-id>",
    "next_review_date": "2027-01-15T00:00:00Z"
  }'
CallPermissionResponse
POST /v1/reviews/schedulesiam:review:write201 with the schedule
GET /v1/reviews/schedulesiam:review:readArray of your organization's schedules
DELETE /v1/reviews/schedules/{schedule_id}iam:review:write204, or 404

There is no endpoint to update a schedule. Delete it and create a new one.