> ## 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.

# Usage & Traces

> Query token usage, costs, traces and spans using the Netra Usage API

The Netra SDK exposes a `usage` client that lets you query:

* **Session-level usage** - tokens, requests, and cost per session
* **Tenant-level usage** - aggregated metrics across a tenant
* **Traces** - list and iterate through traces within a time range
* **Spans** - drill into individual spans for a given trace

This page shows how to use `netra.usage` to retrieve usage and tracing data and how to work efficiently with pagination.

## Getting Started

The `usage` 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 usage client
await client.usage.getSessionUsage(...);
await client.usage.getTenantUsage(...);
await client.usage.listTraces(...);
await client.usage.listSpansByTraceId(...);
```

***

## getSessionUsage

Fetch usage metrics for a single session between a start and end time.

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

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

  const sessionUsage = await client.usage.getSessionUsage(
    "b8a359f8-f28c-4e88-839f-c5db103e9943", // sessionId
    "2026-01-01T00:00:00.000Z",             // startTime
    "2026-01-31T23:59:59.000Z"              // endTime
  );

  if (sessionUsage) {
    console.log("Session:", sessionUsage.sessionId);
    console.log("Tokens:", sessionUsage.tokenCount);
    console.log("Requests:", sessionUsage.requestCount);
    console.log("Total cost (USD):", sessionUsage.totalCost);
  }
  ```

  ```typescript Signature theme={null}
  getSessionUsage(
    sessionId: string,
    startTime: string,
    endTime: string
  ): Promise<SessionUsageData | null>
  ```
</CodeGroup>

### Parameters

| Parameter   | Type     | Description                                                             |
| ----------- | -------- | ----------------------------------------------------------------------- |
| `sessionId` | `string` | Unique identifier of the session                                        |
| `startTime` | `string` | Start of time window (ISO 8601 UTC, e.g., `"2026-01-01T00:00:00.000Z"`) |
| `endTime`   | `string` | End of time window (ISO 8601 UTC)                                       |

### Response: SessionUsageData

| Field          | Type     | Description            |
| -------------- | -------- | ---------------------- |
| `sessionId`    | `string` | The session identifier |
| `tokenCount`   | `number` | Total tokens used      |
| `requestCount` | `number` | Number of requests     |
| `totalCost`    | `number` | Total cost in USD      |

***

## getTenantUsage

Fetch aggregated usage metrics for a tenant across all sessions.

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

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

  const tenantUsage = await client.usage.getTenantUsage(
    "AceTech",                  // tenantId
    "2026-01-01T00:00:00.000Z", // startTime
    "2026-01-31T23:59:59.000Z"  // endTime
  );

  if (tenantUsage) {
    console.log("Tenant:", tenantUsage.tenantId);
    console.log("Org:", tenantUsage.organisationId);
    console.log("Tokens:", tenantUsage.tokenCount);
    console.log("Requests:", tenantUsage.requestCount);
    console.log("Sessions:", tenantUsage.sessionCount);
    console.log("Total cost (USD):", tenantUsage.totalCost);
  }
  ```

  ```typescript Signature theme={null}
  getTenantUsage(
    tenantId: string,
    startTime: string,
    endTime: string
  ): Promise<TenantUsageData | null>
  ```
</CodeGroup>

### Parameters

| Parameter   | Type     | Description                                            |
| ----------- | -------- | ------------------------------------------------------ |
| `tenantId`  | `string` | Identifier of the tenant (e.g., customer organization) |
| `startTime` | `string` | Start of time window (ISO 8601 UTC)                    |
| `endTime`   | `string` | End of time window (ISO 8601 UTC)                      |

### Response: TenantUsageData

| Field            | Type     | Description             |
| ---------------- | -------- | ----------------------- |
| `tenantId`       | `string` | The tenant identifier   |
| `organisationId` | `string` | Organization identifier |
| `tokenCount`     | `number` | Total tokens used       |
| `requestCount`   | `number` | Number of requests      |
| `sessionCount`   | `number` | Number of sessions      |
| `totalCost`      | `number` | Total cost in USD       |

***

## listTraces

Query traces for a time range with optional filtering and pagination.

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

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

  const tracesPage = await client.usage.listTraces({
    startTime: "2026-01-01T00:00:00.000Z",
    endTime: "2026-01-31T23:59:59.000Z",
    tenantId: "AceTech",
    userId: "Jerina",
    sessionId: "b8a359f8-f28c-4e88-839f-c5db103e9943",
    limit: 10,
    // cursor: undefined,
    direction: "down",
    sortField: "start_time",
    sortOrder: "desc",
  });

  if (tracesPage) {
    for (const trace of tracesPage.traces) {
      console.log(trace.id, trace.name, trace.totalTokens, trace.totalCost);
    }

    console.log("Has next page?", tracesPage.hasNextPage);
    console.log("Next cursor:", tracesPage.nextCursor);

    // Pagination
    if (tracesPage.hasNextPage && tracesPage.nextCursor) {
      const nextPage = await client.usage.listTraces({
        startTime: "2026-01-01T00:00:00.000Z",
        endTime: "2026-01-31T23:59:59.000Z",
        tenantId: "AceTech",
        limit: 10,
        cursor: tracesPage.nextCursor,
        direction: "down",
      });
    }
  }
  ```

  ```typescript Signature theme={null}
  listTraces(params: ListTracesParams): Promise<TracesPage | null>

  // ListTracesParams interface
  interface ListTracesParams {
    startTime: string;
    endTime: string;
    traceId?: string;
    sessionId?: string;
    userId?: string;
    tenantId?: string;
    limit?: number;
    cursor?: string;
    direction?: "up" | "down";
    sortField?: string;
    sortOrder?: "asc" | "desc";
  }
  ```
</CodeGroup>

### Parameters (ListTracesParams)

| Parameter   | Type              | Description                              |
| ----------- | ----------------- | ---------------------------------------- |
| `startTime` | `string`          | Start of time range (ISO 8601 UTC)       |
| `endTime`   | `string`          | End of time range (ISO 8601 UTC)         |
| `traceId`   | `string?`         | Filter by trace ID                       |
| `sessionId` | `string?`         | Filter by session ID                     |
| `userId`    | `string?`         | Filter by user ID                        |
| `tenantId`  | `string?`         | Filter by tenant ID                      |
| `limit`     | `number?`         | Maximum traces per page                  |
| `cursor`    | `string?`         | Pagination cursor from previous page     |
| `direction` | `"up" \| "down"`  | Pagination direction (default: `"down"`) |
| `sortField` | `string?`         | Field to sort by (e.g., `"start_time"`)  |
| `sortOrder` | `"asc" \| "desc"` | Sort order                               |

### Response: TracesPage

| Field         | Type             | Description              |
| ------------- | ---------------- | ------------------------ |
| `traces`      | `TraceSummary[]` | List of trace summaries  |
| `hasNextPage` | `boolean`        | Whether more pages exist |
| `nextCursor`  | `string?`        | Cursor for next page     |

<AccordionGroup>
  <Accordion title="TraceSummary Fields" icon="list">
    | Field         | Type     | Description             |
    | ------------- | -------- | ----------------------- |
    | `id`          | `string` | Unique trace identifier |
    | `name`        | `string` | Trace name              |
    | `totalTokens` | `number` | Total tokens in trace   |
    | `totalCost`   | `number` | Total cost in USD       |
    | `startTime`   | `string` | Trace start timestamp   |
    | `endTime`     | `string` | Trace end timestamp     |
  </Accordion>

  <Accordion title="Direction Values" icon="arrows-up-down">
    | Value    | Description                   |
    | -------- | ----------------------------- |
    | `"down"` | Fetch newer/forward in time   |
    | `"up"`   | Fetch older/backwards in time |
  </Accordion>
</AccordionGroup>

***

## iterTraces

Iterator that automatically handles pagination when streaming through all traces.

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

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

  const iterator = client.usage.iterTraces({
    startTime: "2026-01-01T00:00:00.000Z",
    endTime: "2026-01-31T23:59:59.000Z",
    tenantId: "AceTech",
    userId: "Jerina",
    sessionId: "b8a359f8-f28c-4e88-839f-c5db103e9943",
    traceId: "45a32b90-f28c-4e88-839f-c5db103e9943",
    limit: 10,
    direction: "down",
    sortField: "start_time",
    sortOrder: "desc",
  });

  for await (const trace of iterator) {
    console.log(trace.id, trace.name, trace.totalCost);
  }
  ```

  ```typescript Signature theme={null}
  iterTraces(
    params: ListTracesParams
  ): AsyncGenerator<TraceSummary, void, unknown>
  ```
</CodeGroup>

### Parameters

| Parameter   | Type              | Description                              |
| ----------- | ----------------- | ---------------------------------------- |
| `startTime` | `string`          | Start of time range (ISO 8601 UTC)       |
| `endTime`   | `string`          | End of time range (ISO 8601 UTC)         |
| `traceId`   | `string?`         | Filter by trace ID                       |
| `sessionId` | `string?`         | Filter by session ID                     |
| `userId`    | `string?`         | Filter by user ID                        |
| `tenantId`  | `string?`         | Filter by tenant ID                      |
| `limit`     | `number?`         | Maximum traces per page                  |
| `cursor`    | `string?`         | Pagination cursor from previous page     |
| `direction` | `"up" \| "down"`  | Pagination direction (default: `"down"`) |
| `sortField` | `string?`         | Field to sort by (e.g., `"start_time"`)  |
| `sortOrder` | `"asc" \| "desc"` | Sort order                               |

<Tip>
  The iterator handles pagination automatically using `TracesPage.hasNextPage` and `TracesPage.nextCursor`. It stops when there are no more pages.
</Tip>

***

## listSpansByTraceId

Fetch spans within a single trace with optional filtering and pagination.

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

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

  const spansPage = await client.usage.listSpansByTraceId({
    traceId: "728c1de6fa4c53de143a7d7fef33ff91",
    direction: "down",
    limit: 10,
    spanName: "openai.chat",
  });

  if (spansPage) {
    for (const span of spansPage.spans) {
      console.log(span.id, span.name, span.kind, span.latencyMs);
    }

    console.log("Has next page?", spansPage.hasNextPage);
    console.log("Next cursor:", spansPage.nextCursor);
  }
  ```

  ```typescript Signature theme={null}
  listSpansByTraceId(params: ListSpansParams): Promise<SpansPage | null>

  // ListSpansParams interface
  interface ListSpansParams {
    traceId: string;
    cursor?: string;
    direction?: "up" | "down";
    limit?: number;
    spanName?: string;
  }
  ```
</CodeGroup>

### Parameters (ListSpansParams)

| Parameter   | Type             | Description                              |
| ----------- | ---------------- | ---------------------------------------- |
| `traceId`   | `string`         | ID of the trace to fetch spans from      |
| `cursor`    | `string?`        | Pagination cursor from previous page     |
| `direction` | `"up" \| "down"` | Pagination direction (default: `"down"`) |
| `limit`     | `number?`        | Maximum spans per page                   |
| `spanName`  | `string?`        | Filter by span name                      |

### Response: SpansPage

| Field         | Type          | Description              |
| ------------- | ------------- | ------------------------ |
| `spans`       | `TraceSpan[]` | List of span objects     |
| `hasNextPage` | `boolean`     | Whether more pages exist |
| `nextCursor`  | `string?`     | Cursor for next page     |

<AccordionGroup>
  <Accordion title="TraceSpan Fields" icon="diagram-project">
    | Field         | Type     | Description                                |
    | ------------- | -------- | ------------------------------------------ |
    | `id`          | `string` | Unique span identifier                     |
    | `name`        | `string` | Span name                                  |
    | `kind`        | `string` | Span type (e.g., `"generation"`, `"tool"`) |
    | `latencyMs`   | `number` | Duration in milliseconds                   |
    | `startTimeMs` | `string` | Span start timestamp                       |
    | `endTimeMs`   | `string` | Span end timestamp                         |
  </Accordion>
</AccordionGroup>

***

## iterSpansByTraceId

Iterator that automatically handles pagination when walking through all spans of a trace.

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

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

  const iterator = client.usage.iterSpansByTraceId({
    traceId: "728c1de6fa4c53de143a7d7fef33ff91",
    direction: "down",
    limit: 100,
    spanName: "generation_pipeline",
  });

  for await (const span of iterator) {
    console.log(
      `Span: ${span.id}, name=${span.name}, kind=${span.kind}, duration_ms=${span.latencyMs}`
    );
  }
  ```

  ```typescript Signature theme={null}
  iterSpansByTraceId(
    params: ListSpansParams
  ): AsyncGenerator<TraceSpan, void, unknown>
  ```
</CodeGroup>

### Parameters

| Parameter   | Type             | Description                              |
| ----------- | ---------------- | ---------------------------------------- |
| `traceId`   | `string`         | ID of the trace to fetch spans from      |
| `cursor`    | `string?`        | Pagination cursor from previous page     |
| `direction` | `"up" \| "down"` | Pagination direction (default: `"down"`) |
| `limit`     | `number?`        | Maximum spans per page                   |
| `spanName`  | `string?`        | Filter by span name                      |

***

## When to Use Which API

<CardGroup cols={2}>
  <Card title="Usage APIs" icon="gauge">
    **`getSessionUsage` / `getTenantUsage`**

    High-level reporting: tokens, requests, and cost per session or tenant. Use for billing dashboards and cost analysis.
  </Card>

  <Card title="Traces APIs" icon="route">
    **`listTraces` / `iterTraces`**

    Explore what traces exist in a time window, optionally filtered by session, user, or tenant. Use for debugging and monitoring.
  </Card>

  <Card title="Spans APIs" icon="diagram-project">
    **`listSpansByTraceId` / `iterSpansByTraceId`**

    Drill into a single trace to understand all spans (tools, generations, workflows) that occurred. Use for detailed trace analysis.
  </Card>

  <Card title="Iterators" icon="arrows-repeat">
    **`iter*` methods**

    When you need to process all results without manually handling pagination. The iterator fetches pages on-demand.
  </Card>
</CardGroup>

***

## Complete Example

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

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

  // Get session-level usage
  const sessionUsage = await client.usage.getSessionUsage(
    "session-123",
    "2026-01-01T00:00:00.000Z",
    "2026-01-31T23:59:59.000Z"
  );
  if (sessionUsage) {
    console.log(`Session cost: $${sessionUsage.totalCost.toFixed(4)}`);
  }

  // Get tenant-level usage
  const tenantUsage = await client.usage.getTenantUsage(
    "AceTech",
    "2026-01-01T00:00:00.000Z",
    "2026-01-31T23:59:59.000Z"
  );
  if (tenantUsage) {
    console.log(
      `Tenant total: ${tenantUsage.sessionCount} sessions, $${tenantUsage.totalCost.toFixed(4)}`
    );
  }

  // Iterate through all traces for a tenant
  const tracesIterator = client.usage.iterTraces({
    startTime: "2026-01-01T00:00:00.000Z",
    endTime: "2026-01-31T23:59:59.000Z",
    tenantId: "AceTech",
    sortField: "start_time",
    sortOrder: "desc",
  });

  for await (const trace of tracesIterator) {
    console.log(`Trace ${trace.id}: ${trace.name} - $${(trace.totalCost || 0).toFixed(4)}`);

    // Drill into spans for each trace
    const spansIterator = client.usage.iterSpansByTraceId({
        traceId: trace.id
    });

    for await (const span of spansIterator) {
      console.log(`  └─ ${span.name} (${span.kind}): ${span.latencyMs}ms`);
    }
  }
}

main();
```

## Next Steps

* [Dashboard Query](/sdk-reference/dashboard-query/typescript) - Query dashboard metrics and session stats
* [TypeScript SDK Reference](/sdk-reference/sdk/typescript) - Complete SDK documentation
* [Traces Overview](/Observability/Traces/overview) - Understanding traces
* [Sessions](/Observability/Session) - Session management
