Reviews
A ReviewItem is one trace held for human review under EU AI Act
Article 14 oversight. The Policy Engine routes flagged decisions
into the review queue (HTTP 202); a reviewer with the admin or
owner role approves or rejects, and the verdict is recorded back
on the source DecisionTrace. Tested against API version v1. JWT
auth on every endpoint plus workspace-access validation.
The endpoint URL is /api/v1/review-queue (the resource is named
"Review Queue" in product). This page documents the same resource
under the shorter "Reviews" name on the sidebar; the URLs themselves
are unchanged.
The ReviewItem object
| Field | Type | Required | Description |
|---|---|---|---|
_id / id | string | yes | MongoDB ObjectId |
traceId | string | yes | The DecisionTrace this review is for |
agentId | string | no | The Agent document reference; populated to { name } on list |
agentIdStr | string | no | Fallback string identifier when agentId is absent |
action | string | yes | The proposed agent action (e.g., initiate_refund) |
confidence | number | yes | The Confidence Engine score at trace time |
priority | enum | no | critical, high, medium (default), low |
status | enum | no | pending (default), approved, rejected |
workflowStep | number | no | Current step in the review workflow; default 1 |
assignedTo | string | no | User ObjectId of the reviewer |
escalatedAt | string (ISO 8601) | no | Set when escalation fires |
escalatedTo | string | no | User ObjectId the item was escalated to |
escalationReason | string | no | Free-text rationale |
slaDeadline | string (ISO 8601) | no | Hard deadline used by the Multi-Clock Hub when applicable |
context | object | no | The matching trace context, PII-scrubbed on output |
payload | object | no | The trace payload, PII-scrubbed on output |
decision | enum | no | approve or reject; set on resolution |
reason | string | no | Reviewer-provided rationale, max 1,000 chars |
notes | string | no | Reviewer-provided free-form notes, max 2,000 chars |
organizationId / workspaceId | string | yes | Tenancy scope; chains never mix across tenants |
createdAt / updatedAt | string (ISO 8601) | no | Standard timestamps |
Endpoints
GET /api/v1/review-queue
POST /api/v1/review-queue/:id/decision
POST /api/v1/review-queue/bulk-decision
PATCH /api/v1/review-queue/:id/assign
POST /api/v1/review-queue/:id/escalate
GET, assign, and escalate are available to any authenticated
member of the workspace. decision and bulk-decision require the
admin or owner role.
List the queue
GET /api/v1/review-queue
| Query parameter | Description |
|---|---|
status | Filter to pending / approved / rejected; absent returns every status |
Workspace scope comes from the x-workspace-id header (resolved by
validateWorkspaceAccess). Sort order is most-recent-first
(createdAt DESC). The server hard-caps at 500 items; consumers
should respect the truncated flag on the response and refine the
filter rather than paging through.
curl "https://api.adjudon.com/api/v1/review-queue?status=pending" \
-H "Authorization: Bearer $ADJUDON_API_KEY"
import os, requests
r = requests.get(
"https://api.adjudon.com/api/v1/review-queue",
params={"status": "pending"},
headers={"Authorization": f"Bearer {os.environ['ADJUDON_API_KEY']}"},
)
data = r.json()["data"]
Response (200 OK):
{
"success": true,
"data": [/* ReviewItem[] (PII-scrubbed) */],
"count": 42,
"total": 42,
"limit": 500,
"truncated": false
}
payload and context are PII-scrubbed before transport (email,
IBAN, credit-card, SSN, phone). Errors: 401, 403 (workspace
access), 500 INTERNAL_ERROR.
Make a decision
POST /api/v1/review-queue/:id/decision
| Body field | Required | Description |
|---|---|---|
decision | yes | approve or reject |
reason | no | Reviewer rationale, max 1,000 characters |
notes | no | Free-form notes, max 2,000 characters |
curl -X POST https://api.adjudon.com/api/v1/review-queue/65b1f2c4/decision \
-H "Authorization: Bearer $ADJUDON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "decision": "approve", "reason": "Risk acceptable per Q3 policy" }'
The decision is final — once an item is approved or
rejected, the same endpoint returns 400 INVALID_OPERATION. To
revisit a finished review, escalate or open a new trace.
Errors: 400 VALIDATION_ERROR, 400 INVALID_OPERATION (already
decided), 401, 403 (role), 404 NOT_FOUND, 500.
Bulk decision
POST /api/v1/review-queue/bulk-decision
| Body field | Required | Description |
|---|---|---|
ids | yes | Array of ReviewItem ObjectIds; 1 to 100 items |
decision | yes | approve or reject (applied to all) |
reason | no | Shared rationale, max 1,000 characters |
The bulk endpoint applies the same verdict to every still-pending
item in the array. Items that have already been decided are
silently skipped; if no pending items match the supplied ids the
server returns 404 NOT_FOUND.
curl -X POST https://api.adjudon.com/api/v1/review-queue/bulk-decision \
-H "Authorization: Bearer $ADJUDON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": ["65b1f2c4", "65b1f2c5", "65b1f2c6"],
"decision": "approve",
"reason": "End-of-quarter cleanup"
}'
Errors: 400 VALIDATION_ERROR (empty ids, >100 ids, invalid
decision), 401, 403, 404, 500.
Assign a reviewer
PATCH /api/v1/review-queue/:id/assign
| Body field | Required | Description |
|---|---|---|
assignedTo | no | User ObjectId; omit to clear the assignment |
Errors: 400 VALIDATION_ERROR, 401, 404, 500.
Escalate an item
POST /api/v1/review-queue/:id/escalate
| Body field | Required | Description |
|---|---|---|
reason | no | Free-text rationale, max 1,000 characters |
escalateTo | no | User ObjectId; if omitted, the workspace's escalation policy decides |
Sets escalatedAt, escalatedTo, and escalationReason on the
item. The item stays pending — escalation moves the
reviewer, not the verdict. Errors: 400, 401, 404, 500.
Common gotchas
- URL is
/review-queue, not/reviews. The page is named "Reviews" on the sidebar but the live endpoint is mounted at/api/v1/review-queue. Cross-links inside the docs use the page slug/api-reference/reviews; the API call uses/review-queue. - Decisions are final. A second decision on the same item
returns
400 INVALID_OPERATION. The audit log retains the original verdict regardless. - Idempotency. The Idempotency-Key middleware is wired only on
POST /traces;POST /decisionandPOST /bulk-decisionare mutating but do not auto-receive idempotency keys today. A retried decision on the same id is harmless because the second attempt fails withINVALID_OPERATION; a retried bulk-decision with overlapping ids is the same. - Hard cap of 500. The list endpoint returns at most 500 items
per request and signals truncation via the
truncatedflag. Filter bystatusto keep the working set well below the cap.
See also
- Policies & Human Review — the concept page covering Article 14 oversight semantics
- Policies API — what fires items
into this queue (
flag_for_reviewaction) - Traces API — the underlying decision the review item references
- Notifications API — how reviewers get pinged on assignment / SLA risk
- Error Codes — the full error taxonomy