# Get resource change indexed page

Get one page of indexed resource-change rows together with badge totals and selection-aware filter counts.

Badge totals, facets, rows, total items, and pagination are read in one repeatable-read transaction over one committed plan/applied generation pair, so a commit that lands during the request cannot mix those values.

Badge totals are fixed for the pair. The resources badge counts managed resources only. Facets and rows keep the category semantics of list-resource-change-rows and get-resource-change-filter-counts, including data sources inside the resources category.

A 404 means the stage has no fresh indexed snapshot. Callers fall through to the sharded page files and then the legacy list.

Endpoint: GET /iacm/api/orgs/{org}/projects/{project}/executions/{pipeline_execution_id}/{pipeline_stage_id}/resource-changes/{category}/indexed-page
Version: 1.0
Security: x-api-key

## Query parameters:

  - `change` (array)
    Restrict to these change types. Repeat the parameter to select more than one; omit it for all. Only meaningful for the planned_changes and drift_changes categories, whose rows are the only ones carrying a change type.
    Enum: "added", "changed", "deleted", "replaced", "unchanged", "removed", "imported"

  - `provider` (array)
    Restrict to these providers. Repeat the parameter to select more than one; omit it for all.
    Example: ["registry.opentofu.org/hashicorp/aws"]

  - `type` (array)
    Restrict to these provider resource types. Repeat the parameter to select more than one; omit it for all.
    Example: ["aws_instance"]

  - `module` (array)
    Restrict to these modules. Repeat the parameter to select more than one; omit it for all.
    Example: ["root"]

  - `search` (string)
    Case-insensitive substring match against the resource address and name.
    Example: "app_bucket"

  - `limit` (integer)
    Rows per page.
    Example: 25

  - `page` (integer)
    1-indexed page number to fetch.
    Example: 1

## Path parameters:

  - `org` (string, required)
    Org is the organisation identifier.
    Example: "6r"

  - `project` (string, required)
    Project is the project identifier.
    Example: "b4g"

  - `pipeline_execution_id` (string, required)
    Pipeline execution ID
    Example: "4"

  - `pipeline_stage_id` (string, required)
    Pipeline execution stage ID
    Example: "d"

  - `category` (string, required)
    Category to list rows from. One per tab in the table view.
    Enum: "planned_changes", "drift_changes", "resources", "outputs"

## Header parameters:

  - `Harness-Account` (string, required)
    Account is the internal customer account ID.
    Example: "3j"

## Response 200 fields (application/json):

  - `badges` (object, required)
    Badge totals for resource-changes tab, computed independently of paging.
    Example: {"added":1,"changed":0,"data_sources":0,"deleted":0,"drift_added":0,"drift_changed":1,"drift_changes":1,"drift_deleted":0,"drift_imported":0,"drift_removed":0,"drift_replaced":0,"drift_unchanged":0,"has_applied_state":false,"imported":0,"outputs":1,"planned_changes":1,"removed":0,"replaced":0,"resources":3,"unchanged":2}

  - `badges.added` (integer, required)
    Count of added resources in planned changes.
    Example: 1

  - `badges.changed` (integer, required)
    Count of changed resources in planned changes.

  - `badges.data_sources` (integer, required)
    Badge for data_sources filter.

  - `badges.deleted` (integer, required)
    Count of deleted resources in planned changes.

  - `badges.drift_added` (integer, required)
    Count of added resources in drift changes.

  - `badges.drift_changed` (integer, required)
    Count of changed resources in drift changes.
    Example: 1

  - `badges.drift_changes` (integer, required)
    Badge for drift_changes filter.
    Example: 1

  - `badges.drift_deleted` (integer, required)
    Count of deleted resources in drift changes.

  - `badges.drift_imported` (integer, required)
    Count of imported resources in drift changes.

  - `badges.drift_removed` (integer, required)
    Count of removed resources in drift changes.

  - `badges.drift_replaced` (integer, required)
    Count of replaced resources in drift changes.

  - `badges.drift_unchanged` (integer, required)
    Count of unchanged resources in drift changes, which unlike planned unchanged rows are part of the drift_changes total.

  - `badges.has_applied_state` (boolean)
    Whether this execution stage produced applied state.

  - `badges.imported` (integer, required)
    Count of imported resources in planned changes.

  - `badges.outputs` (integer, required)
    Badge for outputs filter.
    Example: 1

  - `badges.planned_changes` (integer, required)
    Badge for planned_changes filter.
    Example: 1

  - `badges.removed` (integer, required)
    Count of removed resources in planned changes.

  - `badges.replaced` (integer, required)
    Count of replaced resources in planned changes.

  - `badges.resources` (integer, required)
    Badge for resources filter.
    Example: 3

  - `badges.unchanged` (integer, required)
    Count of unchanged resources (own lazy-loaded filter).
    Example: 2

  - `facets` (object, required)
    Selection-aware counts for every filter option, across every dimension, in one request.

These are not the badge totals get-resource-change-counts returns. A badge total describes the whole
snapshot and never moves. A filter count answers "how many rows would I get if I also picked this
option", which is what makes the number beside a filter option useful, and it changes as the user
filters.

Each dimension is counted with the other dimensions' filters applied but not its own. Counting
every dimension under one shared predicate would make every unselected option read zero and leave
the user unable to widen a selection they had already narrowed.
    Example: {"categories":{"drift_changes":0,"outputs":0,"planned_changes":131,"resources":0},"change_types":{"added":130,"changed":0,"deleted":1,"imported":0,"removed":0,"unchanged":0},"modules":{"root":131},"providers":{"registry.opentofu.org/hashicorp/aws":131},"types":{"aws_default_vpc":1,"aws_instance":130}}

  - `facets.categories` (object, required)
    Row count per category, with every other dimension's filters applied but not the category filter.
    Example: {"drift_changes":0,"outputs":0,"planned_changes":131,"resources":0}

  - `facets.change_types` (object, required)
    Row count per change type, with every other dimension's filters applied but not the change-type filter. Empty for categories that have no change type. These are the numbers on the cards above the table.
    Example: {"added":130,"changed":0,"deleted":1,"imported":0,"removed":0,"unchanged":0}

  - `facets.modules` (object, required)
    Row count per module, with every other dimension's filters applied but not the module filter.
    Example: {"root":131}

  - `facets.providers` (object, required)
    Row count per provider, with every other dimension's filters applied but not the provider filter.
    Example: {"registry.opentofu.org/hashicorp/aws":131}

  - `facets.types` (object, required)
    Row count per provider resource type, with every other dimension's filters applied but not the type filter.
    Example: {"aws_default_vpc":1,"aws_instance":130}

  - `row_page` (object, required)
    One page of resource-change rows for an execution stage.

Pages are numbered and randomly addressable, so the table's page picker can jump straight to
page 5. totalItems and totalPages are what render the picker and the "(1 - 25) of 131" count.

Rows come back in the order they were stored, which is change-type priority (deleted, added,
changed, unchanged, removed, imported) then name. There is no sort parameter: the ordering was
settled once at write time, so no request pays to establish it and no two callers disagree
about it.
    Example: {"page":1,"pageSize":25,"rows":[{"category":"planned_changes","change":"added","change_count":3,"detail_bytes":2048,"drift":false,"mode":"resource","module":"root","name":"app_bucket","ordinal":17,"provider":"AWS","resource_address":"module.app.aws_s3_bucket.app_bucket","resource_id":"arn:aws:s3:::my-bucket","sensitive":false,"type":"aws_s3_bucket","value":"i-0abc123"},{"category":"planned_changes","change":"added","change_count":3,"detail_bytes":2048,"drift":false,"mode":"resource","module":"root","name":"app_bucket","ordinal":17,"provider":"AWS","resource_address":"module.app.aws_s3_bucket.app_bucket","resource_id":"arn:aws:s3:::my-bucket","sensitive":false,"type":"aws_s3_bucket","value":"i-0abc123"},{"category":"planned_changes","change":"added","change_count":3,"detail_bytes":2048,"drift":false,"mode":"resource","module":"root","name":"app_bucket","ordinal":17,"provider":"AWS","resource_address":"module.app.aws_s3_bucket.app_bucket","resource_id":"arn:aws:s3:::my-bucket","sensitive":false,"type":"aws_s3_bucket","value":"i-0abc123"},{"category":"planned_changes","change":"added","change_count":3,"detail_bytes":2048,"drift":false,"mode":"resource","module":"root","name":"app_bucket","ordinal":17,"provider":"AWS","resource_address":"module.app.aws_s3_bucket.app_bucket","resource_id":"arn:aws:s3:::my-bucket","sensitive":false,"type":"aws_s3_bucket","value":"i-0abc123"}],"totalItems":131,"totalPages":6}

  - `row_page.page` (integer, required)
    1-indexed page number returned.
    Example: 1

  - `row_page.pageSize` (integer, required)
    Maximum rows this page could hold.
    Example: 25

  - `row_page.rows` (array, required)
    Example: [{"category":"planned_changes","change":"added","change_count":3,"detail_bytes":2048,"drift":false,"mode":"resource","module":"root","name":"app_bucket","ordinal":17,"provider":"AWS","resource_address":"module.app.aws_s3_bucket.app_bucket","resource_id":"arn:aws:s3:::my-bucket","sensitive":false,"type":"aws_s3_bucket","value":"i-0abc123"},{"category":"planned_changes","change":"added","change_count":3,"detail_bytes":2048,"drift":false,"mode":"resource","module":"root","name":"app_bucket","ordinal":17,"provider":"AWS","resource_address":"module.app.aws_s3_bucket.app_bucket","resource_id":"arn:aws:s3:::my-bucket","sensitive":false,"type":"aws_s3_bucket","value":"i-0abc123"},{"category":"planned_changes","change":"added","change_count":3,"detail_bytes":2048,"drift":false,"mode":"resource","module":"root","name":"app_bucket","ordinal":17,"provider":"AWS","resource_address":"module.app.aws_s3_bucket.app_bucket","resource_id":"arn:aws:s3:::my-bucket","sensitive":false,"type":"aws_s3_bucket","value":"i-0abc123"}]

  - `row_page.rows.category` (string, required)
    Category this row belongs to.
    Enum: "planned_changes", "drift_changes", "resources", "outputs"

  - `row_page.rows.change` (string)
    Change made to this resource. Populated for planned_changes and drift_changes rows.
    Enum: "added", "changed", "deleted", "replaced", "unchanged", "imported", "removed"

  - `row_page.rows.change_count` (integer)
    Count of changed attributes on this resource. Populated for planned_changes and drift_changes rows.
    Example: 3

  - `row_page.rows.detail_bytes` (integer)
    Uncompressed size in bytes of this row's attribute document, so a client can decide whether to fetch it. Zero for outputs rows, which carry their value inline.
    Example: 2048

  - `row_page.rows.drift` (boolean)
    Whether this row came from drift detection rather than a plan. True exactly when category is drift_changes.

  - `row_page.rows.mode` (string)
    Whether the row is a managed resource or a data source. Populated for resources rows.
    Enum: "resource", "data"

  - `row_page.rows.module` (string, required)
    Module associated with the resource.
    Example: "root"

  - `row_page.rows.name` (string, required)
    Name associated with the resource, or the output name for outputs rows.
    Example: "app_bucket"

  - `row_page.rows.ordinal` (integer, required)
    Zero-based position of this row within its category. Ordinals are per-category and stable for the life of the snapshot, which is what makes them safe to address the detail endpoint with.
    Example: 17

  - `row_page.rows.provider` (string, required)
    Cloud provider associated with the resource.
    Example: "AWS"

  - `row_page.rows.resource_address` (string, required)
    Fully qualified address of the resource, module path included.
    Example: "module.app.aws_s3_bucket.app_bucket"

  - `row_page.rows.resource_id` (string)
    Identifier for the resource from the cloud provider. Populated for resources rows.
    Example: "arn:aws:s3:::my-bucket"

  - `row_page.rows.sensitive` (boolean)
    Whether this row's value is sensitive. Populated for outputs rows.

  - `row_page.rows.type` (string, required)
    Provider resource type.
    Example: "aws_s3_bucket"

  - `row_page.rows.value` (string)
    Output value. Populated for outputs rows, whose values are stored inline rather than behind a detail read.
    Example: "i-0abc123"

  - `row_page.totalItems` (integer, required)
    Total rows matching these filters, ignoring paging.
    Example: 131

  - `row_page.totalPages` (integer, required)
    Total pages matching these filters, so a client need not derive it.
    Example: 6

## Response 400 fields (application/vnd.goa.error):

  - `fault` (boolean, required)
    Is the error a server-side fault?
    Example: true

  - `id` (string, required)
    ID is a unique identifier for this particular occurrence of the problem.
    Example: "123abc"

  - `message` (string, required)
    Message is a human-readable explanation specific to this occurrence of the problem.
    Example: "parameter 'p' must be an integer"

  - `name` (string, required)
    Name is the name of this class of errors.
    Example: "bad_request"

  - `temporary` (boolean, required)
    Is the error temporary?
    Example: true

  - `timeout` (boolean, required)
    Is the error a timeout?


