---
title: "List viewer campaign items"
method: GET
path: "/campaigns/{campaign_id}/viewer-items"
tags: ["campaigns"]
---

# List viewer campaign items

`GET /campaigns/{campaign_id}/viewer-items`

## Request

- Base URL: `https://api.opal.dev/v1`
- URL: `https://api.opal.dev/v1/campaigns/{campaign_id}/viewer-items`
- Auth: HTTP bearer

Returns a paginated list of campaign review items assigned to the
current authenticated viewer. Matches GraphQL `Campaign.viewerItems`.

Campaign access matches `GET /campaigns/{campaign_id}` and GraphQL
`campaign(id)`: the caller must have access-review read permission or
be a reviewer on the campaign. Otherwise the request fails with 403
(same as get-by-id). Item rows are still scoped to the caller's own
reviews (empty page when the caller is an admin but not a reviewer).

## Path parameters

- `campaign_id` string, uuid, required

## Query parameters

- `cursor` string
- `page_size` integer
- `sort_field` 'PRINCIPAL_NAME' | 'ENTITY_NAME' | 'EXPIRATION' | 'LAST_USED': Sort field for viewer campaign items.
- `sort_direction` 'ASC' | 'DESC': Sort direction for viewer campaign items.
- `statuses` ViewerCampaignItemStatusEnum[]
- `access_level_names` string[]
- `principal_ids` string[]
- `entity_ids` string[]
- `item_ids` string[]
- `ai_bucket_id` string, uuid

## Response `200`

A page of viewer campaign items.

- PaginatedViewerCampaignItemsList: A paginated list of viewer campaign items.
  - `next` string, nullable: The cursor with which to continue pagination if additional result pages exist.
  - `previous` string, nullable: The cursor used to obtain the current result page.
  - `results` ViewerCampaignItem[], required
    - `campaign_item_review_id` string, uuid, required: The ID of the campaign item review.
    - `decision` 'APPROVED' | 'REVOKED' | 'CHANGE_ROLE' | 'REDUCE_EXPIRATION' | 'ADMIN_REVOKED' | 'NO_ACTION' | 'REASSIGNED': Decision recorded on a campaign item review row.
    - `note` string, nullable: Optional note from the reviewer.
    - `decided_at` string, date-time, nullable: When the decision was finalized.
    - `pending_decision` 'APPROVED' | 'REVOKED' | 'CHANGE_ROLE' | 'REDUCE_EXPIRATION' | 'ADMIN_REVOKED' | 'NO_ACTION' | 'REASSIGNED': Decision recorded on a campaign item review row.
    - `pending_note` string, nullable: Pending note attached to the reviewer's pending decision.
    - `updated_access_level_remote_id` string, nullable: Target access level remote ID when decision is CHANGE_ROLE.
    - `pending_updated_access_level_remote_id` string, nullable: Pending target access level remote ID when decision is CHANGE_ROLE.
    - `updated_duration_in_minutes` integer, nullable: Built-in duration in minutes when decision is REDUCE_EXPIRATION.
    - `pending_updated_duration_in_minutes` integer, nullable: Staged built-in duration in minutes when the pending decision is REDUCE_EXPIRATION.
    - `reassigned_to_reviewer_ids` string[]: User IDs this review was reassigned to.
    - `principal_id` string, uuid, required: Principal ID from the role assignment.
    - `principal_type` 'GROUP' | 'RESOURCE' | 'USER', required: The type of an entity.
    - `entity_id` string, uuid, required: Entity ID from the role assignment.
    - `entity_type` 'GROUP' | 'RESOURCE' | 'USER', required: The type of an entity.
    - `access_level_name` string, nullable: Denormalized access level name.
    - `access_level_remote_id` string, nullable: Access level remote ID from the role assignment.
    - `granted_at` string, date-time, required: When the access was originally granted.
    - `expires_at` string, date-time, nullable: When the access expires, if set.
    - `role_assignment_id` string, uuid, required: ID of the underlying role assignment.
  - `total_count` integer, required: Total number of items matching the filter (across all pages).

## Changes

- **2026-10-06** `c0ce333f6196`: 2 warning, 3 info
  - added the new `REDUCE_EXPIRATION` enum value to the `results/items/decision/allOf[#/components/schemas/ViewerCampaignItemReviewDecisionEnum]/` response property for the response status `200`
  - added the new `REDUCE_EXPIRATION` enum value to the `results/items/pending_decision/allOf[#/components/schemas/ViewerCampaignItemReviewDecisionEnum]/` response property for the response status `200`
  - added the enum value `REDUCE_EXPIRATION` to the property `items/` of the `query` request parameter `statuses`
  - added the optional property `results/items/pending_updated_duration_in_minutes` to the response with the `200` status
  - …1 more
- **2026-09-12** `a55de6550df3`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/opal/apis/opal-api/changes/campaigns/:campaign_id/viewer-items/get.md)

---

[API](https://skmtc.dev/opal/apis/opal-api.md) - [All operations](https://skmtc.dev/opal/apis/opal-api/llms.txt) - [OpenAPI document](https://skmtc.dev/opal/apis/opal-api/revisions/e7877ea96eab?raw)
