> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/api-reference/ar/registry-v3-tree-view.md).

# Registry V3 Tree View

V3 tree view endpoints for hierarchical navigation

## List node children

> Lists immediate children of a specific node (package/version/folder).\
> Returns child nodes for tree navigation.<br>

```json
{"openapi":"3.0.0","info":{"title":"Harness Artifact Registry API","version":"1.0.0"},"tags":[{"description":"V3 tree view endpoints for hierarchical navigation","name":"Registry V3 - Tree View"}],"servers":[{"url":"/api"}],"paths":{"/v3/tree/nodes/{node_id}/children":{"get":{"description":"Lists immediate children of a specific node (package/version/folder).\nReturns child nodes for tree navigation.\n","operationId":"ListNodeChildrenV3","parameters":[{"$ref":"#/components/parameters/AccountIdentifierV3"},{"$ref":"#/components/parameters/OrgIdentifierV3"},{"$ref":"#/components/parameters/ProjectIdentifierV3"},{"$ref":"#/components/parameters/NodeIdPathParamV3"},{"$ref":"#/components/parameters/TreeCursorParamV3"},{"$ref":"#/components/parameters/TreeSizeParamV3"},{"$ref":"#/components/parameters/TreeDeletedFilterParamV3"},{"$ref":"#/components/parameters/TreeCompactParamV3"}],"responses":{"200":{"$ref":"#/components/responses/TreeResponseV3"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorV3"}}},"description":"Error response."}},"summary":"List node children","tags":["Registry V3 - Tree View"]}}},"components":{"parameters":{"AccountIdentifierV3":{"description":"Unique identifier for the Harness account.\n","in":"query","name":"account_identifier","required":true,"schema":{"type":"string"}},"OrgIdentifierV3":{"description":"Unique identifier for the organization within the account.\n\nExample: `default` or `engineering_org`\n","in":"query","name":"org_identifier","schema":{"type":"string"}},"ProjectIdentifierV3":{"description":"Unique identifier for the project within the organization.\n\nExample: `my_project` or `frontend_services`\n","in":"query","name":"project_identifier","schema":{"type":"string"}},"NodeIdPathParamV3":{"description":"Unique identifier for the node.\n","in":"path","name":"node_id","required":true,"schema":{"type":"string"}},"TreeCursorParamV3":{"description":"Cursor for pagination in tree view endpoints.\nBase64-encoded JSON containing pagination state.\n","in":"query","name":"cursor","schema":{"type":"string"}},"TreeSizeParamV3":{"description":"Number of items to return per page in tree view.\n","in":"query","name":"size","schema":{"default":50,"maximum":1000,"minimum":1,"type":"integer"}},"TreeDeletedFilterParamV3":{"description":"Filter for deleted items in tree view. Applied at the root (registry) level only,\nwhere `registries.registry_deleted_at` is authoritative. Levels below the root always\nreturn every node regardless of soft-delete state - use `isDeleted` on each node to\nrender deleted state. See TreeNodeItemV3.isDeleted for why per-node filtering is not\nsupported yet.\n","in":"query","name":"deleted_filter","schema":{"default":"exclude_deleted","enum":["exclude_deleted","include_deleted","only_deleted"],"type":"string"}},"TreeCompactParamV3":{"description":"Collapses a run of single-child folders into one row, e.g. `io/harness/platform/api`\nrenders as one node instead of four levels. A collapsed row carries the deepest\nfolder's id (what an expand call must use) and a display name joining every segment\nin the run. Collapsing stops at the first node with more than one child, and never\nabsorbs a file - the chain always ends at the last folder.\n\nNo-op for Docker and Helm: those tiers are synthetic (built from images/tags/manifest\nreferences) and cannot form a single-child folder chain, so the parameter is accepted\nand ignored rather than rejected. Not declared on `/tree/roots` - registries are never\ncollapsed into each other - and ignored if sent there.\n","in":"query","name":"compact","schema":{"default":false,"type":"boolean"}}},"responses":{"TreeResponseV3":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TreeResponseBodyV3"}}},"description":"Response for tree view endpoints"}},"schemas":{"TreeResponseBodyV3":{"description":"Response body for tree view endpoints","properties":{"items":{"description":"List of tree nodes","items":{"$ref":"#/components/schemas/TreeNodeItemV3"},"type":"array"},"pagination":{"$ref":"#/components/schemas/TreePaginationV3"}},"required":["items","pagination"]},"TreeNodeItemV3":{"description":"A node in the tree view representing a registry, package, version, folder, or file","properties":{"createdAt":{"description":"Creation timestamp in milliseconds","format":"int64","type":"integer"},"deletedAt":{"description":"Deletion timestamp in milliseconds (if soft-deleted)","format":"int64","type":"integer"},"hasChildren":{"description":"Whether this node has child nodes","type":"boolean"},"id":{"description":"Unique identifier (UUID for nodes, registry_id for root registries)","type":"string"},"isDeleted":{"description":"Whether this node is soft-deleted. Tree levels below the root return both active and\nsoft-deleted nodes, so clients must use this flag to render deleted state rather than\nassuming every returned node is live.\n\nOmitted when soft-delete state cannot be determined for the node's level: the version\nand platform levels of OCI (Docker/Helm) registries come from\n`tags`/`manifests`/`manifest_references`, none of which have a soft-delete column,\nand all nodes of non-OCI registries come from `nodes`, whose `node_deleted_at` column\nis not populated by any write path. Only the root (`registries`) and Docker/Helm\npackage (`images`) levels can answer this. An omitted value means \"unknown\" - it must\nnot be read as \"not deleted\".\n","type":"boolean"},"name":{"description":"Display name of the node","type":"string"},"packageType":{"description":"Package type (for registries/packages)","type":"string"},"path":{"description":"Full path to this node","type":"string"},"type":{"description":"Type of the node","enum":["registry","folder","package","version","file"],"type":"string"}},"required":["id","name","type","hasChildren"],"type":"object"},"TreePaginationV3":{"description":"Pagination information for tree view","properties":{"hasMore":{"description":"Whether there are more pages","type":"boolean"},"nextCursor":{"description":"Cursor for next page (base64 encoded)","type":"string"},"size":{"description":"Page size","format":"int32","type":"integer"},"total":{"description":"Total number of items matching the request across all pages, independent of\npagination.\n\nExact at the root (registry) level, where the filtered set is small enough to\ncount cheaply. Below the root it is **capped** (currently at 1000): child fanout\nis unbounded, and an exact count of a wide parent is far more expensive than the\npage itself. A value at the cap means \"at least this many\", not necessarily\nexact - use `hasMore` to drive \"Load More\" rather than comparing against `total`.\n\nOptional, and **absent on root-level pages fetched with a `cursor`**: the total\ndoes not change while paging through a fixed filter set, so it is computed once on\nthe first page and the client is expected to hold it across Load More.\n","format":"int64","type":"integer"}},"required":["size","hasMore"],"type":"object"},"ErrorV3":{"description":"An error response","properties":{"error":{"$ref":"#/components/schemas/ApiErrorsV3"}},"required":["error"],"type":"object"},"ApiErrorsV3":{"properties":{"code":{"description":"For some errors that could be handled programmatically, a short string indicating the [error code](https://docs.stripe.com/error-codes) reported.","maxLength":5000,"type":"string"},"message":{"description":"A human-readable message providing more details about the error. These messages can be shown to users.","maxLength":40000,"type":"string"},"param":{"description":"If the error is parameter-specific, the parameter related to the error. For example, we can use this to display a message near the correct form field.","maxLength":5000,"type":"string"},"type":{"description":"The type of error returned.","enum":["INVALID_REQUEST_ERROR","AUTHENTICATION_ERROR","PERMISSION_ERROR","API_ERROR"],"type":"string"}},"required":["type"],"title":"APIErrors","type":"object"}}}}
```

## List registry nodes

> Lists top-level packages/folders under a specific registry.\
> Returns immediate children of the registry for tree navigation.<br>

```json
{"openapi":"3.0.0","info":{"title":"Harness Artifact Registry API","version":"1.0.0"},"tags":[{"description":"V3 tree view endpoints for hierarchical navigation","name":"Registry V3 - Tree View"}],"servers":[{"url":"/api"}],"paths":{"/v3/tree/registries/{registry_id}/nodes":{"get":{"description":"Lists top-level packages/folders under a specific registry.\nReturns immediate children of the registry for tree navigation.\n","operationId":"ListRegistryNodesV3","parameters":[{"$ref":"#/components/parameters/AccountIdentifierV3"},{"$ref":"#/components/parameters/OrgIdentifierV3"},{"$ref":"#/components/parameters/ProjectIdentifierV3"},{"$ref":"#/components/parameters/RegistryIdPathParamV3"},{"$ref":"#/components/parameters/TreeCursorParamV3"},{"$ref":"#/components/parameters/TreeSizeParamV3"},{"$ref":"#/components/parameters/TreeDeletedFilterParamV3"},{"$ref":"#/components/parameters/TreeCompactParamV3"}],"responses":{"200":{"$ref":"#/components/responses/TreeResponseV3"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorV3"}}},"description":"Error response."}},"summary":"List registry nodes","tags":["Registry V3 - Tree View"]}}},"components":{"parameters":{"AccountIdentifierV3":{"description":"Unique identifier for the Harness account.\n","in":"query","name":"account_identifier","required":true,"schema":{"type":"string"}},"OrgIdentifierV3":{"description":"Unique identifier for the organization within the account.\n\nExample: `default` or `engineering_org`\n","in":"query","name":"org_identifier","schema":{"type":"string"}},"ProjectIdentifierV3":{"description":"Unique identifier for the project within the organization.\n\nExample: `my_project` or `frontend_services`\n","in":"query","name":"project_identifier","schema":{"type":"string"}},"RegistryIdPathParamV3":{"description":"Unique identifier for the registry.\n","in":"path","name":"registry_id","required":true,"schema":{"type":"string"}},"TreeCursorParamV3":{"description":"Cursor for pagination in tree view endpoints.\nBase64-encoded JSON containing pagination state.\n","in":"query","name":"cursor","schema":{"type":"string"}},"TreeSizeParamV3":{"description":"Number of items to return per page in tree view.\n","in":"query","name":"size","schema":{"default":50,"maximum":1000,"minimum":1,"type":"integer"}},"TreeDeletedFilterParamV3":{"description":"Filter for deleted items in tree view. Applied at the root (registry) level only,\nwhere `registries.registry_deleted_at` is authoritative. Levels below the root always\nreturn every node regardless of soft-delete state - use `isDeleted` on each node to\nrender deleted state. See TreeNodeItemV3.isDeleted for why per-node filtering is not\nsupported yet.\n","in":"query","name":"deleted_filter","schema":{"default":"exclude_deleted","enum":["exclude_deleted","include_deleted","only_deleted"],"type":"string"}},"TreeCompactParamV3":{"description":"Collapses a run of single-child folders into one row, e.g. `io/harness/platform/api`\nrenders as one node instead of four levels. A collapsed row carries the deepest\nfolder's id (what an expand call must use) and a display name joining every segment\nin the run. Collapsing stops at the first node with more than one child, and never\nabsorbs a file - the chain always ends at the last folder.\n\nNo-op for Docker and Helm: those tiers are synthetic (built from images/tags/manifest\nreferences) and cannot form a single-child folder chain, so the parameter is accepted\nand ignored rather than rejected. Not declared on `/tree/roots` - registries are never\ncollapsed into each other - and ignored if sent there.\n","in":"query","name":"compact","schema":{"default":false,"type":"boolean"}}},"responses":{"TreeResponseV3":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TreeResponseBodyV3"}}},"description":"Response for tree view endpoints"}},"schemas":{"TreeResponseBodyV3":{"description":"Response body for tree view endpoints","properties":{"items":{"description":"List of tree nodes","items":{"$ref":"#/components/schemas/TreeNodeItemV3"},"type":"array"},"pagination":{"$ref":"#/components/schemas/TreePaginationV3"}},"required":["items","pagination"]},"TreeNodeItemV3":{"description":"A node in the tree view representing a registry, package, version, folder, or file","properties":{"createdAt":{"description":"Creation timestamp in milliseconds","format":"int64","type":"integer"},"deletedAt":{"description":"Deletion timestamp in milliseconds (if soft-deleted)","format":"int64","type":"integer"},"hasChildren":{"description":"Whether this node has child nodes","type":"boolean"},"id":{"description":"Unique identifier (UUID for nodes, registry_id for root registries)","type":"string"},"isDeleted":{"description":"Whether this node is soft-deleted. Tree levels below the root return both active and\nsoft-deleted nodes, so clients must use this flag to render deleted state rather than\nassuming every returned node is live.\n\nOmitted when soft-delete state cannot be determined for the node's level: the version\nand platform levels of OCI (Docker/Helm) registries come from\n`tags`/`manifests`/`manifest_references`, none of which have a soft-delete column,\nand all nodes of non-OCI registries come from `nodes`, whose `node_deleted_at` column\nis not populated by any write path. Only the root (`registries`) and Docker/Helm\npackage (`images`) levels can answer this. An omitted value means \"unknown\" - it must\nnot be read as \"not deleted\".\n","type":"boolean"},"name":{"description":"Display name of the node","type":"string"},"packageType":{"description":"Package type (for registries/packages)","type":"string"},"path":{"description":"Full path to this node","type":"string"},"type":{"description":"Type of the node","enum":["registry","folder","package","version","file"],"type":"string"}},"required":["id","name","type","hasChildren"],"type":"object"},"TreePaginationV3":{"description":"Pagination information for tree view","properties":{"hasMore":{"description":"Whether there are more pages","type":"boolean"},"nextCursor":{"description":"Cursor for next page (base64 encoded)","type":"string"},"size":{"description":"Page size","format":"int32","type":"integer"},"total":{"description":"Total number of items matching the request across all pages, independent of\npagination.\n\nExact at the root (registry) level, where the filtered set is small enough to\ncount cheaply. Below the root it is **capped** (currently at 1000): child fanout\nis unbounded, and an exact count of a wide parent is far more expensive than the\npage itself. A value at the cap means \"at least this many\", not necessarily\nexact - use `hasMore` to drive \"Load More\" rather than comparing against `total`.\n\nOptional, and **absent on root-level pages fetched with a `cursor`**: the total\ndoes not change while paging through a fixed filter set, so it is computed once on\nthe first page and the client is expected to hold it across Load More.\n","format":"int64","type":"integer"}},"required":["size","hasMore"],"type":"object"},"ErrorV3":{"description":"An error response","properties":{"error":{"$ref":"#/components/schemas/ApiErrorsV3"}},"required":["error"],"type":"object"},"ApiErrorsV3":{"properties":{"code":{"description":"For some errors that could be handled programmatically, a short string indicating the [error code](https://docs.stripe.com/error-codes) reported.","maxLength":5000,"type":"string"},"message":{"description":"A human-readable message providing more details about the error. These messages can be shown to users.","maxLength":40000,"type":"string"},"param":{"description":"If the error is parameter-specific, the parameter related to the error. For example, we can use this to display a message near the correct form field.","maxLength":5000,"type":"string"},"type":{"description":"The type of error returned.","enum":["INVALID_REQUEST_ERROR","AUTHENTICATION_ERROR","PERMISSION_ERROR","API_ERROR"],"type":"string"}},"required":["type"],"title":"APIErrors","type":"object"}}}}
```

## List tree roots (registries)

> Lists all registries at the root level with optional search and filters.\
> Returns a hierarchical view of registries for tree navigation.\
> \
> \`scope\` is only accepted here, and is resolved exactly as it is for\
> \`ListRegistriesV3\`: the current space, plus its ancestors or descendants. It has no\
> equivalent on the levels below, because those are already bounded to the single\
> registry named in the path.<br>

```json
{"openapi":"3.0.0","info":{"title":"Harness Artifact Registry API","version":"1.0.0"},"tags":[{"description":"V3 tree view endpoints for hierarchical navigation","name":"Registry V3 - Tree View"}],"servers":[{"url":"/api"}],"paths":{"/v3/tree/roots":{"get":{"description":"Lists all registries at the root level with optional search and filters.\nReturns a hierarchical view of registries for tree navigation.\n\n`scope` is only accepted here, and is resolved exactly as it is for\n`ListRegistriesV3`: the current space, plus its ancestors or descendants. It has no\nequivalent on the levels below, because those are already bounded to the single\nregistry named in the path.\n","operationId":"ListTreeRootsV3","parameters":[{"$ref":"#/components/parameters/AccountIdentifierV3"},{"$ref":"#/components/parameters/OrgIdentifierV3"},{"$ref":"#/components/parameters/ProjectIdentifierV3"},{"$ref":"#/components/parameters/RegistryScopeV3"},{"$ref":"#/components/parameters/TreeCursorParamV3"},{"$ref":"#/components/parameters/TreeSizeParamV3"},{"$ref":"#/components/parameters/TreeDeletedFilterParamV3"},{"description":"Search term to filter registries by name (case-insensitive substring match).\nSearch is supported at the root (registry) level only - there is no search across\nartifacts, images, versions or files, since that requires scanning unbounded\nsubtrees. Cross-node search is planned via the Elasticsearch-backed index.\n","in":"query","name":"search","schema":{"type":"string"}},{"description":"Filter by registry type","in":"query","name":"registry_type","schema":{"type":"string"}},{"description":"Filter by package type","in":"query","name":"package_type","schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/TreeResponseV3"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorV3"}}},"description":"Error response."}},"summary":"List tree roots (registries)","tags":["Registry V3 - Tree View"]}}},"components":{"parameters":{"AccountIdentifierV3":{"description":"Unique identifier for the Harness account.\n","in":"query","name":"account_identifier","required":true,"schema":{"type":"string"}},"OrgIdentifierV3":{"description":"Unique identifier for the organization within the account.\n\nExample: `default` or `engineering_org`\n","in":"query","name":"org_identifier","schema":{"type":"string"}},"ProjectIdentifierV3":{"description":"Unique identifier for the project within the organization.\n\nExample: `my_project` or `frontend_services`\n","in":"query","name":"project_identifier","schema":{"type":"string"}},"RegistryScopeV3":{"description":"**Scope of registries to list**\n* **none** – current space only (default)   * **ancestors** – current space **plus** all parent spaces   * **descendants** – current space **plus** all child spaces  \nIf omitted, `none` is assumed.\n","in":"query","name":"scope","schema":{"enum":["ancestors","descendants","none"],"type":"string"}},"TreeCursorParamV3":{"description":"Cursor for pagination in tree view endpoints.\nBase64-encoded JSON containing pagination state.\n","in":"query","name":"cursor","schema":{"type":"string"}},"TreeSizeParamV3":{"description":"Number of items to return per page in tree view.\n","in":"query","name":"size","schema":{"default":50,"maximum":1000,"minimum":1,"type":"integer"}},"TreeDeletedFilterParamV3":{"description":"Filter for deleted items in tree view. Applied at the root (registry) level only,\nwhere `registries.registry_deleted_at` is authoritative. Levels below the root always\nreturn every node regardless of soft-delete state - use `isDeleted` on each node to\nrender deleted state. See TreeNodeItemV3.isDeleted for why per-node filtering is not\nsupported yet.\n","in":"query","name":"deleted_filter","schema":{"default":"exclude_deleted","enum":["exclude_deleted","include_deleted","only_deleted"],"type":"string"}}},"responses":{"TreeResponseV3":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TreeResponseBodyV3"}}},"description":"Response for tree view endpoints"}},"schemas":{"TreeResponseBodyV3":{"description":"Response body for tree view endpoints","properties":{"items":{"description":"List of tree nodes","items":{"$ref":"#/components/schemas/TreeNodeItemV3"},"type":"array"},"pagination":{"$ref":"#/components/schemas/TreePaginationV3"}},"required":["items","pagination"]},"TreeNodeItemV3":{"description":"A node in the tree view representing a registry, package, version, folder, or file","properties":{"createdAt":{"description":"Creation timestamp in milliseconds","format":"int64","type":"integer"},"deletedAt":{"description":"Deletion timestamp in milliseconds (if soft-deleted)","format":"int64","type":"integer"},"hasChildren":{"description":"Whether this node has child nodes","type":"boolean"},"id":{"description":"Unique identifier (UUID for nodes, registry_id for root registries)","type":"string"},"isDeleted":{"description":"Whether this node is soft-deleted. Tree levels below the root return both active and\nsoft-deleted nodes, so clients must use this flag to render deleted state rather than\nassuming every returned node is live.\n\nOmitted when soft-delete state cannot be determined for the node's level: the version\nand platform levels of OCI (Docker/Helm) registries come from\n`tags`/`manifests`/`manifest_references`, none of which have a soft-delete column,\nand all nodes of non-OCI registries come from `nodes`, whose `node_deleted_at` column\nis not populated by any write path. Only the root (`registries`) and Docker/Helm\npackage (`images`) levels can answer this. An omitted value means \"unknown\" - it must\nnot be read as \"not deleted\".\n","type":"boolean"},"name":{"description":"Display name of the node","type":"string"},"packageType":{"description":"Package type (for registries/packages)","type":"string"},"path":{"description":"Full path to this node","type":"string"},"type":{"description":"Type of the node","enum":["registry","folder","package","version","file"],"type":"string"}},"required":["id","name","type","hasChildren"],"type":"object"},"TreePaginationV3":{"description":"Pagination information for tree view","properties":{"hasMore":{"description":"Whether there are more pages","type":"boolean"},"nextCursor":{"description":"Cursor for next page (base64 encoded)","type":"string"},"size":{"description":"Page size","format":"int32","type":"integer"},"total":{"description":"Total number of items matching the request across all pages, independent of\npagination.\n\nExact at the root (registry) level, where the filtered set is small enough to\ncount cheaply. Below the root it is **capped** (currently at 1000): child fanout\nis unbounded, and an exact count of a wide parent is far more expensive than the\npage itself. A value at the cap means \"at least this many\", not necessarily\nexact - use `hasMore` to drive \"Load More\" rather than comparing against `total`.\n\nOptional, and **absent on root-level pages fetched with a `cursor`**: the total\ndoes not change while paging through a fixed filter set, so it is computed once on\nthe first page and the client is expected to hold it across Load More.\n","format":"int64","type":"integer"}},"required":["size","hasMore"],"type":"object"},"ErrorV3":{"description":"An error response","properties":{"error":{"$ref":"#/components/schemas/ApiErrorsV3"}},"required":["error"],"type":"object"},"ApiErrorsV3":{"properties":{"code":{"description":"For some errors that could be handled programmatically, a short string indicating the [error code](https://docs.stripe.com/error-codes) reported.","maxLength":5000,"type":"string"},"message":{"description":"A human-readable message providing more details about the error. These messages can be shown to users.","maxLength":40000,"type":"string"},"param":{"description":"If the error is parameter-specific, the parameter related to the error. For example, we can use this to display a message near the correct form field.","maxLength":5000,"type":"string"},"type":{"description":"The type of error returned.","enum":["INVALID_REQUEST_ERROR","AUTHENTICATION_ERROR","PERMISSION_ERROR","API_ERROR"],"type":"string"}},"required":["type"],"title":"APIErrors","type":"object"}}}}
```
