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

# Query sessions

> Returns a paginated list of sessions with aggregated metrics, one row per distinct session ID in the requested time range.

The preferred alternative to `POST /v3/fetch-sessions`, which returns bare session ID strings with no metadata and requires a follow-up call per session to render anything useful. `fetch-sessions` is not deprecated by this endpoint's introduction; a deprecation is a separate decision with its own migration path.

**Time range is required**, including when `session_ids` is supplied. Sessions are aggregated across their spans, so without a bounded window the query cannot prune partitions and would group the entire trace table. This differs from the other session-addressed endpoints — `DELETE /v3/sessions` and `GET /v3/sessions/{session_id}/timeline` both take IDs with no window — because neither of those can be asked to aggregate an unbounded set of spans, and partition pruning is this endpoint's only hard bound on query cost.

**Metrics are computed over the requested window, not the session's whole lifetime.** See the `Session` schema.

**Filters are explicit typed fields, not the `QueryCondition` DSL** used by `POST /v3/spans/query`. The only optional filter at launch is `session_ids`. Expressing a simple ID list as a DSL tree is strictly worse ergonomics for no functional gain; a `filter` field can be added later without breaking this contract.

**Sorting is restricted to `start_time`.** Sorting by aggregates (`duration`, `span_count`, `total_tokens`) is not yet supported and is rejected with a 400.

**`status` and full-text `search` are deliberately absent.** A session-level status means imposing a severity order on OTel `StatusCode`, and the ambiguous case is the common one: a session whose spans are all `Unset`. Redefining a response field later is a breaking change, whereas adding one is not, so this waits for a decision rather than shipping a guess. `search` is a different query shape at session granularity than at span granularity — matching is per span, but the aggregates must still cover every span of a matched session, not only the matching ones. Both can be added later without breaking this contract.

Spans carrying no session ID are excluded. Sessions are scoped to a single application.



## OpenAPI

````yaml POST /v3/sessions/query
openapi: 3.0.3
info:
  title: Fiddler API - 2.0
  description: APIs to interact with Fiddler
  termsOfService: https://fiddler.ai/about/terms
  contact:
    email: support@fiddler.ai
  license:
    name: Proprietary
    url: '2.0'
  version: '2.0'
servers: []
security:
  - BearerAuth: []
tags:
  - name: access-key
    description: CRUD operations for API keys
  - name: agent-v3
    description: CRUD for the Agent Registry (Stage 1, manual entries)
  - name: aggregation-invalidation-request-v3
    description: Endpoints related to retrieving aggregation invalidation requests
  - name: alert-rules-v3
    description: CRUD for Alert Rules, Summary, and Stats APIs
  - name: application-v3
  - name: auth
    description: Authentication strategies and login flows
  - name: baseline-v3
    description: CRUD for baseline
  - name: catalog-v3
    description: >-
      Entity catalog provides paginated, searchable discovery of entity names
      (attribute keys, agent names, span types, span names, score names,
      evaluator config names) and their distinct values. Powered by ClickHouse
      materialized views — no worker or PostgreSQL dependency.
  - name: chart-annotation-v3
    description: Endpoints related to retrieving chart annotations
  - name: chart-v3
    description: CRUD for chart
  - name: queries-v3
    description: v3 queries API
  - name: configuration-v3
    description: CRUD for configurations
  - name: cost-evaluators-v3
    description: >
      Paginated roll-up of per-evaluator LLM cost and token usage, aggregated
      hourly. Available only on deployments with evaluator cost reporting
      enabled.
  - name: custom-metrics-v3
  - name: dimensionality-reduction-v3
  - name: environment-v3
    description: Endpoints related to environment management
  - name: evals
  - name: datasets
  - name: evaluation-v3
  - name: evaluator-v3
  - name: rule-evaluators-v3
  - name: experiment-v3
  - name: explainability-v3
  - name: llm_rca-v3
  - name: file-upload
    description: Endpoints related to file uploading.
  - name: fql-expressions-v3
    description: >
      Endpoints for listing FQL (Fiddler Query Language) functions available for
      GenAI custom metrics. Used by the frontend for autocomplete and signature
      hints in the FQL editor.
  - name: genai-alert-rules-v3
    description: CRUD API for GenAI Alert Rules
  - name: genai-custom-metrics-v3
    description: API for GenAI Custom Metrics
  - name: genai-metrics-v3
    description: >-
      Endpoints for pre-aggregated GenAI metrics. All metric data is
      pre-aggregated hourly by a Celery-based metric collector; no real-time
      aggregation is performed at request time.
  - name: guardrails-api
    description: Endpoints related to retrieving Guardrails specific data
  - name: ingestion-v3
  - name: intercom-api
    description: Endpoints related to intercom APIs
  - name: jobs-v3
  - name: llm-gateway-v3
  - name: auth-login
  - name: auth-logout
  - name: mcp-client-setup-v3
    description: Endpoints for retrieving MCP client setup instructions.
  - name: metrics-v3
    description: Metrics endpoints
  - name: model-v3
  - name: dashboard-v3
  - name: model-deployment-v3
  - name: monitoring-summary-v3
  - name: histograms-v3
  - name: organization-roles-v3
    description: Update user org role
  - name: organization-settings-v3
    description: Update organization settings such as timezone, email configuration, etc.
  - name: pagerduty-api
    description: CRUD for Pagerduty services.
  - name: project-v3
  - name: project-roles-v3
    description: Project role assignment management
  - name: scores-v3
    description: Unified CRUD for scores and annotations
  - name: searchable-text-key-v3
    description: >-
      Manage the global searchable text keys table that controls which OTel
      attribute keys are routed to the full-text-searchable `ValueContent`
      column in the unified attributes table. Changes propagate to the backing
      ClickHouse dictionary within 1-2 minutes and affect all tenants.
  - name: segments-v3
  - name: semantic-mapping-v3
    description: >-
      Manage the global semantic name mappings table that maps raw OTel
      attribute keys to canonical semantic concepts. Changes propagate to the
      backing ClickHouse dictionary within 1-2 minutes and affect all tenants.
  - name: server-info-v3
    description: Endpoints related to retrieving server information
  - name: service-account
    description: >
      Service accounts and their API keys. A human Org Admin manages the service
      accounts of their own organization: create, read, update, and
      enable/disable (there is no delete — an account is disabled instead), and
      issue, rename, re-date, enable/disable, and revoke each account's API
      keys. An API key is an `fks_` secret that inherits the account's grants
      and cannot manage service accounts; an active, unexpired key must be
      disabled before it can be revoked, and it authenticates only while both it
      and its account are active. Scopes here are capability scopes (what the
      account may do), not OAuth scopes.
  - name: sessions-v3
    description: v3 session APIs
  - name: span-v3
  - name: team-roles-v3
  - name: team-v3
  - name: traces-v3
    description: v3 trace api for monitoring
  - name: fetch-sessions-v3
    description: v3 fetch sessions api for monitoring
  - name: user-access-key
    description: >
      CRUD operations for user API keys. All endpoints are user-scoped — each
      user can only operate on their own API keys. No one including Org admins
      have access to other users' API keys.
  - name: users-v3
  - name: version-compatibility-v3
  - name: webhooks
externalDocs:
  url: https://docs.fiddler.ai
  description: Find out more about Fiddler
paths:
  /v3/sessions/query:
    post:
      tags:
        - sessions-v3
      summary: Query sessions
      description: >-
        Returns a paginated list of sessions with aggregated metrics, one row
        per distinct session ID in the requested time range.


        The preferred alternative to `POST /v3/fetch-sessions`, which returns
        bare session ID strings with no metadata and requires a follow-up call
        per session to render anything useful. `fetch-sessions` is not
        deprecated by this endpoint's introduction; a deprecation is a separate
        decision with its own migration path.


        **Time range is required**, including when `session_ids` is supplied.
        Sessions are aggregated across their spans, so without a bounded window
        the query cannot prune partitions and would group the entire trace
        table. This differs from the other session-addressed endpoints — `DELETE
        /v3/sessions` and `GET /v3/sessions/{session_id}/timeline` both take IDs
        with no window — because neither of those can be asked to aggregate an
        unbounded set of spans, and partition pruning is this endpoint's only
        hard bound on query cost.


        **Metrics are computed over the requested window, not the session's
        whole lifetime.** See the `Session` schema.


        **Filters are explicit typed fields, not the `QueryCondition` DSL** used
        by `POST /v3/spans/query`. The only optional filter at launch is
        `session_ids`. Expressing a simple ID list as a DSL tree is strictly
        worse ergonomics for no functional gain; a `filter` field can be added
        later without breaking this contract.


        **Sorting is restricted to `start_time`.** Sorting by aggregates
        (`duration`, `span_count`, `total_tokens`) is not yet supported and is
        rejected with a 400.


        **`status` and full-text `search` are deliberately absent.** A
        session-level status means imposing a severity order on OTel
        `StatusCode`, and the ambiguous case is the common one: a session whose
        spans are all `Unset`. Redefining a response field later is a breaking
        change, whereas adding one is not, so this waits for a decision rather
        than shipping a guess. `search` is a different query shape at session
        granularity than at span granularity — matching is per span, but the
        aggregates must still cover every span of a matched session, not only
        the matching ones. Both can be added later without breaking this
        contract.


        Spans carrying no session ID are excluded. Sessions are scoped to a
        single application.
      operationId: querySessionsV3
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SessionQueryRequest'
            examples:
              all_sessions:
                $ref: '#/components/examples/SessionQueryAllSessions'
              filtered_by_id:
                $ref: '#/components/examples/SessionQueryFilteredById'
      responses:
        '200':
          description: A paginated list of sessions matching the query
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedApiResponse'
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          items:
                            type: array
                            items:
                              $ref: '#/components/schemas/Session'
              examples:
                populated:
                  $ref: '#/components/examples/SessionQueryResponsePopulated'
                empty:
                  $ref: '#/components/examples/SessionQueryResponseEmpty'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '403':
          $ref: '#/components/responses/403'
        '404':
          $ref: '#/components/responses/404'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying
            X-RateLimit-Limit:
              schema:
                type: string
              description: Rate limit policy
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: Remaining requests in current window
            X-RateLimit-Reset:
              schema:
                type: integer
              description: Unix timestamp when the rate limit resets
        '500':
          $ref: '#/components/responses/500'
        '504':
          description: >-
            Gateway Timeout — the ClickHouse query did not complete within the
            server-side timeout (default 30 s). Narrow the time range or retry
            with exponential backoff.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    SessionQueryRequest:
      type: object
      description: >-
        Request body for `POST /v3/sessions/query`. Unknown fields are rejected
        with a 400.
      required:
        - application_id
        - start_time
        - end_time
      properties:
        application_id:
          type: string
          format: uuid
          description: UUID of the Fiddler GenAI application.
          example: c688de46-2054-49ab-b85f-0f0178cb44d7
        start_time:
          type: string
          format: date-time
          description: >-
            Start of the time range (inclusive, UTC). Must be timezone-aware and
            strictly before `end_time`. Matched against span start timestamps,
            so a session that began before this bound appears only if it also
            has spans inside the window.
          example: '2026-03-01T00:00:00Z'
        end_time:
          type: string
          format: date-time
          description: End of the time range (exclusive, UTC). Must be timezone-aware.
          example: '2026-03-02T00:00:00Z'
        session_ids:
          type: array
          description: >-
            Optional allow-list of session IDs. Omit or pass `null` to return
            all sessions in the window. An empty array is treated as omitted.
            Empty-string entries are rejected — spans with no session context
            are excluded from this endpoint, so `""` can never match. The cap
            matches `DELETE /v3/sessions`, so the same ID list works against
            either endpoint; a list longer than `page_size` simply spans several
            pages.
          nullable: true
          maxItems: 1000
          items:
            $ref: '#/components/schemas/SessionId'
          example:
            - chat-abc123
            - chat-def456
        ordering:
          type: string
          description: >-
            Sort field with an optional leading `-` for descending. Only
            `start_time` is supported; any other field is rejected with a 400.
          default: '-start_time'
          enum:
            - start_time
            - '-start_time'
        page_size:
          type: integer
          description: Number of sessions per page.
          default: 50
          minimum: 1
          maximum: 200
          example: 50
        offset:
          type: integer
          description: >-
            Zero-based offset into the result set. Deep pagination re-scans the
            window through a `GROUP BY`, so the offset is capped. Because of
            this cap, `data.page_count` in the response can advertise pages
            beyond what this endpoint will actually serve: `page_count` is
            `ceil(total / page_size)` with no awareness of the offset limit, so
            a large `total` with a small `page_size` can put the last page's
            offset past 10000. Requesting such a page returns 400, not an empty
            result. A client walking pages by index should stop once its next
            offset would exceed 10000, not once it reaches `page_count`.
          default: 0
          minimum: 0
          maximum: 10000
          example: 0
    PaginatedApiResponse:
      type: object
      description: |
        Response object for paginated API responses.
      properties:
        api_version:
          type: string
          default: '3.0'
          enum:
            - '2.0'
            - '3.0'
          description: |
            API version of the response.
        kind:
          type: string
          default: PAGINATED
          enum:
            - PAGINATED
          description: |
            Type of response, indicating a paginated response.
        data:
          type: object
          properties:
            page_size:
              type: integer
              default: 10
              example: 10
              description: |
                Number of items per page in the response.
            item_count:
              type: integer
              default: 10
              example: 10
              description: |
                Number of items in the current page.
            total:
              type: integer
              example: 100
              default: 100
              description: |
                Total number of items across all pages.
            page_count:
              type: integer
              default: 10
              example: 10
              description: |
                Total number of pages.
            page_index:
              type: integer
              default: 1
              example: 1
              description: |
                Current page index.
            offset:
              type: integer
              default: 0
              example: 0
              description: |
                Offset of the first item in the current page.
    Session:
      type: object
      description: >-
        A single session, with metrics aggregated across the spans that fall
        inside the requested time window — **not** across the session's whole
        lifetime. A session that started before `start_time` or continues past
        `end_time` reports only the part inside the window, so the same session
        queried over two adjacent windows returns two different `span_count`
        values and neither is the whole-session total. Widen the window to
        converge on the true figures.
      required:
        - session_id
        - trace_count
        - span_count
        - start_time
        - end_time
        - duration
        - total_tokens
      properties:
        session_id:
          $ref: '#/components/schemas/SessionId'
        trace_count:
          type: integer
          description: Number of distinct traces with at least one span in the window.
          minimum: 0
          example: 3
        span_count:
          type: integer
          description: Number of spans in the window, across all of the session's traces.
          minimum: 0
          example: 47
        start_time:
          type: string
          format: date-time
          description: >-
            Start time of the earliest in-window span (UTC). Never earlier than
            the requested `start_time`, even if the session began before it.
          example: '2026-03-01T10:00:00Z'
        end_time:
          type: string
          format: date-time
          description: >-
            End of the latest in-window span — its start plus its duration, not
            merely the latest start time. A long-running span that began early
            can therefore set `end_time`. This one *can* fall outside the
            requested range: a span starting just inside the window may finish
            after `end_time`.
          example: '2026-03-01T10:15:12.500Z'
        duration:
          type: integer
          format: int64
          description: >-
            `end_time - start_time` in **nanoseconds**, matching the units of
            `duration` on span and timeline responses. Divide by 1 000 000 for
            milliseconds. This is wall-clock span, not summed span time, so it
            includes any idle gaps between traces in the session — and it
            measures the session's in-window extent, not its full duration.
          minimum: 0
          example: 912500000000
        total_tokens:
          type: integer
          description: >-
            Token usage summed across the in-window spans. Each span contributes
            its own reported `total_tokens` when it has one, and `input_tokens +
            output_tokens` otherwise — so a provider that reports only a total
            is counted, and one that reports both a total and its components is
            not counted twice. Cache and reasoning tokens are not added on top:
            whether they are already inside the components is provider-specific,
            so adding them unconditionally would overstate usage for providers
            that nest them. Where a provider bills them separately, they are
            included via that provider's own reported total. Token attributes
            are conventionally present only on leaf LLM spans; that convention
            is not enforced at ingest, so a parent span echoing its children's
            token counts would inflate this total. Sessions with no LLM spans
            report `0`.
          minimum: 0
          example: 28450
    ErrorResponse:
      type: object
      description: |
        Response object for errors returned by the API.
      properties:
        api_version:
          type: string
          default: '3.0'
          enum:
            - '2.0'
            - '3.0'
          description: |
            API version of the response.
        kind:
          type: string
          default: ERROR
          enum:
            - ERROR
          description: |
            Type of response, usually indicating an error.
        error:
          type: object
          properties:
            code:
              type: integer
              format: int32
              description: >
                Represents the code for this error, typically an HTTP response
                code.
              default: 400
              enum:
                - 400
                - 401
                - 403
                - 404
                - 409
                - 410
                - 422
                - 429
                - 500
                - 501
                - 503
            message:
              type: string
              description: >
                A human-readable message providing more details about the error.
                If there are multiple errors, it will be the message for the
                first error.
              example: Resource Not Found
            errors:
              type: array
              description: >
                Container for additional information regarding the error,
                especially for multiple errors.
              items:
                type: object
                properties:
                  reason:
                    type: string
                    description: >
                      Unique identifier for this error, different from the error
                      code.
                    example: ResourceNotFoundException
                  message:
                    type: string
                    description: >
                      A human-readable message providing more details about the
                      error. If there is only one error, this field will match
                      error.message.
                    example: Resource Not Found
                  help:
                    type: string
                    description: >
                      Link to support or documentation providing more
                      information on the error.
    SessionId:
      type: string
      description: Session ID grouping related traces
      minLength: 1
  examples:
    SessionQueryAllSessions:
      value:
        application_id: c688de46-2054-49ab-b85f-0f0178cb44d7
        start_time: '2026-03-01T00:00:00Z'
        end_time: '2026-03-02T00:00:00Z'
        ordering: '-start_time'
        page_size: 50
        offset: 0
    SessionQueryFilteredById:
      value:
        application_id: c688de46-2054-49ab-b85f-0f0178cb44d7
        start_time: '2026-03-01T00:00:00Z'
        end_time: '2026-03-02T00:00:00Z'
        session_ids:
          - chat-abc123
          - chat-def456
    SessionQueryResponsePopulated:
      value:
        api_version: '3.0'
        kind: PAGINATED
        data:
          total: 57
          page_size: 2
          item_count: 2
          page_count: 29
          page_index: 2
          offset: 2
          items:
            - session_id: chat-abc123
              trace_count: 3
              span_count: 47
              start_time: '2026-03-01T10:00:00Z'
              end_time: '2026-03-01T10:15:12.500Z'
              duration: 912500000000
              total_tokens: 28450
            - session_id: chat-def456
              trace_count: 1
              span_count: 4
              start_time: '2026-03-01T09:42:00Z'
              end_time: '2026-03-01T09:42:00.750Z'
              duration: 750000000
              total_tokens: 0
    SessionQueryResponseEmpty:
      value:
        api_version: '3.0'
        kind: PAGINATED
        data:
          total: 0
          page_size: 50
          item_count: 0
          page_count: 0
          page_index: 1
          offset: 0
          items: []
  responses:
    '400':
      description: Bad Request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    '401':
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    '403':
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    '404':
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    '500':
      description: Internal Server Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer

````