---
name: clinic-cluster-metadata
description: |
  Query canonical Data Proxy cluster metadata, DBAAS-org lists/details, and supported-tier components/topology.
---

# Cluster metadata API

Choose the metadata helper by the requested capability. Shell helpers live in `cluster-metadata/scripts/clinic-cluster.sh` and are loaded by `source scripts/clinic-shell.sh`.

## ID contract

| ID | Meaning | Canonical use |
|----|---------|---------------|
| logical `clusterID` | TiDB Cloud logical cluster ID | Normal `{clusterID}` path segment; accepted by BYOC logs, metrics, Slow Query, Top SQL, and live Statements |
| physical BYOC ID | Parent `byoc-host` cluster ID | Accepted by BYOC diagnostic routes; required by canonical BYOC Continuous Profiling inventory |
| DBAAS org ID | TiDB Cloud organization ID | `{orgID}` in `/data-proxy/api/v1/orgs/{orgID}/...` |
| legacy Dashboard `tenantID` | The same DBAAS org identity in the legacy Dashboard response | May be used as canonical `{orgID}` |
| legacy Dashboard `orgID` | Clinic-internal database ID | Legacy Clinic paths only; never use in a canonical path |
| `diagnosticContext.parentId` / `parentID` | Physical parent ID when present | Resolve a logical BYOC cluster to its physical namespace/target for infra metrics and profiling inventory |

`clinic_get_cluster_by_id` returns canonical metadata and is the preferred way to resolve a known cluster. Its `orgId` field is the DBAAS org ID.

```bash
source scripts/clinic-shell.sh
get_clinic_auth

CLUSTER_ID="1234567890123456789"
METADATA=$(clinic_get_cluster_by_id "$CLUSTER_ID")
DBAAS_ORG_ID=$(printf '%s' "$METADATA" | jq -r '.orgId')
PHYSICAL_CLUSTER_ID=$(printf '%s' "$METADATA" | jq -r '.diagnosticContext.parentId // .parentId // empty')
```

For BYOC, keep both IDs instead of treating them as interchangeable. Most canonical diagnosis routes accept either. Data-plane PromQL should use namespace `tidb${PHYSICAL_CLUSTER_ID}`, and canonical Continuous Profiling requires the physical ID. See `../byoc-diagnostics/SUBSKILL.md`.

## Endpoints and helpers

### Exact cluster metadata

```text
GET /data-proxy/api/v1/clusters/{clusterID}
```

This global/internal lookup does not add a fake org path parameter. Use it when an exact logical or physical BYOC cluster ID is known:

```bash
clinic_get_cluster_by_id "$CLUSTER_ID"

curl --fail-with-body \
  -H "Authorization: Bearer ${CLINIC_API_KEY}" \
  "${CLINIC_ENDPOINT}/data-proxy/api/v1/clusters/${CLUSTER_ID}"
```

### List clusters in an org

```text
GET /data-proxy/api/v1/orgs/{orgID}/clusters
```

Optional query parameters are `page` (default `1`), `pageSize` (default `50`), `query`, `showDeleted` (default `false`), and `include_total` (default `false`). By default, the response omits `total` and returns `has_more`: `{"items":[],"page":1,"pageSize":50,"has_more":false}`.

```bash
clinic_list_clusters "$DBAAS_ORG_ID" "prod" "false" 50 1

curl --fail-with-body --get \
  -H "Authorization: Bearer ${CLINIC_API_KEY}" \
  --data-urlencode 'page=1' \
  --data-urlencode 'pageSize=50' \
  --data-urlencode 'showDeleted=false' \
  --data-urlencode 'include_total=false' \
  "${CLINIC_ENDPOINT}/data-proxy/api/v1/orgs/${DBAAS_ORG_ID}/clusters"
```

Page until `has_more` is `false`. Request `include_total=true` only when the exact number of matching clusters is explicitly required; counted responses include `total` instead of `has_more`.

The canonical `query` searches cluster names or IDs inside this one org. It does not search tenant names/IDs and does not accept provider, region, status, version, deployment-type, tenant-plan, control-plane, or sort filters. Do not pass those parameters to this endpoint: unknown query parameters are currently ignored rather than rejected. For a known cluster ID, prefer the exact endpoint above. Do not request the exact total merely to drive pagination.

### Global discovery and advanced filters

Use `clinic_search_clusters` when the user asks to discover clusters across orgs, search by tenant, or filter server-side by any advanced dimension. It calls `GET /clinic/api/v1/dashboard/clusters2`.

```bash
# Find active AWS Essential V2 clusters.
clinic_search_clusters \
  --provider aws \
  --deploy-type-v2 "essential v2" \
  --cluster-status active \
  --show-deleted false \
  --limit 50 \
  --page 1

# Repeat a flag to express OR within one dimension.
clinic_search_clusters \
  --provider aws \
  --provider gcp \
  --deploy-type-v2 premium \
  --deploy-type-v2 "premium reserved" \
  --limit 50 \
  --page 1
```

Supported options are `--query`, `--show-deleted`, repeatable `--cluster-id`, `--cluster-status`, `--cluster-version`, `--deploy-type`, `--deploy-type-v2`, `--tenant-plan`, `--control-plane`, `--provider`, and `--region`, plus `--sort`, `--order`, `--limit`, `--page`, and `--include-total`. Different dimensions combine with AND; repeated values within one dimension use the backend's IN/OR semantics. Use the exact stored values, including spaces in values such as `essential v2`.

`--sort` accepts `clusterCreatedAt`, `clusterDeletedAt`, or `clusterDuration`; the default is creation time. `--order ascend` selects ascending order, while omission uses descending order. Therefore an unqualified “first page” is the newest matching clusters by creation time.

The helper explicitly sends `include_total=false` by default. The response omits `total` and returns `has_more`; paginate until the requested result count is satisfied or `has_more` is `false`. Pass `--include-total true` only when the caller explicitly needs the exact matching count; that response includes `total`. Filter or summarize response fields such as `clusterID`, `tenantID`, `clusterProviderName`, `clusterDeployTypeV2`, `clusterStatus`, and `clusterRegionName`; do not assume canonical field names on discovery rows.

Python callers can use the same route-neutral intent:

```python
rows = api.search_clusters(
    providers=["aws"],
    deploy_types_v2=["essential v2"],
    cluster_statuses=["active"],
    limit=50,
)
```

Python also defaults `include_total=False`. Pass `include_total=True` only for an explicit exact-count request.

### Org-owned cluster detail

```text
GET /data-proxy/api/v1/orgs/{orgID}/clusters/{clusterID}
```

This route verifies that the cluster belongs to the DBAAS org.

```bash
clinic_get_cluster "$DBAAS_ORG_ID" "$CLUSTER_ID"
```

Use detail metadata for name, status, provider, region, project, deployment type, and version. Use components for node/resource topology.

### Components and topology

```text
GET /data-proxy/api/v1/orgs/{orgID}/clusters/{clusterID}/components
```

```bash
clinic_get_components "$DBAAS_ORG_ID" "$CLUSTER_ID"

# Convenience: resolves canonical orgId and rejects unsupported shared tiers.
clinic_get_topology "$CLUSTER_ID"
```

The successful response is a component array. Common fields include:

| Field | Meaning |
|-------|---------|
| `component_type` | `pd`, `tidb`, `tikv`, `tiflash`, and other available component types |
| `node_count`, `min_node_count`, `max_node_count` | Current/configured node counts |
| `cpu`, `memory_gi` | Per-node resources |
| `version`, `image.tag` | Version/runtime image information |
| `storages[]` | Storage type, size, IOPS, or throughput when available |

Topology is available for Dedicated, resource-pool, Premium, and BYOC variants when the backend exposes components. It is not available for `shared`, `starter`, or `essential`; use metadata plus metrics/logs instead.

The compatibility function name `clinic_get_resource_pool_components` now delegates to canonical `clinic_get_components`.

## Legacy compatibility

Old caller contracts remain available. Skill workflows normally use the route-neutral discovery helper above instead of selecting this transport directly:

- `GET /clinic/api/v1/dashboard/clusters2` (global/advanced discovery and the historical exact-ID compatibility helper; `include_total=false` by default)
- `GET /clinic/api/v1/orgs/{clinicInternalOrgID}/clusters/{clusterID}`
- `GET /clinic/api/v1/orgs/{clinicInternalOrgID}/clusters/{clusterID}/resource-pool/components`

Explicit helpers are `clinic_legacy_search_clusters`, `clinic_legacy_search_cluster_by_id`, `clinic_legacy_get_cluster`, `clinic_legacy_get_cluster_by_id`, `clinic_legacy_get_resource_pool_components`, and `clinic_legacy_get_topology`. `clinic_search_clusters` is the public capability helper for global/advanced discovery and hides its compatibility transport. Historical `clinic_search_cluster_by_id` remains available for NGM context discovery; use canonical `clinic_get_cluster_by_id` for ordinary exact metadata.

The legacy `{clinicInternalOrgID}` is Dashboard `orgID`; it is unrelated to the canonical org path value except that both records describe the same tenant context.
