Skip to content

Access Reviews

Access Reviews let administrators periodically audit every user’s role assignment within a partner or organisation scope. When a review is created, the system automatically snapshots all current user-role mappings into individual review items. A designated reviewer works through each item, deciding whether to approve or revoke the assignment. Completing the review applies all revocation decisions in a single atomic transaction, removing the affected users from the scope.

All access review operations are recorded in the audit log under the access_review.* action namespace.


Scope and Permissions

Access reviews are scoped to either a partner (MSP) or an organisation (customer). The scope is determined automatically from the authenticated user’s context.

ScopeUsers included in the review
PartnerAll users in the partner_users table for that partner
OrganisationAll users in the organization_users table for that organisation

Required Permissions

OperationPermission
List reviews, view review detailsusers:read
Create reviews, update item decisions, complete reviewsusers:write

Database Schema

Access reviews are stored across two tables.

access_reviews

ColumnTypeDescription
iduuidPrimary key (auto-generated)
partner_iduuidReferences partners.id (null for org-scoped reviews)
org_iduuidReferences organizations.id (null for partner-scoped reviews)
namevarchar(255)Human-readable review name
descriptiontextOptional longer description
statusaccess_review_statusOne of pending, in_progress, completed
reviewer_iduuidReferences users.id — the assigned reviewer
due_datetimestampOptional deadline
created_attimestampRow creation time
updated_attimestampLast modification time
completed_attimestampSet when the review is completed

access_review_items

ColumnTypeDescription
iduuidPrimary key (auto-generated)
review_iduuidReferences access_reviews.id (cascade delete)
user_iduuidReferences users.id — the user under review
role_iduuidReferences roles.id — the role assigned to the user
decisionaccess_review_decisionOne of pending, approved, revoked
notestextOptional reviewer notes
reviewed_attimestampWhen the decision was made
reviewed_byuuidReferences users.id — who made the decision
created_attimestampRow creation time

Status Enums

-- Review-level status
CREATE TYPE access_review_status AS ENUM ('pending', 'in_progress', 'completed');
-- Item-level decision
CREATE TYPE access_review_decision AS ENUM ('pending', 'approved', 'revoked');

Creating an Access Review

When you create a review, the API automatically enumerates every user-role mapping in scope and inserts one access_review_items row for each. All items start with a pending decision.

  1. Send a POST /access-reviews request with a name (required), optional description, optional due date, and optional reviewer ID.
  2. The API looks up all users in the caller’s scope (partner_users or organization_users).
  3. One review item is created per user-role mapping.
  4. The response includes the review ID, name, status (pending), and the number of items generated.

Request Body

{
"name": "Q1 2026 Quarterly Review",
"description": "Audit all technician access before renewal",
"dueDate": "2026-03-31T23:59:59Z",
"reviewerId": "d4f5a6b7-c8d9-4e0f-a1b2-c3d4e5f6a7b8"
}
FieldTypeRequiredDescription
namestringYes1—255 characters
descriptionstringNoFree-text description
dueDatestring (ISO 8601)NoReview deadline
reviewerIdstring (UUID)NoDefaults to the authenticated user

Response (201)

{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Q1 2026 Quarterly Review",
"status": "pending",
"itemCount": 12
}

Review Workflow

A review moves through three statuses during its lifecycle:

pending --> in_progress --> completed
StatusMeaning
pendingThe review has been created but no decisions have been recorded yet.
in_progressAt least one item decision has been updated. Automatically set when the first item is reviewed.
completedAll items have been decided and the review has been finalised. Revocations have been applied.

Reviewing Role Assignments

Listing Reviews

Retrieve all reviews in the current scope:

Terminal window
curl -H "Authorization: Bearer $TOKEN" \
https://breeze.yourdomain.com/api/v1/access-reviews

Response (200)

{
"data": [
{
"id": "a1b2c3d4-...",
"name": "Q1 2026 Quarterly Review",
"description": null,
"status": "in_progress",
"reviewerId": "d4f5a6b7-...",
"reviewerName": "Jane Admin",
"dueDate": "2026-03-31T23:59:59.000Z",
"createdAt": "2026-01-15T10:00:00.000Z",
"completedAt": null
}
]
}

Reviews are ordered by createdAt ascending.

Viewing a Review with Items

Fetch a single review along with all of its items, including user details, role names, and the permissions granted by each role:

Terminal window
curl -H "Authorization: Bearer $TOKEN" \
https://breeze.yourdomain.com/api/v1/access-reviews/:id

Response (200)

{
"id": "a1b2c3d4-...",
"name": "Q1 2026 Quarterly Review",
"description": null,
"status": "in_progress",
"reviewerId": "d4f5a6b7-...",
"dueDate": "2026-03-31T23:59:59.000Z",
"createdAt": "2026-01-15T10:00:00.000Z",
"completedAt": null,
"items": [
{
"id": "item-uuid-...",
"userId": "user-uuid-...",
"userName": "Bob Technician",
"userEmail": "[email protected]",
"lastActiveAt": "2026-02-10T14:30:00.000Z",
"roleId": "role-uuid-...",
"roleName": "Technician",
"decision": "pending",
"notes": null,
"reviewedAt": null,
"permissions": [
"devices:read",
"devices:write",
"scripts:read"
]
}
]
}

Each item includes:

FieldDescription
userName / userEmailIdentity of the user under review
lastActiveAtThe user’s last login timestamp — useful for identifying stale accounts
roleNameThe display name of the assigned role
permissionsArray of resource:action strings granted by the role
decisionCurrent decision: pending, approved, or revoked
notesReviewer comments (if any)
reviewedAtTimestamp when the decision was recorded

Updating an Item Decision

Record an approve or revoke decision on a single review item:

Terminal window
curl -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"decision": "approved", "notes": "Access confirmed for project work"}' \
https://breeze.yourdomain.com/api/v1/access-reviews/:id/items/:itemId
FieldTypeRequiredDescription
decisionstringYesOne of approved, revoked, or pending
notesstringNoFree-text reviewer notes

Response (200)

{
"id": "item-uuid-...",
"decision": "approved",
"notes": "Access confirmed for project work",
"reviewedAt": "2026-02-18T09:15:00.000Z"
}

The API records the authenticated user as reviewedBy and sets reviewedAt to the current time. If the parent review was in pending status, it is automatically transitioned to in_progress.


Completing a Review

Once every item has been decided (no items remain in pending), the review can be completed.

  1. Ensure all items have a decision of approved or revoked.
  2. Send a POST /access-reviews/:id/complete request.
  3. The API verifies there are no pending items.
  4. All revoked users are removed from the scope (partner_users or organization_users) in a single database transaction.
  5. The review status is set to completed and completedAt is recorded.
Terminal window
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
https://breeze.yourdomain.com/api/v1/access-reviews/:id/complete

Response (200)

{
"id": "a1b2c3d4-...",
"status": "completed",
"completedAt": "2026-02-18T12:00:00.000Z",
"revokedCount": 3
}

Completion Guards

The API enforces the following rules before allowing completion:

ConditionHTTP StatusError Message
Review not found404Access review not found
Review already completed400Review is already completed
Pending items remain400Cannot complete review with pending items

Review History

Completed reviews and their items remain in the database indefinitely, providing a full audit trail. List all reviews to see their status and completion timestamps:

Terminal window
curl -H "Authorization: Bearer $TOKEN" \
https://breeze.yourdomain.com/api/v1/access-reviews

Filter completed reviews by checking the status field in the response. Each completed review retains the full set of items with their recorded decisions, notes, reviewer identity (reviewedBy), and timestamps.

Audit Log Events

All mutating operations generate audit log entries:

ActionTrigger
access_review.createA new review is created. Details include itemCount.
access_review.item.updateA decision is recorded on an item. Details include reviewId and decision.
access_review.completeA review is finalised. Details include revokedCount.

API Reference

All endpoints are mounted under /api/v1/access-reviews. Authentication via JWT bearer token or API key is required.

MethodPathDescription
GET/access-reviewsList all reviews in scope
POST/access-reviewsCreate a new review (auto-generates items)
GET/access-reviews/:idGet a review with all items, roles, and permissions
PATCH/access-reviews/:id/items/:itemIdUpdate the decision on a single item
POST/access-reviews/:id/completeFinalise the review and apply revocations

Error Responses

All endpoints may return the following common errors:

StatusMeaning
400Validation error, cannot modify completed review, or pending items remain
403Missing partner/organisation context or insufficient organisation access
404Review or review item not found
500Internal server error (e.g. transaction failure)

Troubleshooting

”Partner or organization context required” (403)

The authenticated user’s JWT does not contain a partnerId or orgId. Access reviews require a partner-scoped or organisation-scoped session. System-scoped tokens cannot create or view reviews.

”Full partner organization access required” (403)

The user is authenticated at the partner level but their accessibleOrgIds list does not cover every organisation belonging to the partner. Ensure the user has been granted access to all partner organisations before initiating a review.

”Cannot complete review with pending items” (400)

At least one review item still has a pending decision. Fetch the review detail (GET /access-reviews/:id) and look for items where decision is pending. Update each pending item to either approved or revoked before retrying completion.

”Cannot modify completed review” (400)

The review has already been finalised. Completed reviews are immutable. If access needs to be changed after completion, manage user-role assignments directly or create a new access review.

Review was created with zero items

This occurs when there are no user-role mappings in the current scope (i.e. no rows in partner_users or organization_users). The review can still be completed immediately since there are no pending items. Verify that users have been added to the partner or organisation before creating the review.