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

# Dashboard Query

> TypeScript API reference for Netra Dashboard queries. Fetch metrics, session summaries, and usage data programmatically with the dashboard query API.

The Netra SDK exposes a `dashboard` client that lets you perform dashboard queries and retrieve relevant data programmatically.

This page shows how to use `netra.dashboard` to craft dashboard queries, fetch session summaries, and retrieve session statistics.

## Getting Started

The `dashboard` client is available on the main `Netra` entry point after initialization.

```typescript theme={null}
import { Netra } from "netra-sdk-js";

const client = new Netra({
  apiKey: "your-api-key",
});

// Access the dashboard client
await client.dashboard.queryData(...);
await client.dashboard.getSessionSummary(...);
await client.dashboard.getSessionStats(...);
```

***

## queryData

Fetch dashboard data with customizable metrics, dimensions, and filters. This method supports various chart types and aggregation strategies.

<CodeGroup>
  ```typescript Usage theme={null}
  import { Netra } from "netra-sdk-js";
  import {
    Scope,
    ChartType,
    Measure,
    Aggregation,
    DimensionField,
    GroupBy,
    FilterField,
    Operator,
    FilterType,
  } from "netra-sdk-js/api/dashboard";

  const client = new Netra({ apiKey: "..." });

  const result = await client.dashboard.queryData({
    scope: Scope.SPANS,
    chartType: ChartType.LINE_TIME_SERIES,
    metrics: {
      measure: Measure.TOTAL_COST,
      aggregation: Aggregation.TOTAL_COUNT,
    },
    dimension: {
      field: DimensionField.SERVICE,
    },
    filter: {
      startTime: "2026-01-10T00:00:00.000Z",
      endTime: "2026-01-14T23:59:59.000Z",
      groupBy: GroupBy.DAY,
      filters: [
        {
          field: FilterField.ENVIRONMENT,
          operator: Operator.EQUALS,
          type: FilterType.STRING,
          value: "production",
        },
      ],
    },
  });

  console.log(result);
  ```

  ```typescript Signature theme={null}
  queryData(params: QueryDataParams): Promise<QueryResponse | null>

  // QueryDataParams interface
  interface QueryDataParams {
    scope: Scope;
    chartType: ChartType;
    metrics: Metrics;
    filter: FilterConfig;
    dimension?: Dimension;
  }
  ```
</CodeGroup>

### Parameters

| Parameter   | Type           | Description                                            |
| ----------- | -------------- | ------------------------------------------------------ |
| `scope`     | `Scope`        | Scope of data to query (`SPANS` or `TRACES`)           |
| `chartType` | `ChartType`    | Chart visualization type (controls the response shape) |
| `metrics`   | `Metrics`      | Defines what metric to compute and how to aggregate it |
| `filter`    | `FilterConfig` | Filter configuration constraining the query            |
| `dimension` | `Dimension?`   | Optional grouping to split results by a dimension      |

### Enums and Types

<AccordionGroup>
  <Accordion icon="bullseye" title="Scope">
    | Value          | Description                       |
    | -------------- | --------------------------------- |
    | `Scope.SPANS`  | Query individual span-level data  |
    | `Scope.TRACES` | Query trace-level aggregated data |
  </Accordion>

  <Accordion icon="chart-line" title="ChartType">
    | Value                        | Description          |
    | ---------------------------- | -------------------- |
    | `ChartType.LINE_TIME_SERIES` | Line chart over time |
    | `ChartType.BAR_TIME_SERIES`  | Bar chart over time  |
    | `ChartType.HORIZONTAL_BAR`   | Horizontal bar chart |
    | `ChartType.VERTICAL_BAR`     | Vertical bar chart   |
    | `ChartType.PIE`              | Pie chart            |
    | `ChartType.NUMBER`           | Single numeric value |
  </Accordion>

  <Accordion icon="calculator" title="Metrics">
    The `Metrics` object defines what to measure and how to aggregate.

    **Measure:**

    | Value                     | Description             |
    | ------------------------- | ----------------------- |
    | `Measure.LATENCY`         | Request latency         |
    | `Measure.ERROR_RATE`      | Error rate percentage   |
    | `Measure.PII_COUNT`       | Count of PII detections |
    | `Measure.REQUEST_COUNT`   | Number of requests      |
    | `Measure.TOTAL_COST`      | Total cost in USD       |
    | `Measure.VIOLATIONS`      | Policy violations count |
    | `Measure.TOTAL_TOKENS`    | Total token usage       |
    | `Measure.AUDIO_DURATION`  | Audio Duration          |
    | `Measure.CHARACTER_COUNT` | Character Count         |
    | `Measure.TTFT`            | Time to First Token     |

    **Aggregation:**

    | Value                     | Description            |
    | ------------------------- | ---------------------- |
    | `Aggregation.AVERAGE`     | Mean value             |
    | `Aggregation.P50`         | 50th percentile        |
    | `Aggregation.P90`         | 90th percentile        |
    | `Aggregation.P95`         | 95th percentile        |
    | `Aggregation.P99`         | 99th percentile        |
    | `Aggregation.MEDIAN`      | Median value           |
    | `Aggregation.PERCENTAGE`  | Percentage calculation |
    | `Aggregation.TOTAL_COUNT` | Sum total              |
  </Accordion>

  <Accordion icon="filter" title="FilterConfig">
    | Field       | Type        | Description                                                             |
    | ----------- | ----------- | ----------------------------------------------------------------------- |
    | `startTime` | `string`    | Start of time window (ISO 8601 UTC, e.g., `"2026-01-10T00:00:00.000Z"`) |
    | `endTime`   | `string`    | End of time window (ISO 8601 UTC)                                       |
    | `groupBy`   | `GroupBy`   | Time bucket size: `DAY`, `HOUR`, or `MINUTE`                            |
    | `filters`   | `Filter[]?` | Optional list of filter conditions                                      |
  </Accordion>

  <Accordion icon="filter-list" title="Filter">
    | Field      | Type          | Description                                   |                    |
    | ---------- | ------------- | --------------------------------------------- | ------------------ |
    | `field`    | \`FilterField | string\`                                      | Field to filter on |
    | `operator` | `Operator`    | Comparison operator                           |                    |
    | `type`     | `FilterType`  | Value type                                    |                    |
    | `value`    | `any`         | Value to compare against                      |                    |
    | `key`      | `string?`     | Required only for `FilterType.OBJECT` filters |                    |

    **FilterField values:** `TOTAL_COST`, `SERVICE`, `TENANT_ID`, `USER_ID`, `SESSION_ID`, `ENVIRONMENT`, `LATENCY`, `MODEL_NAME` (Spans only), `MODELS` (Traces only), `METADATA`

    **Operator values:** `EQUALS`, `NOT_EQUALS`, `CONTAINS`, `NOT_CONTAINS`, `STARTS_WITH`, `ENDS_WITH`, `GREATER_THAN`, `LESS_THAN`, `GREATER_EQUAL_TO`, `LESS_EQUAL_TO`, `ANY_OF`, `NONE_OF`

    **FilterType values:** `STRING`, `NUMBER`, `BOOLEAN`, `ARRAY_OPTIONS`, `OBJECT`
  </Accordion>

  <Accordion icon="layer-group" title="Dimension">
    | Field   | Type             | Description       |
    | ------- | ---------------- | ----------------- |
    | `field` | `DimensionField` | Field to group by |

    **DimensionField values:**

    | Value                        | Supported Scopes |
    | ---------------------------- | ---------------- |
    | `DimensionField.ENVIRONMENT` | Spans, Traces    |
    | `DimensionField.SERVICE`     | Spans only       |
    | `DimensionField.MODEL_NAME`  | Spans only       |
  </Accordion>
</AccordionGroup>

<Note>
  If the query scope is `Scope.TRACES`, only `DimensionField.ENVIRONMENT` is supported. The `Scope.SPANS` supports all dimension fields.
</Note>

***

## getSessionSummary

Retrieve aggregated session metrics including total sessions, costs, latency, and cost breakdown by model.

<CodeGroup>
  ```typescript Usage theme={null}
  import { Netra } from "netra-sdk-js";
  import {
    SessionFilterField,
    SessionOperator,
    SessionFilterType,
  } from "netra-sdk-js/api/dashboard";

  const client = new Netra({ apiKey: "..." });

  const result = await client.dashboard.getSessionSummary({
    startTime: "2026-01-01T00:00:00.000Z",
    endTime: "2026-01-31T23:59:59.000Z",
    filters: [
      {
        field: SessionFilterField.TENANT_ID,
        operator: SessionOperator.ANY_OF,
        type: SessionFilterType.ARRAY,
        value: ["Unilever", "AceTech"],
      },
    ],
  });

  console.log(result);
  ```

  ```typescript Signature theme={null}
  getSessionSummary(filter: SessionFilterConfig): Promise<any | null>

  // SessionFilterConfig interface
  interface SessionFilterConfig {
    startTime: string;
    endTime: string;
    filters?: SessionFilter[];
  }
  ```
</CodeGroup>

### Parameters

| Parameter | Type                  | Description                        |
| --------- | --------------------- | ---------------------------------- |
| `filter`  | `SessionFilterConfig` | Filter configuration for the query |

### SessionFilterConfig

| Field       | Type               | Description                         |
| ----------- | ------------------ | ----------------------------------- |
| `startTime` | `string`           | Start of time window (ISO 8601 UTC) |
| `endTime`   | `string`           | End of time window (ISO 8601 UTC)   |
| `filters`   | `SessionFilter[]?` | Optional list of filter conditions  |

### SessionFilter (Optional)

| Field      | Type                 | Description                 |
| ---------- | -------------------- | --------------------------- |
| `field`    | `SessionFilterField` | Supports `TENANT_ID`        |
| `operator` | `SessionOperator`    | Currently supports `ANY_OF` |
| `type`     | `SessionFilterType`  | Currently supports `ARRAY`  |
| `value`    | `string[]`           | List of values to match     |

\| `value` | `string[]` | List of values to match |

### Response

```json theme={null}
{
  "timeRange": {
    "startTime": "2026-01-01T00:00:00.000Z",
    "endTime": "2026-01-31T23:59:59.000Z"
  },
  "data": {
    "totalSessions": 207,
    "totalCost": 0.041807,
    "avgCostPerSession": 0.000202,
    "avgLatencyMs": 8689.83,
    "costByModel": [
      {
        "model": "gpt-4o-mini",
        "cost": 0.041807
      }
    ]
  }
}
```

***

## getSessionStats

Fetch a paginated list of sessions with individual session metrics including request count, cost, and duration.

<CodeGroup>
  ```typescript Usage theme={null}
  import { Netra } from "netra-sdk-js";
  import {
    SessionFilterField,
    SessionOperator,
    SessionFilterType,
    SortField,
    SortOrder,
  } from "netra-sdk-js/api/dashboard";

  const client = new Netra({ apiKey: "..." });

  const sessionStats = await client.dashboard.getSessionStats(
    "2026-01-01T00:00:00.000Z", // startTime
    "2026-01-31T23:59:59.000Z", // endTime
    10,                         // limit
    [                           // filters
      {
        field: SessionFilterField.TENANT_ID,
        operator: SessionOperator.ANY_OF,
        type: SessionFilterType.ARRAY,
        value: ["Unilever", "AceTech"],
      },
    ],
    undefined,                  // cursor
    SortField.START_TIME,       // sortField
    SortOrder.DESC              // sortOrder
  );

  if (sessionStats) {
    console.log(sessionStats.data);

    // Pagination
    if (sessionStats.hasNextPage && sessionStats.nextCursor) {
      const nextPage = await client.dashboard.getSessionStats(
        "2026-01-01T00:00:00.000Z",
        "2026-01-31T23:59:59.000Z",
        10,
        [
          {
            field: SessionFilterField.TENANT_ID,
            operator: SessionOperator.ANY_OF,
            type: SessionFilterType.ARRAY,
            value: ["Unilever", "AceTech"],
          },
        ],
        sessionStats.nextCursor,
        SortField.START_TIME,
        SortOrder.DESC
      );
      console.log(nextPage?.data);
    }
  }
  ```

  ```typescript Signature theme={null}
  getSessionStats(
    startTime: string,
    endTime: string,
    limit?: number,
    filters?: SessionFilter[],
    cursor?: string,
    sortField?: SortField,
    sortOrder?: SortOrder
  ): Promise<SessionStatsResult | null>
  ```
</CodeGroup>

### Parameters

| Parameter   | Type               | Description                            |
| ----------- | ------------------ | -------------------------------------- |
| `startTime` | `string`           | Start of time window (ISO 8601 UTC)    |
| `endTime`   | `string`           | End of time window (ISO 8601 UTC)      |
| `limit`     | `number?`          | Maximum results per page (default: 10) |
| `filters`   | `SessionFilter[]?` | Optional filter conditions             |
| `cursor`    | `string?`          | Pagination cursor from previous page   |
| `sortField` | `SortField?`       | Field to sort by                       |
| `sortOrder` | `SortOrder?`       | Sort direction                         |

### Sorting Options

<AccordionGroup>
  <Accordion icon="arrow-down-a-z" title="SortField">
    | Value                      | Description                |
    | -------------------------- | -------------------------- |
    | `SortField.SESSION_ID`     | Sort by session ID         |
    | `SortField.START_TIME`     | Sort by session start time |
    | `SortField.TOTAL_REQUESTS` | Sort by request count      |
    | `SortField.TOTAL_COST`     | Sort by total cost         |
  </Accordion>

  <Accordion icon="arrow-up-down" title="SortOrder">
    | Value            | Description      |
    | ---------------- | ---------------- |
    | `SortOrder.ASC`  | Ascending order  |
    | `SortOrder.DESC` | Descending order |
  </Accordion>
</AccordionGroup>

### Response

```json theme={null}
{
  "data": [
    {
      "sessionId": "00973697-f64b-4144-a42d-6845f5d149e4",
      "sessionStartTime": "2026-01-22 09:54:51.210",
      "totalRequests": 1,
      "totalCost": 0.0000885,
      "sessionDuration": "3.15s",
      "cursor": "MjAyNi0wMS0yMiAwOTo1NDo1MS4yMTB8MDA5NzM2OTctZjY0Yi00MTQ0LWE0MmQtNjg0NWY1ZDE0OWU0"
    },
    {
      "sessionId": "48827b92-24fa-4278-b559-a982d1ddee96",
      "sessionStartTime": "2026-01-22 09:54:47.563",
      "totalRequests": 1,
      "totalCost": 0.00012465,
      "sessionDuration": "3.65s",
      "cursor": "MjAyNi0wMS0yMiAwOTo1NDo0Ny41NjN8NDg4MjdiOTItMjRmYS00Mjc4LWI1NTktYTk4MmQxZGRlZTk2"
    }
  ],
  "hasNextPage": true,
  "nextCursor": "MjAyNi0wMS0yMiAwOTo1MzoyNy4xNjN8ODMzNmQwOTYtZjNiNS00ZTk5LWE1ZjEtYTk2OTkxMjlmNDFh"
}
```

***

## iterSessionStats

Stream over all pages of session stats until completion. This iterator handles pagination automatically.

<CodeGroup>
  ```typescript Usage theme={null}
  import { Netra } from "netra-sdk-js";
  import {
    SessionFilterField,
    SessionOperator,
    SessionFilterType,
    SortField,
    SortOrder,
  } from "netra-sdk-js/api/dashboard";

  const client = new Netra({ apiKey: "..." });

  const iterator = client.dashboard.iterSessionStats(
    "2026-01-01T00:00:00.000Z",
    "2026-01-31T23:59:59.000Z",
    [
      {
        field: SessionFilterField.TENANT_ID,
        operator: SessionOperator.ANY_OF,
        type: SessionFilterType.ARRAY,
        value: ["Unilever", "AceTech"],
      },
    ],
    SortField.START_TIME,
    SortOrder.DESC
  );

  for await (const session of iterator) {
    console.log(session);
  }
  ```

  ```typescript Signature theme={null}
  iterSessionStats(
    startTime: string,
    endTime: string,
    filters?: SessionFilter[],
    sortField?: SortField,
    sortOrder?: SortOrder
  ): AsyncGenerator<SessionStatsData, void, unknown>
  ```
</CodeGroup>

### Parameters

| Parameter   | Type               | Description                         |
| ----------- | ------------------ | ----------------------------------- |
| `startTime` | `string`           | Start of time window (ISO 8601 UTC) |
| `endTime`   | `string`           | End of time window (ISO 8601 UTC)   |
| `filters`   | `SessionFilter[]?` | Optional filter conditions          |
| `sortField` | `SortField?`       | Field to sort by                    |
| `sortOrder` | `SortOrder?`       | Sort direction                      |

### Response

```json theme={null}
{
  "sessionId": "sess_abc123def456",
  "startTime": "2026-01-15T10:23:45.000Z",
  "totalRequests": 12,
  "totalCost": 0.0347,
  "sessionDuration": "4m 32s",
  "cursor": "eyJzZXNzaW9uX2lkIjoic2Vzc19hYmMxMjNkZWY0NTYifQ=="
}
{
  "sessionId": "sess_xyz789ghi012",
  "startTime": "2026-01-14T08:15:30.000Z",
  "totalRequests": 5,
  "totalCost": 0.0123,
  "sessionDuration": "1m 15s",
  "cursor": "eyJzZXNzaW9uX2lkIjoic2Vzc194eXo3ODlnaGkwMTIifQ=="
}
{
  "sessionId": "sess_mno345pqr678",
  "startTime": "2026-01-12T14:50:10.000Z",
  "totalRequests": 28,
  "totalCost": 0.0891,
  "sessionDuration": "12m 08s",
  "cursor": "eyJzZXNzaW9uX2lkIjoic2Vzc19tbm8zNDVwcXI2NzgifQ=="
}
```

<Tip>
  Use `iterSessionStats` when you need to process all sessions without manually handling pagination. The iterator fetches pages on-demand as you iterate.
</Tip>

***

## Complete Example

```typescript theme={null}
import { Netra } from "netra-sdk-js";
import {
  Scope,
  ChartType,
  Measure,
  Aggregation,
  DimensionField,
  GroupBy,
  SessionFilterField,
  SessionOperator,
  SessionFilterType,
  SortField,
  SortOrder,
} from "netra-sdk-js/api/dashboard";

async function main() {
  // Initialize the SDK
  const client = new Netra({
    apiKey: "your-api-key",
  });

  // Query cost trends over time
  const costTrends = await client.dashboard.queryData({
    scope: Scope.SPANS,
    chartType: ChartType.LINE_TIME_SERIES,
    metrics: {
      measure: Measure.TOTAL_COST,
      aggregation: Aggregation.TOTAL_COUNT,
    },
    dimension: {
      field: DimensionField.SERVICE,
    },
    filter: {
      startTime: "2026-01-01T00:00:00.000Z",
      endTime: "2026-01-31T23:59:59.000Z",
      groupBy: GroupBy.DAY,
    },
  });

  // Get session summary for specific tenants
  const summary = await client.dashboard.getSessionSummary({
    startTime: "2026-01-01T00:00:00.000Z",
    endTime: "2026-01-31T23:59:59.000Z",
    filters: [
      {
        field: SessionFilterField.TENANT_ID,
        operator: SessionOperator.ANY_OF,
        type: SessionFilterType.ARRAY,
        value: ["TenantA", "TenantB"],
      },
    ],
  });

  // Iterate through all sessions
  const iterator = client.dashboard.iterSessionStats(
    "2026-01-01T00:00:00.000Z",
    "2026-01-31T23:59:59.000Z",
    undefined,
    SortField.TOTAL_COST,
    SortOrder.DESC
  );

  for await (const session of iterator) {
    console.log(
      `Session ${session.session_id}: $${session.totalCost.toFixed(4)}`
    );
  }
}

main();
```

## Next Steps

* [Usage Utilities](/usage/usage-utilities) - Query token usage and trace data
* [TypeScript SDK Reference](/sdk-reference/sdk/typescript) - Complete SDK documentation
* [Custom Dashboard](/Dashboard/Custom-dashboard) - Build custom dashboards
