---
title: "POST /campaigns"
method: POST
path: "/campaigns"
tags: ["campaigns"]
---

# POST /campaigns

`POST /campaigns`

Creates a campaign. Campaign scope only supports direct access edges:
`configuration.query.edgeFilter.directOnly` defaults to `true`, is
always stored as `true`, and passing `false` returns 400.

## Request body

- CreateCampaignInfo — # CreateCampaignInfo Object ### Description The `CreateCampaignInfo` object is used to create a campaign. ### Usage Example Use in the `POST Campaigns` endpoint.
  - `name` string, required — The name of the campaign.
  - `configuration` CreateCampaignConfigurationInfo, required — Configuration to apply when creating a campaign. `query` is required; other omitted fields use defaults.
    - `query` OpalAccessPathQueryBody, required — Edge-query filters for an ACCESS_PATH OpalQuery. At least one of principalFilter or entitlementFilter is required.
      - `principalFilter` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
        - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
        - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
        - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
          - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
          - `string` string, required — The string value to match against the entity name.
        - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
          - `key` string, required — The tag key to filter by.
          - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
          - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
        - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
          - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
          - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
        - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
          - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
          - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
        - `entityIDs` string[] — Filter by specific entity UUIDs.
        - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
        - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
        - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
        - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
        - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
        - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
      - `entitlementFilter` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
        - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
        - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
        - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
          - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
          - `string` string, required — The string value to match against the entity name.
        - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
          - `key` string, required — The tag key to filter by.
          - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
          - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
        - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
          - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
          - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
        - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
          - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
          - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
        - `entityIDs` string[] — Filter by specific entity UUIDs.
        - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
        - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
        - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
        - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
        - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
        - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
      - `principalAccessFilters` AccessRelationshipFilters — Filters the returned nodes by the access edges connected to them. When `isAccessibleBy` and `hasAccessTo` are provided, the returned nodes must satisfy both edge constraints simultaneously.
        - `isAccessibleBy` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
          - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
          - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
          - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
            - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
            - `string` string, required — The string value to match against the entity name.
          - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
            - `key` string, required — The tag key to filter by.
            - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
            - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
          - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
            - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
            - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
          - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
            - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
            - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
          - `entityIDs` string[] — Filter by specific entity UUIDs.
          - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
          - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
          - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
          - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
          - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
          - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
        - `hasAccessTo` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
          - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
          - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
          - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
            - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
            - `string` string, required — The string value to match against the entity name.
          - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
            - `key` string, required — The tag key to filter by.
            - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
            - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
          - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
            - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
            - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
          - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
            - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
            - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
          - `entityIDs` string[] — Filter by specific entity UUIDs.
          - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
          - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
          - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
          - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
          - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
          - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
      - `entitlementAccessFilters` AccessRelationshipFilters — Filters the returned nodes by the access edges connected to them. When `isAccessibleBy` and `hasAccessTo` are provided, the returned nodes must satisfy both edge constraints simultaneously.
        - `isAccessibleBy` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
          - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
          - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
          - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
            - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
            - `string` string, required — The string value to match against the entity name.
          - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
            - `key` string, required — The tag key to filter by.
            - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
            - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
          - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
            - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
            - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
          - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
            - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
            - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
          - `entityIDs` string[] — Filter by specific entity UUIDs.
          - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
          - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
          - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
          - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
          - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
          - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
        - `hasAccessTo` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
          - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
          - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
          - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
            - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
            - `string` string, required — The string value to match against the entity name.
          - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
            - `key` string, required — The tag key to filter by.
            - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
            - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
          - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
            - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
            - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
          - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
            - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
            - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
          - `entityIDs` string[] — Filter by specific entity UUIDs.
          - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
          - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
          - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
          - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
          - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
          - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
      - `accessLevelRemoteIds` string[] — Filter by access-level remote IDs on the terminal edge.
      - `accessLevelNames` string[] — Filter by access-level display names on the terminal edge.
      - `edgeFilter` OpalAccessPathEdgeFilter — Constraints on the access path edges themselves.
        - `directOnly` boolean — When true, only return direct (depth-1) principal-to-entitlement edges.
        - `accessDurationType` 'EXPIRING_ONLY' | 'PERMANENT_ONLY' — Constrain results by whether the terminal access expires.
    - `reviewer_assignment_policy` 'MANUALLY' | 'BY_OWNING_TEAM_ADMIN' | 'BY_OWNING_TEAM_ADMIN_ALL' | 'BY_MANAGER' | 'BY_APPROVERS' | 'BY_APPROVERS_ALL' — A policy for auto-assigning reviewers. If auto-assignment is on, specific assignments can still be manually adjusted after the access review is started. Default is Manually. BY_OWNING_TEAM_ADMIN assigns reviews to resource admins in round-robin fashion. BY_OWNING_TEAM_ADMIN_ALL assigns reviews to all resource admins. BY_APPROVERS assigns reviews to resource approvers in round-robin fashion. BY_APPROVERS_ALL assigns reviews to all resource approvers.
    - `allow_self_review` boolean — Whether reviewers can review their own access.
    - `send_reviewer_assignment_notification` boolean — Whether to notify reviewers upon assignment.
    - `allow_reviewer_reassignment` boolean — Whether reviewers may reassign their reviews to another user.
    - `start_date` string, date-time, nullable — Scheduled start date of the campaign.
    - `end_date` string, date-time, nullable — Scheduled end date of the campaign.
    - `timezone` string — IANA timezone used to interpret campaign deadlines (e.g. America/Los_Angeles).
    - `revoke_on` 'ACTION' | 'END' | 'NONE' — When access decisions take effect during a campaign.
    - `reminder_schedule` integer[] — Days before end date to send reminder notifications.
    - `reminder_include_manager` boolean — Whether to include the reviewer's manager in reminders.
    - `require_reason_on_denial` boolean — Whether reviewers must provide a reason when denying (revoking) access.
    - `hide_ai_suggestions` boolean — Whether AI suggestions are hidden from reviewers.
    - `custom_start_message` string, nullable — Optional custom message included when notifying reviewers that the campaign started.
    - `group_asset_visibility_policy` 'STRICT' | 'VIEW_VISIBLE_AND_ASSIGNED' | 'VIEW_ALL' — Controls what group assets reviewers can see during the campaign.
    - `is_template` boolean — Whether this configuration is a recurring schedule template.
    - `cron_expression` string, nullable — Cron expression driving the recurring schedule. Null for one-off campaigns.
    - `recurring_duration_days` integer, nullable — Deadline window in days applied to each draft generated from this template.
    - `excluded_role_assignment_ids` string[] — Role assignment IDs to exclude from the campaign scope during population.

## Response `201`

The campaign successfully created.

- Campaign — An access review campaign.
  - `campaign_id` string, uuid, required — The ID of the campaign.
  - `name` string, required — The name of the campaign.
  - `status` 'DRAFT' | 'ONGOING' | 'COMPLETED' | 'STOPPED' | 'ENDED', required — The current status of a campaign.
  - `is_template` boolean, required — Whether this campaign is a recurring schedule template. Templates spawn draft campaigns on schedule rather than being reviewed directly.
  - `created_at` string, date-time, required — The creation time of the campaign.
  - `updated_at` string, date-time, required — The last updated time of the campaign.
  - `created_by_user_id` string, uuid, required — The ID of the user who created the campaign.
  - `configuration` CampaignConfiguration — Configuration for an access review campaign.
    - `configuration_id` string, uuid, required — The ID of the campaign configuration.
    - `created_at` string, date-time, required — The creation time of the configuration.
    - `updated_at` string, date-time, required — The last updated time of the configuration.
    - `query` OpalAccessPathQueryBody — Edge-query filters for an ACCESS_PATH OpalQuery. At least one of principalFilter or entitlementFilter is required.
      - `principalFilter` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
        - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
        - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
        - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
          - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
          - `string` string, required — The string value to match against the entity name.
        - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
          - `key` string, required — The tag key to filter by.
          - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
          - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
        - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
          - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
          - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
        - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
          - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
          - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
        - `entityIDs` string[] — Filter by specific entity UUIDs.
        - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
        - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
        - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
        - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
        - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
        - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
      - `entitlementFilter` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
        - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
        - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
        - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
          - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
          - `string` string, required — The string value to match against the entity name.
        - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
          - `key` string, required — The tag key to filter by.
          - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
          - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
        - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
          - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
          - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
        - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
          - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
          - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
        - `entityIDs` string[] — Filter by specific entity UUIDs.
        - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
        - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
        - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
        - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
        - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
        - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
      - `principalAccessFilters` AccessRelationshipFilters — Filters the returned nodes by the access edges connected to them. When `isAccessibleBy` and `hasAccessTo` are provided, the returned nodes must satisfy both edge constraints simultaneously.
        - `isAccessibleBy` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
          - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
          - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
          - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
            - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
            - `string` string, required — The string value to match against the entity name.
          - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
            - `key` string, required — The tag key to filter by.
            - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
            - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
          - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
            - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
            - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
          - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
            - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
            - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
          - `entityIDs` string[] — Filter by specific entity UUIDs.
          - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
          - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
          - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
          - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
          - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
          - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
        - `hasAccessTo` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
          - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
          - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
          - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
            - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
            - `string` string, required — The string value to match against the entity name.
          - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
            - `key` string, required — The tag key to filter by.
            - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
            - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
          - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
            - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
            - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
          - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
            - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
            - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
          - `entityIDs` string[] — Filter by specific entity UUIDs.
          - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
          - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
          - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
          - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
          - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
          - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
      - `entitlementAccessFilters` AccessRelationshipFilters — Filters the returned nodes by the access edges connected to them. When `isAccessibleBy` and `hasAccessTo` are provided, the returned nodes must satisfy both edge constraints simultaneously.
        - `isAccessibleBy` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
          - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
          - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
          - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
            - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
            - `string` string, required — The string value to match against the entity name.
          - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
            - `key` string, required — The tag key to filter by.
            - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
            - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
          - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
            - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
            - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
          - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
            - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
            - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
          - `entityIDs` string[] — Filter by specific entity UUIDs.
          - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
          - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
          - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
          - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
          - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
          - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
        - `hasAccessTo` AccessEntityFilters — Filters for matching entities by type, name, tag, IDs, connections, or access levels. Supports recursive logical composition via allOf/anyOf.
          - `entityTypes` string[] — Filter by entity type. Only RESOURCE, GROUP, and USER are queryable via OpalQuery.
          - `entityItemTypes` EntityItemTypeEnum[] — Filter by entity item types.
          - `entityName` EntityNameFilter — Filters entities by name using a string match strategy.
            - `stringMatchType` 'CONTAINS' | 'EQUALS' | 'STARTS_WITH' | 'ENDS_WITH', required — How to match a string value against entity names.
            - `string` string, required — The string value to match against the entity name.
          - `entityTag` EntityTagFilter — Filters entities by a tag key/value pair, optionally scoped to a connection.
            - `key` string, required — The tag key to filter by.
            - `value` string — The tag value to filter by. If omitted, matches any value for the given key.
            - `connectionId` string, uuid — If specified, filters by tags associated with this connection.
          - `hrIdpStatus` IdpStatusFilter — Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. "IDP status is NOT active"), so it still returns only users rather than sweeping in groups/resources.
            - `statuses` UserHrIdpStatusEnum[] — Match users whose HR/IDP status is one of these values.
            - `not` boolean — Invert the match within the user domain (e.g. "IDP status is NOT active").
          - `entityAdminOwner` EntityAdminFilter — Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
            - `ownerIDs` string[], required — The owner (group) UUIDs to match entities against.
            - `not` boolean — Invert the match — return resources/groups NOT owned by the given owners.
          - `entityIDs` string[] — Filter by specific entity UUIDs.
          - `importedFromApp` string[] — Filter by app IDs from which returned nodes will be imported from.
          - `roleRemoteIds` string[] — Filter by role remote IDs. Can only be applied within a hasAccessTo clause.
          - `roleNames` string[] — Filter by role display names (e.g. "Admin", "Read"). Can only be applied within a hasAccessTo clause.
          - `allOf` AccessEntityFilters[] — A list of nested filters that must all match (logical AND). Each item has the same shape as this object — scalar fields like `entityTypes` or `entityTag`, and can further nest `allOf`, `anyOf`, or `not`.
          - `anyOf` AccessEntityFilters[] — A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object.
          - `not` object — Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: ["RESOURCE"]}}` to exclude resources.
      - `accessLevelRemoteIds` string[] — Filter by access-level remote IDs on the terminal edge.
      - `accessLevelNames` string[] — Filter by access-level display names on the terminal edge.
      - `edgeFilter` OpalAccessPathEdgeFilter — Constraints on the access path edges themselves.
        - `directOnly` boolean — When true, only return direct (depth-1) principal-to-entitlement edges.
        - `accessDurationType` 'EXPIRING_ONLY' | 'PERMANENT_ONLY' — Constrain results by whether the terminal access expires.
    - `reviewer_assignment_policy` 'MANUALLY' | 'BY_OWNING_TEAM_ADMIN' | 'BY_OWNING_TEAM_ADMIN_ALL' | 'BY_MANAGER' | 'BY_APPROVERS' | 'BY_APPROVERS_ALL', required — A policy for auto-assigning reviewers. If auto-assignment is on, specific assignments can still be manually adjusted after the access review is started. Default is Manually. BY_OWNING_TEAM_ADMIN assigns reviews to resource admins in round-robin fashion. BY_OWNING_TEAM_ADMIN_ALL assigns reviews to all resource admins. BY_APPROVERS assigns reviews to resource approvers in round-robin fashion. BY_APPROVERS_ALL assigns reviews to all resource approvers.
    - `allow_self_review` boolean, required — Whether reviewers can review their own access.
    - `send_reviewer_assignment_notification` boolean, required — Whether to notify reviewers upon assignment.
    - `allow_reviewer_reassignment` boolean, required — Whether reviewers may reassign their reviews to another user.
    - `start_date` string, date-time, nullable — Scheduled start date of the campaign.
    - `end_date` string, date-time, nullable — Scheduled end date of the campaign.
    - `timezone` string, required — IANA timezone used to interpret campaign deadlines (e.g. America/Los_Angeles).
    - `revoke_on` 'ACTION' | 'END' | 'NONE', required — When access decisions take effect during a campaign.
    - `reminder_schedule` integer[] — Days before end date to send reminder notifications.
    - `reminder_include_manager` boolean, required — Whether to include the reviewer's manager in reminders.
    - `require_reason_on_denial` boolean, required — Whether reviewers must provide a reason when denying (revoking) access.
    - `hide_ai_suggestions` boolean, required — Whether AI suggestions are hidden from reviewers.
    - `custom_start_message` string, nullable — Optional custom message included when notifying reviewers that the campaign started.
    - `group_asset_visibility_policy` 'STRICT' | 'VIEW_VISIBLE_AND_ASSIGNED' | 'VIEW_ALL', required — Controls what group assets reviewers can see during the campaign.
    - `is_template` boolean, required — Whether this configuration is a recurring schedule template.
    - `cron_expression` string, nullable — Cron expression driving the recurring schedule. Null for one-off campaigns.
    - `next_scheduled_run` string, date-time, nullable — Next time a draft will be generated from this template.
    - `last_scheduled_run` string, date-time, nullable — Most recent time a draft was generated from this template.
    - `recurring_duration_days` integer, nullable — Deadline window in days applied to each draft generated from this template.
  - `started_at` string, date-time, nullable — The time the campaign was started, if started.
  - `started_by_user_id` string, uuid, nullable — The ID of the user who started the campaign, if started.
  - `stopped_at` string, date-time, nullable — The time the campaign was manually stopped, if stopped.
  - `stopped_by_user_id` string, uuid, nullable — The ID of the user who stopped the campaign, if stopped.
  - `ended_at` string, date-time, nullable — The time the campaign reached its scheduled end, if ended.
  - `ended_by_user_id` string, uuid, nullable — The ID of the user who ended the campaign, if ended.

---

[API](https://skmtc.net/opal/apis/opal-api.md) · [All operations](https://skmtc.net/opal/apis/opal-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/opal/opal-api/revisions/13b58df96d40/schema)
