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

# List session summaries

> Use `limit` and `offset` to page through the results. The response includes
message, trace-event, and token counts per session, but not the messages or
trace details themselves. Use the conversation-history endpoint for messages and
the traces endpoint for execution detail.


Use this endpoint to retrieve session-level analytics for a project. Each result represents one conversation session and includes summary information such as the channel, environment, status, containment outcome, message and trace-event counts, token usage, cost, and session duration. The response does not include the individual messages or trace details; use the conversation-history and traces endpoints to retrieve those details.

It provides the following filters:

* `fromDate` — Inclusive start timestamp.
* `toDate` — Exclusive end timestamp.
* `sessionIds` — Filter by specific session IDs; up to 10,000.
* `containmentType` — Filter by how the session was resolved, such as `contained_resolved`, `contained_partial`, `escalated`, or `abandoned`.
* `environment` — Filter by environment: `dev`, `staging`, `production`, or `working-copy`.
* `channelUId` — Filter by the end-user identity recorded on the channel.
* `callerNumber` — Filter by caller number or caller identity.
* `channel` — Filter by the channel through which the conversation originated.
* `traceDimensions[key]` — Filter by custom session dimensions and their values.
* `status` — Filter by session state, such as `active`, `idle`, `ended`, `completed`, `escalated`, or `abandoned`.

You must provide either `fromDate` and `toDate` together, or `sessionIds`. All other filters are optional. Multiple filters are combined with `AND` logic; multiple values within a filter are combined with `OR` logic.

Use `limit` and `offset` to paginate through the results.


## OpenAPI

````yaml agent-platform/api-specs/sessions.yaml get /api/public/analytics/projects/{projectId}/sessions
openapi: 3.1.0
info:
  title: ABL Public Analytics Sessions API
  version: 1.0.0
  summary: Retrieve project-scoped session analytics.
  description: >
    Returns one row per conversation session in a project, summarising how it
    went:

    which channel it came in on, how it ended, how many messages were exchanged,
    how

    many tokens were used, and what it cost.


    Give either a date range (`fromDate` and `toDate` together) or a list of

    `sessionIds`. Other filters are optional. Different filters combine with
    AND, and

    multiple values in the same filter combine with OR — so

    `channel=web_chat,voice&status=ended` means web chat or voice sessions that
    have

    ended.


    Authenticate with the `x-api-key` header. The key must be bound to the
    project you

    are querying and have `session:read` permission.


    ## Sending parameters in a POST body


    Every GET on this API has a POST form on the same path. Send the same
    parameters

    as a flat JSON object instead of a query string. Use POST when the
    parameters

    themselves must be encrypted: a GET query string is never encrypted. GET
    stays

    available and unchanged.


    - Body keys are exactly the GET query parameter names. Numbers and booleans
    are
      converted to the strings the GET parser expects. List parameters accept a
      JSON array or a comma-separated string.
      `traceDimensions` is an object of dimension name to value, for example
      `{"traceDimensions": {"accountTier": "gold"}}`, instead of the
      `traceDimensions[key]` query form.
    - An unknown key, a `null`, or a nested value is rejected with
      `400 INVALID_QUERY_PARAMETER`. A body that is not a JSON object is rejected
      with `400 INVALID_REQUEST_BODY`.
    - Do not add a query string to a POST (`400 INVALID_QUERY_PARAMETER`), and
    do
      not split parameters between the query string and the body.
    - `Content-Type` must be `application/json` or `application/jose+json`,
      otherwise `415 UNSUPPORTED_MEDIA_TYPE`.
    - Permissions, validation, pagination and the response shape are identical
    to
      the GET form.

    ## Payload encryption


    Payload encryption is an opt-in setting on a Platform Key, configured in
    Studio

    under Settings → API Keys → Platform Keys. It has two independent toggles.

    Neither changes what the key may access, and both are available only to keys

    bound to exactly one project.


    **Request encryption** applies to POST bodies (a GET has no body). The body
    must

    be a JWE (RFC 7516) in flattened JSON serialization, `{protected, iv,

    ciphertext, tag}`, whose protected header is
    `{"alg":"dir","enc":"A256GCM"}`,

    optionally with `kid`, `typ` and `cty`. The key is the 32-byte AES-256
    request

    key Studio shows when request encryption is enabled. `kid` is optional; if
    sent

    it must equal the key's Key ID shown in Studio.


    **Response encryption** applies to every response sent after the key is

    authenticated, successes and errors alike (400, 403, 404, 413, 415, 429,
    500,

    503). The body is a flattened JWE `{protected, encrypted_key, iv,
    ciphertext,

    tag}` with protected header

    `{"alg":"RSA-OAEP-256","enc":"A256GCM","kid":"<Key
    ID>","pkf":"<fingerprint>"}`,

    sealed with a fresh AES-256 key per response that is wrapped with the RSA
    public

    key (≥ 2048 bits) configured on the Platform Key. `pkf` is the SHA-256 hex

    digest of that public key's SubjectPublicKeyInfo DER. The response keeps

    `Content-Type: application/json` and adds `X-ABL-Encrypted: true`.
    Decrypting

    it yields exactly the JSON documented in this spec. A `401` is never
    encrypted

    (the key is not known yet), and a `304` has no body.


    | Key setting | Plain JSON body | JWE body |

    |---|---|---|

    | Request encryption off | accepted | `400 ENCRYPTED_PAYLOAD_INVALID` |

    | Request encryption on | `400 ENCRYPTED_PAYLOAD_INVALID` | decrypted, then
    handled as plain JSON |


    Encryption fails closed: a configured key never receives plaintext by
    accident.


    - `400 ENCRYPTED_PAYLOAD_INVALID` is returned for every envelope problem:
    any
      other `alg`/`enc`, `zip` or `crit`, unknown header parameters, `unprotected`,
      `header`, `aad` or `recipients` members, a `kid` that is not this key's,
      padded or standard base64, a wrong IV (12 bytes) or tag (16 bytes) length, a
      failed authentication tag, or a plaintext that is not JSON.
    - `503 ENCRYPTION_CONFIG_UNAVAILABLE` (with `Retry-After: 30`) means the
    key's
      encryption configuration could not be read. Retry later; there is no
      plaintext fallback.
    - `500 INTERNAL_ERROR` with a content-free body is returned if a response
    cannot
      be encrypted.

    All JWE members are unpadded base64url. The AAD is the ASCII of the
    `protected`

    member, as in standard JWE, so JOSE libraries (for example `jose` for
    Node.js)

    can produce and open these envelopes directly. Pin the algorithms when

    decrypting: key management `RSA-OAEP-256`, content encryption `A256GCM`.
  x-source-release: develop
  x-source-commit: b6a1a328b3e089e03ca2494a7091d72a6a481d4b
  x-payload-encryption:
    jira: ABLP-5317
    source: develop, PR
    source-commit: 6de86f59eb
    runtime-capability: 'GET /health -> capabilities.payloadEncryption: 2'
servers:
  - url: https://{host}
    description: ABL Runtime public endpoint
    variables:
      host:
        default: runtime.example.com
security:
  - ApiKeyAuth: []
tags:
  - name: Sessions
paths:
  /api/public/analytics/projects/{projectId}/sessions:
    get:
      tags:
        - Sessions
      summary: List session summaries
      description: >
        Use `limit` and `offset` to page through the results. The response
        includes

        message, trace-event, and token counts per session, but not the messages
        or

        trace details themselves. Use the conversation-history endpoint for
        messages and

        the traces endpoint for execution detail.
      operationId: listPublicAnalyticsSessions
      parameters:
        - $ref: '#/components/parameters/ProjectId'
        - $ref: '#/components/parameters/FromDateOptional'
        - $ref: '#/components/parameters/ToDateOptional'
        - $ref: '#/components/parameters/SessionIds'
        - name: containmentType
          in: query
          description: >
            Filter by how the session was resolved — whether the agent handled
            it or it

            went to a human. Pass one or more values, comma-separated or by
            repeating

            the parameter, up to 100.


            Values are case-sensitive and anything else is rejected with `400

            INVALID_CONTAINMENT_TYPE`.
          style: form
          explode: false
          schema:
            type: array
            maxItems: 100
            uniqueItems: true
            items:
              type: string
              enum:
                - contained
                - contained_resolved
                - contained_partial
                - contained_unresolved
                - escalated
                - abandoned
        - name: environment
          in: query
          description: >
            Filter by environment. Pass one or more values, comma-separated or
            by

            repeating the parameter.


            Values are case-sensitive and anything else is rejected with `400

            INVALID_ENVIRONMENT`. Use `dev`, not `development` or `prod` — the
            service

            handles both stored spellings for you behind the scenes, but only
            accepts

            the four values below as input.
          style: form
          explode: false
          schema:
            type: array
            maxItems: 4
            uniqueItems: true
            items:
              type: string
              maxLength: 128
              enum:
                - dev
                - staging
                - production
                - working-copy
        - name: channelUId
          in: query
          description: >
            Filter to sessions belonging to specific end users, using the
            identity

            recorded for them on the channel. Pass up to 100 values,
            comma-separated or

            by repeating the parameter.
          style: form
          explode: false
          schema:
            type: array
            maxItems: 100
            uniqueItems: true
            items:
              type: string
              minLength: 1
        - name: callerNumber
          in: query
          description: >
            Filter to sessions from specific callers (ANI or provider caller
            id). Pass up

            to 100 values, comma-separated (spaces after commas are allowed) or
            by

            repeating the parameter; the filter is ANDed with every other
            filter. The

            100-value limit counts entries before duplicates are merged; more
            returns

            `400 TOO_MANY_FILTER_VALUES`. A value that itself contains a comma
            cannot be

            queried, because commas always separate values.


            Paste the value in any format the provider, a transcript, a CDR or a

            spreadsheet shows. Each value is turned into the same match key the
            platform

            stored at call time: invisible characters, fullwidth digits and
            Unicode

            dashes are cleaned up, a national trunk `(0)` after the country code
            is

            removed (`+44 (0)20 7946 0958` matches `+442079460958`), and
            phone-like

            values (including `sip:` and

            `tel:` URIs, spaces, dashes, dots, slashes and parentheses) become
            E.164.

            7 to 15 bare digits are treated as an international number
            (`919876543210`

            matches `+919876543210`). Digits written in a national format keep
            their

            digits (`098765 43210` matches `09876543210`). Other values, such as
            softphone

            usernames, SDK ids or `Anonymous`, are matched as cleaned text.
            Matching is

            exact and case-sensitive: `anonymous` does not match `Anonymous`,
            and

            `+14155550100 ext 12` does not match `+14155550100`. Non-ASCII
            digits such as

            Arabic-Indic digits are not converted to ASCII. Keys longer than 128

            characters are truncated, the same way they were when stored.


            There is no country inference: a national number without its country
            code

            (`9876543210`) does not match a stored `+919876543210`, and `00` or
            `011`

            dial prefixes are not converted. Send the full international form
            where

            possible. Send `+` as `%2B` or use the POST twin; an unencoded `+`
            decodes to

            a space, which is also accepted and gives the same match.
            `Anonymous` matches

            every withheld-number call in the window.


            An entry that is empty or has no letter or digit (for example

            `callerNumber=`, a trailing comma, or only `+`), or an entry longer
            than 512

            characters, returns `400 INVALID_CALLER_NUMBER`. The value is

            never returned in the response. When the project's reporting
            exposure config

            disables the `identity` field group, a request with this parameter
            returns

            `403 CALLER_NUMBER_LOOKUP_DISABLED`.


            Coverage: matches sessions whose summary was written after this
            filter

            shipped. Sessions recorded earlier are not returned for
            `callerNumber` (use

            `/conversation-history`, which reads the session record directly).

            Playground and Studio debug sessions are never matched.
          style: form
          explode: false
          schema:
            type: array
            maxItems: 100
            items:
              type: string
              minLength: 1
              maxLength: 512
        - name: channel
          in: query
          description: >
            Filter by the channel the conversation came in on. Pass one or more
            values,

            comma-separated or by repeating the parameter, up to 50 distinct
            channels of

            128 characters each.


            This endpoint understands shorthand. Values are grouped into channel

            families before matching, and each family also matches its older
            stored

            spellings, so `channel=web`, `channel=sdk_web`, and
            `channel=web_chat` all

            return the same web-chat sessions. The groupings are listed under

            `x-alias-groups`, and those alias spellings are accepted here even
            though

            they are not in the enum — the enum is kept identical across all the
            public

            analytics endpoints so there is one channel list to learn.


            Because of that grouping, asking for one specific voice channel such
            as

            `channel=voice_pipeline` returns all voice sessions, not just that

            transport. Use the traces endpoint if you need to distinguish them.


            Not restricted to a fixed list, so an unrecognised value returns no
            results

            rather than an error.
          style: form
          explode: false
          schema:
            type: array
            maxItems: 50
            uniqueItems: true
            items:
              type: string
              maxLength: 128
              enum:
                - http_async
                - slack
                - line
                - msteams
                - whatsapp
                - messenger
                - instagram
                - twilio_sms
                - zendesk
                - telegram
                - genesys
                - genesys_open_messaging
                - ai4w
                - kore_agent_assist
                - email
                - voice_vxml
                - korevg
                - audiocodes
                - genesys_audio_connector
                - voice_pipeline
                - voice_realtime
                - voice
                - voice_twilio
                - voice_livekit
                - ag_ui
                - a2a
                - sdk_websocket
                - web_debug
                - web_chat
                - api
                - http
          x-alias-groups:
            web_chat:
              - web
              - sdk_web
              - sdk_chat
              - chat
              - webchat
              - sdk_websocket
              - sdk_ws
              - sdk-ws
              - ws
            web_debug:
              - debug_websocket
              - web_debug_socket
            api:
              - http
              - sdk_http
              - sdk_api
            twilio_sms:
              - sms
              - twilio
            voice:
              - vxml
              - voice_vxml
              - korevg
              - audiocodes
              - genesys_audio_connector
              - voice_pipeline
              - voice_realtime
              - voice_twilio
              - voice_livekit
              - twilio_voice
        - $ref: '#/components/parameters/TraceDimension'
        - name: status
          in: query
          description: >
            Filter by the session's current state. Pass a single value; if you
            repeat

            the parameter only the first value is used.


            Case-sensitive, and anything else is rejected with `400
            INVALID_STATUS`.

            Note that sessions can be stored with a status of `failed`, but
            `failed` is

            not accepted as a filter value here.
          schema:
            type: string
            enum:
              - active
              - idle
              - ended
              - completed
              - escalated
              - abandoned
              - archived
        - name: limit
          in: query
          description: >
            How many sessions to return. A page may come back with fewer than
            requested

            so the response stays within the 1 MiB size limit — check `hasMore`
            rather

            than assuming a short page is the last one.
          schema:
            type: integer
            minimum: 1
            maximum: 10000
            default: 100
        - name: offset
          in: query
          schema:
            type: integer
            minimum: 0
            default: 0
      responses:
        '200':
          description: Session page returned successfully.
          headers:
            X-ABL-Encrypted:
              $ref: '#/components/headers/XAblEncrypted'
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/SessionListResponse'
                  - $ref: '#/components/schemas/EncryptedResponse'
              example:
                success: true
                total: 1
                offset: 0
                limit: 100
                hasMore: false
                sessions:
                  - id: sess-01J4S8Y1
                    channel: web_chat
                    environment: production
                    status: ended
                    containmentType: contained_resolved
                    createdAt: '2026-08-01T00:00:00.000Z'
                    lastActivityAt: '2026-08-01T00:05:00.000Z'
                    endedAt: '2026-08-01T00:05:30.000Z'
                    messageCount:
                      user: 3
                      agent: 4
                      total: 7
                    traceEventCount:
                      llm_call: 2
                      decision: 1
                      tool_call: 5
                      error: 1
                      total: 12
                    tokenCount:
                      inputTokens: 100
                      cachedTokens: 10
                      completionTokens: 32
                      reasoningTokens: 8
                      outputTokens: 40
                      totalTokens: 140
                    traceDimensions:
                      accountTier: gold
                    estimatedCost: 0.0025
                    durationMs: 330000
                    idleDurationMs: 30000
                    isTest: null
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '413':
          $ref: '#/components/responses/ResponseTooLarge'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/Unavailable'
components:
  parameters:
    ProjectId:
      name: projectId
      in: path
      required: true
      description: Project identifier bound to the API key.
      schema:
        type: string
        minLength: 1
    FromDateOptional:
      name: fromDate
      in: query
      description: >-
        Inclusive ISO 8601 start timestamp. Required with `toDate` unless
        `sessionIds` is supplied.
      schema:
        type: string
        format: date-time
    ToDateOptional:
      name: toDate
      in: query
      description: >-
        Exclusive ISO 8601 end timestamp. Required with `fromDate` unless
        `sessionIds` is supplied.
      schema:
        type: string
        format: date-time
    SessionIds:
      name: sessionIds
      in: query
      description: >
        Filter to specific sessions. Pass up to 10,000 session IDs,
        comma-separated or

        by repeating the parameter. Can be used instead of a date range.
      style: form
      explode: false
      schema:
        type: array
        maxItems: 10000
        uniqueItems: true
        items:
          type: string
          minLength: 1
    TraceDimension:
      name: traceDimensions[key]
      in: query
      description: >
        Filter by a custom dimension recorded against the session. Replace `key`
        with

        the dimension name — for example `traceDimensions[accountTier]=gold`.
        Repeat

        with different keys to require all of them. Values match exactly.
        Remember to

        URL-encode the brackets if your HTTP client does not do it for you.
      allowReserved: true
      schema:
        type: string
      x-dynamic-parameter: true
  headers:
    XAblEncrypted:
      description: >-
        Present with value `true` when the body is an `EncryptedResponse`.
        Absent otherwise.
      schema:
        type: string
        enum:
          - 'true'
  schemas:
    SessionListResponse:
      type: object
      additionalProperties: false
      required:
        - success
        - sessions
        - total
        - offset
        - limit
        - hasMore
      properties:
        success:
          type: boolean
          const: true
          description: |
            Always true on a successful response.
        sessions:
          description: The sessions on this page.
          type: array
          items:
            $ref: '#/components/schemas/Session'
        total:
          type: integer
          minimum: 0
          description: |
            Total number of sessions matching your filters, across all pages.
        offset:
          type: integer
          minimum: 0
          description: |
            The offset applied to this response.
        limit:
          type: integer
          minimum: 1
          maximum: 10000
          description: |
            The page size applied to this response.
        hasMore:
          type: boolean
          description: |
            Whether more pages are available after this one.
    EncryptedResponse:
      type: object
      additionalProperties: false
      required:
        - protected
        - encrypted_key
        - iv
        - ciphertext
        - tag
      description: >
        Response body for a Platform Key with response encryption on (signalled
        by the

        `X-ABL-Encrypted: true` header): a JWE in flattened JSON serialization.
        The

        decrypted plaintext is the JSON body documented for that status code.
      properties:
        protected:
          type: string
          pattern: ^[A-Za-z0-9_-]+$
          description: >-
            base64url of the protected header. Decodes to
            `ResponseProtectedHeader`.
        encrypted_key:
          type: string
          pattern: ^[A-Za-z0-9_-]+$
          description: >-
            The per-response AES-256 key, wrapped with the customer's RSA public
            key using RSA-OAEP-256.
        iv:
          type: string
          pattern: ^[A-Za-z0-9_-]+$
          description: base64url of the 12-byte AES-GCM IV (fresh per response).
        ciphertext:
          type: string
          pattern: ^[A-Za-z0-9_-]+$
          description: base64url of the AES-256-GCM ciphertext.
        tag:
          type: string
          pattern: ^[A-Za-z0-9_-]+$
          description: base64url of the 16-byte AES-GCM authentication tag.
    Session:
      type: object
      additionalProperties: false
      required:
        - id
        - channel
        - environment
        - status
        - containmentType
        - createdAt
        - lastActivityAt
        - endedAt
        - messageCount
        - traceEventCount
        - tokenCount
        - traceDimensions
        - estimatedCost
        - durationMs
        - idleDurationMs
        - isTest
      properties:
        id:
          type: string
          description: >
            The session identifier. Use it with the conversation-history and
            traces endpoints.
        channel:
          type: string
          description: >
            The channel the conversation came in on, exactly as recorded — not
            grouped

            into a family the way the `channel` filter is. Empty when no channel
            was

            recorded.
          enum:
            - ''
            - http_async
            - slack
            - line
            - msteams
            - whatsapp
            - messenger
            - instagram
            - twilio_sms
            - zendesk
            - telegram
            - genesys
            - genesys_open_messaging
            - ai4w
            - kore_agent_assist
            - email
            - voice_vxml
            - korevg
            - audiocodes
            - genesys_audio_connector
            - voice_pipeline
            - voice_realtime
            - voice
            - voice_twilio
            - voice_livekit
            - ag_ui
            - a2a
            - sdk_websocket
            - web_debug
            - web_chat
            - api
            - http
        environment:
          type: string
          description: Empty when the source column is null.
          enum:
            - ''
            - development
            - staging
            - production
            - working-copy
        status:
          type: string
          description: >
            The session's state. `failed` can appear here even though it cannot
            be used

            as a `status` filter value. Empty when no status was recorded.
          enum:
            - ''
            - active
            - idle
            - ended
            - completed
            - failed
            - escalated
            - abandoned
            - archived
        containmentType:
          description: >
            How the session was resolved — whether the agent handled it or it
            went to a human.
          type: string
          enum:
            - contained
            - contained_resolved
            - contained_partial
            - contained_unresolved
            - escalated
            - abandoned
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
          description: |
            When the session started.
        lastActivityAt:
          type:
            - string
            - 'null'
          format: date-time
          description: |
            When the last message or event occurred in the session.
        endedAt:
          type:
            - string
            - 'null'
          format: date-time
          description: |
            When the session ended. Null while it is still open.
        messageCount:
          $ref: '#/components/schemas/MessageCount'
        traceEventCount:
          $ref: '#/components/schemas/TraceEventCount'
        tokenCount:
          $ref: '#/components/schemas/TokenCount'
        traceDimensions:
          description: |
            Custom dimensions recorded against the session, as key/value pairs.
            Filter on these with the traceDimensions[key] parameter.
          type: object
          additionalProperties:
            type: string
        estimatedCost:
          type: number
          minimum: 0
          description: Estimated cost in the platform billing currency.
        durationMs:
          type: number
          minimum: 0
          description: |
            Total elapsed time from start to end, in milliseconds.
        idleDurationMs:
          type: number
          minimum: 0
          description: >
            Part of the duration where nothing happened — time spent waiting, in
            milliseconds.

            Useful for separating real handling time from waiting.
        isTest:
          type:
            - boolean
            - 'null'
          description: Reserved field; currently returned as null.
    ErrorEnvelope:
      type: object
      required:
        - error
      properties:
        success:
          type: boolean
          const: false
          description: |
            Always false on an error response.
        error:
          description: >
            Details of what went wrong. `code` is a stable machine-readable
            value; `message` is

            human-readable.
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: object
              additionalProperties: true
        message:
          type: string
          description: >-
            Present on some authorization denials in addition to
            `error.message`.
        required:
          description: >-
            Permission(s) the caller was missing. Present on authorization
            denials.
          oneOf:
            - type: string
            - type: array
              items:
                type: string
    MessageCount:
      type: object
      additionalProperties: false
      required:
        - user
        - agent
        - total
      properties:
        user:
          type: number
          minimum: 0
          description: |
            Messages sent by the end user.
        agent:
          type: number
          minimum: 0
          description: |
            Messages sent by the agent.
        total:
          type: number
          minimum: 0
          description: |
            Total number of trace events recorded for the session.
    TraceEventCount:
      type: object
      additionalProperties: false
      required:
        - llm_call
        - decision
        - tool_call
        - error
        - total
      properties:
        llm_call:
          type: number
          minimum: 0
          description: |
            Number of LLM calls made during the session.
        decision:
          type: number
          minimum: 0
          description: |
            Number of agent decisions taken, such as routing choices.
        tool_call:
          type: number
          minimum: 0
          description: |
            Number of tool calls made.
        error:
          type: number
          minimum: 0
          description: |
            Number of failed events during the session.
        total:
          type: number
          minimum: 0
          description: |
            Total number of trace events recorded for the session.
    TokenCount:
      type: object
      additionalProperties: false
      required:
        - inputTokens
        - cachedTokens
        - completionTokens
        - reasoningTokens
        - outputTokens
        - totalTokens
      properties:
        inputTokens:
          type: number
          minimum: 0
          description: |
            Tokens in the prompts sent to models across the session.
        cachedTokens:
          type: number
          minimum: 0
          description: >
            Input tokens served from the provider prompt cache. Part of
            inputTokens, and usually

            cheaper.
        completionTokens:
          type: number
          minimum: 0
          description: |
            Tokens generated as answers, not counting reasoning tokens.
        reasoningTokens:
          type: number
          minimum: 0
          description: >
            Tokens spent on internal model reasoning. Billed as output but not
            part of any visible

            answer.
        outputTokens:
          type: number
          minimum: 0
          description: |
            All tokens produced by models — answers plus reasoning.
        totalTokens:
          type: number
          minimum: 0
          description: |
            Input plus output tokens for the whole session.
  responses:
    BadRequest:
      description: >
        Invalid or unsupported filters, pagination, date range, or
        required-filter

        combination.


        Encryption and POST-body errors also return 400:
        `ENCRYPTED_PAYLOAD_INVALID`

        (malformed, unexpected or undecryptable JWE, or a plain body for a

        request-encrypted key), `INVALID_REQUEST_BODY` (POST body is not a JSON
        object),

        and `INVALID_QUERY_PARAMETER` (unknown, null or nested POST body key, or
        a query

        string on a POST).


        `INVALID_CALLER_NUMBER`: the `callerNumber` parameter is present but an
        entry is

        empty or has no letter or digit after cleanup (an empty value, only
        separators,

        a trailing or doubled comma, only whitespace, invisible characters or

        punctuation such as `+`, or an empty POST array), is not a string, or is
        longer

        than 512 characters. Any caller format, including bare

        digits and national formats, is accepted. The message names the position
        of

        the offending entry and never echoes it.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorEnvelope'
              - $ref: '#/components/schemas/EncryptedResponse'
    Unauthorized:
      description: Missing or invalid `x-api-key`, or an Authorization header was supplied.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Forbidden:
      description: >
        The key lacks `session:read` for its bound project, or
        (`CALLER_NUMBER_LOOKUP_DISABLED`)

        the request used `callerNumber` while the project's reporting exposure
        config

        disables the `identity` field group.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorEnvelope'
              - $ref: '#/components/schemas/EncryptedResponse'
    NotFound:
      description: >-
        Project not found or deliberately concealed because it is outside the
        key's project scope.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorEnvelope'
              - $ref: '#/components/schemas/EncryptedResponse'
    ResponseTooLarge:
      description: A single session cannot fit within the 1 MiB response budget.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorEnvelope'
              - $ref: '#/components/schemas/EncryptedResponse'
    RateLimited:
      description: Tenant request rate limit exceeded.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorEnvelope'
              - $ref: '#/components/schemas/EncryptedResponse'
    InternalError:
      description: >
        Unexpected query failure.


        Also returned, with a content-free body, when a response cannot be
        encrypted for

        a response-encrypted key.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorEnvelope'
              - $ref: '#/components/schemas/EncryptedResponse'
    Unavailable:
      description: >
        Analytics backing store unavailable.


        `ENCRYPTION_CONFIG_UNAVAILABLE` (with `Retry-After: 30`) means the
        Platform

        Key's payload-encryption configuration could not be read. There is no
        plaintext

        fallback.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorEnvelope'
              - $ref: '#/components/schemas/EncryptedResponse'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Project-bound API key. Do not send an Authorization header with this
        API.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.