> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lumos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sync App Review

> Run the sync for one app review, optionally replacing its scope filters in the same call.

The sync runs asynchronously: the request returns `202 Accepted` with an operation. Poll `GET /v1/operations/{id}` until `done` is true.

Rebuilding the subject set is what re-scoping means. Reviewer assignments survive for subjects that survive; subjects that fall out of scope take their assignments with them. A caller that re-scopes after assigning should re-check how many subjects are still unassigned before launching.

Only an app review at or before `assigning-reviewers` can be synced — once the review has launched, reviewers hold decisions a sync would invalidate.



## OpenAPI

````yaml /api-reference/lumos-api-v1.json post /v1/access-reviews/{review_uuid}/apps/{app_review_uuid}:sync
openapi: 3.1.0
info:
  title: Lumos API (v1)
  description: >

    Lumos API v1 is the programmatic interface to your connected apps, the
    entitlements on them, and

    the workflows that grant access to those entitlements.


    Every path is prefixed with `/v1`. Authenticate with an API token, which
    inherits the permissions

    of the user who created it: a call returns what that user could see in the
    Lumos UI, and nothing

    more.


    New here? Browse what you can connect with `GET /v1/integrations`, read the
    credentials an

    integration expects with `GET
    /v1/integrations/{app_class_id}/connection-schema`, then connect it

    with `POST /v1/apps`.


    Every list endpoint shares one pagination contract. Set the page length with
    `page_size`, then send

    the `next_page_token` from a response back as `page_token` to fetch the next
    page. A `null`

    `next_page_token` means you have reached the end.


    Every error shares one envelope. Branch on the machine-readable `code`, not
    on `detail`.
  version: 0.1.0
servers:
  - url: https://api.lumos.com
security: []
tags:
  - name: Access Policies
    description: >

      An access policy grants apps, and optionally specific entitlements on
      them, to the identities that

      qualify under its `access_condition`, a Lumos Condition object.


      `POST /v1/access-policies` creates a policy and returns 201. `GET
      /v1/access-policies` lists

      policies, and `GET`, `PUT`, and `DELETE` on
      `/v1/access-policies/{access_policy_id}` read, replace,

      and delete one.


      Each entitlement a policy grants appears under `apps[].entitlements[]`,
      identified by its

      Entitlement UUID, the `id` that `GET /v1/entitlements/{entitlement_uuid}`
      returns.
  - name: Access Requests
    description: >

      An access request asks for access to an app, or to specific entitlements
      on it, for you or for

      another user.


      - `POST /v1/access-requests` creates requests, naming entitlements by
      Entitlement UUID in
        `entitlement_ids`, and returns them as a list.
      - `GET /v1/access-requests` and `GET /v1/access-requests/{id}` read
      requests.

      - `POST /v1/access-requests/{id}:cancel` cancels a pending request.


      Of the built-in roles, Admin, Read Only Admin, AppStore Read Only Admin,
      and App Admin can read

      every access request in your organization. Anyone else sees only the
      requests they made and the

      ones made for them.
  - name: Access Reviews
    description: >

      An access review is a campaign that reviews who has access to what across
      your connected apps.

      Each app in a campaign is an app review.


      v1 has two access-review endpoints so far, both scoped to one app review:


      - `GET
      /v1/access-reviews/{review_uuid}/apps/{app_review_uuid}/subject-filters`
      lists the fields
        you can filter the app review's subjects on. Each field comes with the operators it supports
        and, when it has a fixed set of values, the values it accepts.
      - `POST /v1/access-reviews/{review_uuid}/apps/{app_review_uuid}:sync` runs
      the app review's data
        import, optionally with new scope filters. It returns 202 with an operation. Poll
        `GET /v1/operations/{operation_id}` until `done` is true.

      You can't create, list, or update campaigns in v1 yet. Lumos enables these
      endpoints per

      organization, separately from the rest of v1, so contact your Lumos
      representative to turn them on.
  - name: Accounts
    description: >

      An account is a person's presence inside a connected app. Accounts arrive
      through sync; you cannot

      create one through this API.


      `GET /v1/accounts/{account_uuid}/entitlements` lists what one account
      holds. It reads the same

      relationship as `GET /v1/entitlements/{entitlement_uuid}/accounts`, from
      the account's side rather

      than the entitlement's.
  - name: Activity Logs
    description: >

      Activity logs record the actions taken across your organization's apps and
      identities.

      `GET /v1/activity-logs` lists them, newest first.


      Reading activity logs requires permission to view them across your
      organization. Of the built-in

      roles, Admin and Read Only Admin have it. Without it, the request returns
      403.
  - name: App Categories
    description: >

      App categories are the fixed set of categories an app can belong to, such
      as `Developers`.

      `GET /v1/app-categories` lists them as `{label}` objects.


      A `label` is the exact value to send as `category` to `POST /v1/apps` and

      `PATCH /v1/apps/{app_uuid}`. It is also the value the app read endpoints
      report. Read the list

      instead of hard-coding it.
  - name: Apps
    description: >

      An app is an integration you have connected, one per connected instance of
      a service. Your Okta

      tenant is an app. A second Slack workspace is a second app.


      ### Connecting one


      1. `GET /v1/integrations/{app_class_id}/connection-schema` to see which
      `auth` and `settings`
         keys the integration expects.
      2. `POST /v1/apps` with those credentials. Apps whose credentials validate
      right away connect, and
         their first sync waits for an admin to review match rules. It starts from the Lumos UI, or from
         `POST /v1/apps/{app_uuid}:sync` with `skip_first_sync_review: true`. Apps that need browser
         consent are finished in the Lumos UI.
      3. `GET /v1/apps/{app_uuid}` to follow the first sync. `sync_status` shows
      the state of the
         app's most recent sync. A sync started with `POST /v1/apps/{app_uuid}:sync` also returns an
         operation, which you poll with `GET /v1/operations/{operation_id}`.
      4. `POST /v1/apps/{app_uuid}:sync` to resync later. Only one sync runs per
      app at a time, so a
         second request while one is in flight returns 409.

      Rotate credentials with `PATCH /v1/apps/{app_uuid}`, which also updates an
      app's metadata.

      `POST /v1/apps/{app_uuid}:disconnect` drops the stored credentials and
      returns the app to a

      connectable state; `DELETE /v1/apps/{app_uuid}` removes the app outright.


      ### Reading apps


      `expand` is opt-in and evaluated per field: ask for `admins`,
      `custom_attributes`,

      `appstore_settings`, or any of the three workflow fields. A field you lack
      permission to read is

      left out of the response instead of failing the whole request, so a 200
      does not prove every field

      you asked for came back.


      To list only the connected apps you manage through the API, combine
      `connection_source=api` with

      `disconnected=false`.


      ### Bound workflows


      Each app carries three bindings: an approval workflow, a default
      provisioning workflow, and a

      default deprovisioning workflow. The two `default_` workflows are the ones
      that entitlements on

      the app fall back to. To bind a workflow to one entitlement instead, use
      the Entitlements

      endpoints.
  - name: Custom Attribute Definitions
    description: >

      Custom attributes are the extra fields your organization keeps on users.
      These endpoints read

      their *definitions*, not the values stored against any particular user.


      `GET /v1/custom-attribute-definitions` returns one entry per label,
      unified across every app that

      supplies it. Narrow the list with `source_type` to tell attributes synced
      from an app apart from

      ones your team created, or with `app_id` to see only what a single app
      supplies.


      `GET /v1/custom-attribute-definitions/{id}` reads one definition by its
      `id`, and

      `GET /v1/custom-attribute-definitions/{id}/configs` lists the configs
      behind it, highest priority

      first.
  - name: Entitlements
    description: >

      An entitlement is a grantable unit of access on an app: a role, a license
      tier, a group, or

      another access right. Accounts hold entitlements.


      - `POST /v1/entitlements` creates a requestable entitlement on an app.

      - `GET /v1/apps/{app_uuid}/entitlements` lists the entitlements on one
      app.

      - `GET /v1/entitlements/{entitlement_uuid}/accounts` lists who currently
      holds one.

      - `PATCH /v1/entitlements/{entitlement_uuid}` updates its `label`,
      `description`, and
        `custom_approval_message_override`. Sending any other field returns 400.
      - `DELETE /v1/entitlements/{entitlement_uuid}` refuses while the
      entitlement is still held,
        returning 409 with an `active_accounts` count.

      ### Per-entitlement workflows


      An entitlement can have its own approval override, provisioning workflow,
      and deprovisioning

      workflow, bound to it rather than to the whole app. Each has a GET and a
      PUT, and the approval

      override also has a DELETE that turns it off.


      An entitlement that can't be requested returns 404 with

      `Workflows are not available for this entitlement.` on each of these
      endpoints.
  - name: Groups
    description: >

      Lumos syncs groups from your connected apps, such as your Okta groups, and
      these endpoints read

      them.


      - `GET /v1/groups` lists groups. Filter by `name` (add `exact_match=true`
      to require an exact
        match), by `integration_specific_id` (the group's ID in the source system), or by `app_id`.
      - `GET /v1/groups/{group_id}` reads one group, and `GET
      /v1/groups/{group_id}/users` lists its
        members.

      An `app_id` that matches no app in your organization returns 404.
  - name: Identity Events
    description: >

      Identity events are the changes Lumos detects on your organization's
      identities, such as a change

      to a status, a group membership, or a custom attribute. `GET
      /v1/identity-events` lists them.

      Narrow the list with `identity_ids`, `changed_fields`, `start_time`, and
      `end_time`.


      A page can come back empty while `next_page_token` is still set, because
      events Lumos can't read

      are dropped after a page is fetched. Keep paging until `next_page_token`
      is absent, not until a

      page is empty.
  - name: Inline Webhooks
    description: >

      Inline webhooks are the webhooks your organization has configured in
      Lumos.

      `GET /v1/inline-webhooks` lists all of them, whatever their type.


      A webhook's `type` says where Lumos uses it.
  - name: Integrations
    description: >

      An integration is a service Lumos knows how to connect to, identified by
      an `app_class_id` such as

      `okta.com` or `workspace.google.com`. This is the catalog you connect
      *from*. Apps you have

      already connected are read through the Apps endpoints.


      Only connectable integrations appear here. Software discovered in your
      environment that has no

      Lumos integration behind it is excluded.


      ### Discovering how to connect


      1. `GET /v1/integrations?query=google` to find the integration. The filter
      matches both the
         `app_class_id` and the display name, so `google` returns `workspace.google.com` and
         `cloud.google.com`.
      2. `GET /v1/integrations/{app_class_id}/connection-schema` for the JSON
      schema of the `auth` and
         `settings` fields it expects.
      3. `POST /v1/apps` with those values.


      Step 2 is the point of this group: it lets you build a connect form
      without hardcoding one

      credential shape per integration.


      `GET /v1/integrations/{app_class_id}` and the connection schema return 404
      for any integration the

      list leaves out. The connection schema also returns 404 for an integration
      whose schema Lumos

      cannot describe yet.
  - name: Knowledge
    description: >

      Knowledge entries are the documents and notes Lumos agents draw on when
      they answer access

      questions. Each entry carries a title, body, tags, and product scopes,
      plus an optional file

      attachment.


      Because of that attachment, create and update send `multipart/form-data`
      rather than JSON. On

      update, tag and scope lists replace what was there instead of appending,
      and `clear_attachment=true`

      removes an existing file without uploading a replacement.


      `DELETE` deletes a knowledge entry. It no longer appears in list results,
      and you can't restore

      it through the API.


      Pages here are small: `page_size` defaults to 10 and is clamped to 25.
  - name: Lifecycle Management
    description: >

      Lifecycle management covers user offboardings. An offboarding runs your
      organization's

      offboarding workflow for one user, either right away or at a scheduled
      time.


      - `POST /v1/lifecycle-management/user-offboardings` starts an offboarding
      now, or at
        `scheduled_at` when you send a future time.
      - `GET /v1/lifecycle-management/user-offboardings/{user_offboarding_id}`
      reads one.

      - `POST
      /v1/lifecycle-management/user-offboardings/{user_offboarding_id}:cancel`
      cancels one that
        is scheduled or in progress.

      There is no list endpoint, so keep the `id` that create returns.


      `workflow_config_id` names an offboarding workflow configuration, not a
      workflow from

      `/v1/workflows`. Omit it to use the configuration your organization has
      selected for automatic

      offboarding. Only organizations with the multiple offboarding workflows
      feature can send it. For

      any other organization, a request that includes it returns 400.
  - name: Meta
    description: >

      `GET /v1/info` returns the API's current git revision, and `GET /v1/art`
      returns Lumos ASCII art.

      Use either to check your setup.


      Both require an API token. A 200 means your token works.
  - name: Operations
    description: >

      An operation tracks work that continues after the request that started it
      has returned. These

      endpoints start such work and respond with 202 and an operation:


      - `POST /v1/apps/{app_uuid}:sync`

      - `POST /v1/accounts:upload`

      - `POST /v1/access-reviews/{review_uuid}/apps/{app_review_uuid}:sync`


      Poll `GET /v1/operations/{operation_id}` until `done` is true. While
      `done` is false, neither

      `result` nor `error` is set. Once `done` is true, exactly one of them is.


      An app-sync operation shows the app's most recent sync, which can be a
      later run than the one you

      started.
  - name: Pre-Approval Rules
    description: >

      A pre-approval rule pre-approves matching access requests for an app.


      - `GET /v1/apps/{app_uuid}/pre-approval-rules` lists an app's rules, and
      `POST` on the same path
        creates one.
      - `GET`, `PATCH`, and `DELETE` on
      `/v1/apps/{app_uuid}/pre-approval-rules/{pre_approval_rule_id}`
        read, update, and delete one.

      If the app has been merged into another app, these endpoints work on the
      rules of the app it was

      merged into.


      Lumos enables condition-based pre-approval rules per organization,
      separately from the rest of v1,

      so contact your Lumos representative to turn them on.
  - name: Tasks
    description: >

      A task is work Lumos assigns to a person or group, such as approving an
      access request or

      provisioning access by hand. A workflow that creates a task waits for
      someone to act on it before

      it continues.


      ### Finding tasks


      `GET /v1/tasks` lists the tasks visible to you. `show_all_tasks=true`
      lists every task in your

      organization instead. It needs permission to view every task, which the
      built-in Admin, Read Only

      Admin, and AppStore Read Only Admin roles have, and which a custom role
      can also grant. Anyone

      else gets a 403.


      Filter with `type`, `category`, `status`, and `product_area`, whose values
      are lowercase and

      kebab-case. For example,

      `GET /v1/tasks?category=approval&product_area=appstore&status=pending`
      lists pending AppStore

      approvals.


      A task names the entitlement it grants or removes in `entitlement_id`, an
      Entitlement UUID.


      ### Acting on a task


      - `POST /v1/tasks/{task_id}:complete` approves an approval task, or
      completes another task with
        its one completion action.
      - `POST /v1/tasks/{task_id}:dismiss` denies an approval task, or dismisses
      another task without
        doing its work.
      - `POST /v1/tasks/{task_id}:perform-action` takes a specific action.
        `GET /v1/tasks/{task_id}/actions` lists the actions you can take and the statuses each one can
        move the task to, which are the values `transition_to` accepts.
      - `POST /v1/tasks/{task_id}:reassign` changes who the task is assigned to.
  - name: Users
    description: >

      Users are the people in your organization. These endpoints read them, and
      the only thing they

      change is a user's Lumos roles.


      - `GET /v1/users` lists users. `search` matches names and emails, and
      `exact_match=true`
        requires an exact match.
      - `GET /v1/users/current` returns the user who owns your API token.

      - `GET /v1/users/{user_id}` reads one user, and `GET
      /v1/users/{user_id}/accounts` lists the
        accounts that user holds.
      - `GET /v1/users/{user_id}/roles` lists a user's Lumos roles. Each role
      has an `id` (a built-in
        role's kebab-case name such as `app-admin`, or a custom role's UUID), a display `label`,
        `is_custom`, and a `resource_type` that is null for roles that apply across the organization.
        `POST /v1/users/{user_id}/roles/{role_id}` assigns one, and
        `DELETE /v1/users/{user_id}/roles/{role_id}` removes one, where `role_id` is the role's `id`.
        Assigning a role the user already has, or removing one they don't have, changes nothing.

      A user who has been deleted returns the same 404 as one who doesn't exist
      in your organization.
  - name: Workflows
    description: >

      A workflow is a reusable definition of the steps Lumos runs to approve a
      request, provision access,

      or deprovision it. Create the definition here, then bind it to an app or
      an entitlement through

      their own workflow endpoints.


      ### Building one


      1. `GET /v1/workflow-steps?app_id={app_uuid}&type={workflow type}` to
      discover the steps available
         for that app in the type of workflow you will create, each with the input schema it accepts.
         Without `type`, it lists only the steps every workflow type accepts.
      2. `POST /v1/workflows` with the steps you want.

      3. Bind it, for example with `PUT
      /v1/apps/{app_uuid}/default-provisioning-workflow`.


      `type` and `app_id` are fixed at creation. `PUT
      /v1/workflows/{workflow_id}` returns 400 for a

      change to either.


      ### Workflows this API cannot describe


      Some workflows Lumos builds for you, including the out-of-the-box
      provisioning defaults, contain

      steps with no public representation. `GET /v1/workflows` skips them, so a
      page can hold fewer items

      than `page_size` while more results remain. Treat an absent
      `next_page_token`, not a short page, as

      the end of the list. Binding one of these to an app or entitlement returns
      400.
paths:
  /v1/access-reviews/{review_uuid}/apps/{app_review_uuid}:sync:
    post:
      tags:
        - Access Reviews
      summary: Sync App Review
      description: >-
        Run the sync for one app review, optionally replacing its scope filters
        in the same call.


        The sync runs asynchronously: the request returns `202 Accepted` with an
        operation. Poll `GET /v1/operations/{id}` until `done` is true.


        Rebuilding the subject set is what re-scoping means. Reviewer
        assignments survive for subjects that survive; subjects that fall out of
        scope take their assignments with them. A caller that re-scopes after
        assigning should re-check how many subjects are still unassigned before
        launching.


        Only an app review at or before `assigning-reviewers` can be synced —
        once the review has launched, reviewers hold decisions a sync would
        invalidate.
      operationId: syncAppReview
      parameters:
        - name: review_uuid
          in: path
          required: true
          schema:
            type: string
            description: The access review's ID.
            title: Review Uuid
          description: The access review's ID.
        - name: app_review_uuid
          in: path
          required: true
          schema:
            type: string
            description: >-
              The app review's ID. An app review is one app within the access
              review that `review_uuid` names.
            title: App Review Uuid
          description: >-
            The app review's ID. An app review is one app within the access
            review that `review_uuid` names.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SyncAppReviewInput'
      responses:
        '202':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OperationEnvelope'
        '400':
          description: >-
            Validation error — a filter names an unknown scopable property, or
            carries a value the property does not accept
            (`scope_filter.invalid`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorEnvelope'
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorEnvelope'
          description: Unauthorized
        '403':
          description: Forbidden — the caller may not sync this app review.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorEnvelope'
        '404':
          description: >-
            Not found — no campaign with this UUID in your organization
            (`access_review.not_found`), or the campaign holds no app review
            with this UUID (`app_review.not_found`). An app review under a
            different campaign reports the latter.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorEnvelope'
        '409':
          description: >-
            Conflict — a sync is already running
            (`app_review.sync_in_progress`), or the review has launched and can
            no longer be synced (`app_review.launched`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorEnvelope'
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorEnvelope'
          description: Too Many Requests
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorEnvelope'
          description: Internal Server Error
      security:
        - HTTPBearer: []
components:
  schemas:
    SyncAppReviewInput:
      properties:
        scope_filters:
          anyOf:
            - items:
                oneOf:
                  - $ref: '#/components/schemas/ScalarScopeFilterInput'
                  - $ref: '#/components/schemas/CustomAttributeScopeFilterInput'
                  - $ref: '#/components/schemas/DatetimeScopeFilterInput'
                discriminator:
                  propertyName: group
                  mapping:
                    ACCESS_APPROVED_AT: '#/components/schemas/ScalarScopeFilterInput'
                    ACCESS_GRANTED_AT: '#/components/schemas/ScalarScopeFilterInput'
                    ACCESS_LENGTH: '#/components/schemas/ScalarScopeFilterInput'
                    ACCESS_PROVISIONED_AT: '#/components/schemas/ScalarScopeFilterInput'
                    ACCESS_REQUESTED_AT: '#/components/schemas/ScalarScopeFilterInput'
                    ACCOUNT: '#/components/schemas/ScalarScopeFilterInput'
                    ACCOUNT_DELTA: '#/components/schemas/ScalarScopeFilterInput'
                    ACCOUNT_ENTITLEMENT: '#/components/schemas/ScalarScopeFilterInput'
                    ACCOUNT_SOURCE: '#/components/schemas/ScalarScopeFilterInput'
                    ACCOUNT_STATUS: '#/components/schemas/ScalarScopeFilterInput'
                    CATEGORIES: '#/components/schemas/ScalarScopeFilterInput'
                    CUSTOM_ATTRIBUTE: '#/components/schemas/CustomAttributeScopeFilterInput'
                    EMAIL_DOMAIN: '#/components/schemas/ScalarScopeFilterInput'
                    EMPLOYMENT_STATUS: '#/components/schemas/ScalarScopeFilterInput'
                    ENTITLEMENT_TAG: '#/components/schemas/ScalarScopeFilterInput'
                    IDENTITY: '#/components/schemas/ScalarScopeFilterInput'
                    LAST_ACTIVITY: '#/components/schemas/DatetimeScopeFilterInput'
                    LAST_LOGIN: '#/components/schemas/DatetimeScopeFilterInput'
                    SOD_POLICY: '#/components/schemas/ScalarScopeFilterInput'
                    TEAM: '#/components/schemas/ScalarScopeFilterInput'
                    UNMATCHED_ACCOUNTS: '#/components/schemas/ScalarScopeFilterInput'
                    USER_OR_GROUP: '#/components/schemas/ScalarScopeFilterInput'
              type: array
            - type: 'null'
          title: Scope Filters
          description: >-
            Replaces the app review's scope filters wholesale — this is a PUT,
            not a merge, so send the full set you want and omit the field
            entirely to sync against the filters already set. An empty list
            clears them. Each filter's `value` must be one that `GET
            /access_reviews/scope_options` advertises for this app.
        skip_new_data:
          type: boolean
          title: Skip New Data
          description: >-
            When true, rebuilds the subject set from data already synced instead
            of pulling fresh data from the integration — the fast path when only
            the filters changed.
          default: false
      additionalProperties: false
      type: object
      title: SyncAppReviewInput
      examples:
        - scope_filters:
            - group: EMPLOYMENT_STATUS
              label: Inactive
              name: Employment Status
              value: INACTIVE
          skip_new_data: true
    OperationEnvelope:
      properties:
        operation:
          $ref: '#/components/schemas/OperationOutput'
          description: The launched operation.
      type: object
      required:
        - operation
      title: OperationEnvelope
      description: 202 response body for endpoints that launch an operation.
    ApiErrorEnvelope:
      properties:
        error:
          $ref: '#/components/schemas/ApiError'
          description: The error that caused this response.
      type: object
      required:
        - error
      title: ApiErrorEnvelope
      description: >-
        The V1 error response body. Every error nests under `error`, so an error
        body is

        recognizable by its shape, not only its status code.
    ScalarScopeFilterInput:
      properties:
        group:
          type: string
          enum:
            - ACCOUNT_ENTITLEMENT
            - TEAM
            - EMPLOYMENT_STATUS
            - EMAIL_DOMAIN
            - CATEGORIES
            - ACCOUNT_DELTA
            - ACCOUNT_STATUS
            - ACCOUNT_SOURCE
            - SOD_POLICY
            - ACCESS_GRANTED_AT
            - ACCESS_REQUESTED_AT
            - ACCESS_APPROVED_AT
            - ACCESS_PROVISIONED_AT
            - ACCESS_LENGTH
            - USER_OR_GROUP
            - UNMATCHED_ACCOUNTS
            - ENTITLEMENT_TAG
            - IDENTITY
            - ACCOUNT
          title: Group
          description: >-
            Scope filter group. Use DatetimeScopeFilterInput for LAST_LOGIN /
            LAST_ACTIVITY and CustomAttributeScopeFilterInput for
            CUSTOM_ATTRIBUTE.
        name:
          type: string
          maxLength: 255
          title: Name
          description: >-
            Internal identifier for this filter item. For ACCOUNT_ENTITLEMENT
            this is the entitlement **type label** (e.g. 'Team', 'Role', 'Repo
            Access') — copy it from the matching item's `name` in GET
            /access_reviews/scope_options.
        label:
          type: string
          maxLength: 255
          title: Label
          description: Human-readable display label.
        value:
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
          title: Value
          description: >-
            The value to filter by. This must be the exact `value` of an item
            returned by GET /access_reviews/scope_options for this app — the
            machine-matchable identifier, **not** the human-readable `label`.
            For ACCOUNT_ENTITLEMENT the value is the entitlement's
            integration_specific_entitlement_id, which may be an opaque id (e.g.
            a numeric team id) rather than its display name. Posting a `label`,
            or any value not present in scope_options, is rejected.
        type:
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
          title: Type
          description: >-
            Attribute type. Required for USER_OR_GROUP (must be 'USER' or
            'GROUP'). Ignored for all other groups.
      additionalProperties: false
      type: object
      required:
        - group
        - name
        - label
      title: ScalarScopeFilterInput
      description: |-
        Scope filter for groups whose value is a simple string/UUID/enum.

        Datetime-valued groups (``LAST_LOGIN``, ``LAST_ACTIVITY``) use
        :class:`DatetimeScopeFilterInput`; ``CUSTOM_ATTRIBUTE`` uses
        :class:`CustomAttributeScopeFilterInput`.
    CustomAttributeScopeFilterInput:
      properties:
        group:
          type: string
          enum:
            - CUSTOM_ATTRIBUTE
          const: CUSTOM_ATTRIBUTE
          title: Group
          description: Always CUSTOM_ATTRIBUTE.
        name:
          type: string
          maxLength: 255
          title: Name
          description: >-
            Custom attribute label (e.g. 'Department'). Matches the label from
            scope_options.
        label:
          type: string
          maxLength: 255
          title: Label
          description: Human-readable display label.
        value:
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
          title: Value
          description: Value to filter by for this custom attribute.
        type:
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
          title: Type
          description: >-
            Attribute type (STRING, INTEGER, DATETIME, USER, GROUP,
            SINGLESELECT, MULTISELECT).
      additionalProperties: false
      type: object
      required:
        - group
        - name
        - label
      title: CustomAttributeScopeFilterInput
      description: |-
        Scope filter for ``CUSTOM_ATTRIBUTE`` groups.

        Custom attributes are keyed by ``name`` (the attribute label, e.g.
        "Department"). ``type`` declares the attribute's type (STRING, INTEGER,
        DATETIME, USER, GROUP, SINGLESELECT, MULTISELECT).
    DatetimeScopeFilterInput:
      properties:
        group:
          type: string
          enum:
            - LAST_LOGIN
            - LAST_ACTIVITY
          title: Group
          description: Datetime scope filter group. Must be LAST_LOGIN or LAST_ACTIVITY.
        name:
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
          title: Name
          description: >-
            Optional. If given, must equal the group's `name` from GET
            /access_reviews/scope_options (e.g. 'Last Login'); the stored filter
            always uses that name.
        after:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: After
          description: >-
            Inclusive lower bound. Records where the datetime field is >= this
            value match.
        before:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Before
          description: >-
            Inclusive upper bound. Records where the datetime field is <= this
            value match.
      additionalProperties: false
      type: object
      required:
        - group
      title: DatetimeScopeFilterInput
      description: >-
        Scope filter for datetime-valued groups (``LAST_LOGIN``,
        ``LAST_ACTIVITY``).


        Provide ``after``, ``before``, or both. Bounds are inclusive. At least
        one

        must be set.


        - ``after`` alone: matches records where the field is on or after that
        timestamp.

        - ``before`` alone: matches records where the field is on or before that
        timestamp.

        - Both: matches records in the closed interval ``[after, before]``. If
        the
          two bounds are equal, this matches records at exactly that timestamp.
    OperationOutput:
      properties:
        id:
          type: string
          title: Id
          description: >-
            Opaque operation identifier. Poll `GET /v1/operations/{id}` with it;
            do not decode or construct it.
        done:
          type: boolean
          title: Done
          description: >-
            Whether the operation reached a terminal state. While false, neither
            `result` nor `error` is set; when true, exactly one of them is.
        result:
          anyOf:
            - type: object
            - type: 'null'
          title: Result
          description: Operation output on success. Shape depends on the operation kind.
        error:
          anyOf:
            - $ref: '#/components/schemas/OperationError'
            - type: 'null'
          description: >-
            Terminal failure details. Set only when `done` and the operation
            failed.
        metadata:
          anyOf:
            - additionalProperties:
                type: string
              type: object
            - type: 'null'
          title: Metadata
          description: >-
            Operation kind and launch context (e.g. type, the resource it runs
            against). Informational; keys may be added over time.
      type: object
      required:
        - id
        - done
      title: OperationOutput
    ApiError:
      properties:
        detail:
          type: string
          title: Detail
          description: Human-readable summary of the error.
        type:
          $ref: '#/components/schemas/ErrorType'
          description: >-
            Category:
            validation|authentication|permission|not_found|conflict|rate_limited|runtime.
        code:
          type: string
          title: Code
          description: Stable machine-readable error code; branch on this, not 'detail'.
        errors:
          items:
            $ref: '#/components/schemas/ApiErrorField'
          type: array
          title: Errors
          description: Field-level errors; empty for non-validation errors.
      type: object
      required:
        - detail
        - type
        - code
      title: ApiError
      description: The V1 error object — the contents of the envelope's `error` field.
    OperationError:
      properties:
        code:
          type: string
          title: Code
          description: Stable machine-readable failure code.
        message:
          type: string
          title: Message
          description: Human-readable failure description.
        errors:
          items:
            $ref: '#/components/schemas/ApiErrorField'
          type: array
          title: Errors
          description: >-
            Item-level failures for bulk operations, such as one entry for each
            uploaded account that failed. Empty when the failure is not
            itemized.
      type: object
      required:
        - code
        - message
      title: OperationError
      description: Terminal failure of an operation, in the standard error shape.
    ErrorType:
      type: string
      enum:
        - validation
        - authentication
        - permission
        - not_found
        - conflict
        - rate_limited
        - runtime
      title: ErrorType
    ApiErrorField:
      properties:
        field:
          type: string
          title: Field
          description: Input field this error refers to, e.g. 'steps[2].inputs.group_id'.
        code:
          type: string
          title: Code
          description: Stable machine-readable code for this field error.
        message:
          type: string
          title: Message
          description: Human-readable description of the field error.
      type: object
      required:
        - field
        - code
        - message
      title: ApiErrorField
      description: A single field-level error (used for validation failures).
  securitySchemes:
    HTTPBearer:
      type: http
      scheme: bearer

````