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

# Explore query volume over time

> Executes an Explore query and returns its Volume Over Time: matching mention volume aggregated into daily buckets, one per UTC calendar day in the requested date range. Use the optional `group_by` field to break each bucket down by channel, domain, or language.

### Rate limits and quota

- **5 queries per user per minute**, shared with `POST /explore/analytics/distribution`. Exceeding it returns a `429` with `error: "rate_limited"`.
- **1,000 queries per user per month** for this endpoint, resetting at the start of each calendar month (UTC). Exceeding it returns a `429` with `error: "quota_exceeded"`.

Every request counts toward the per-minute limit; only successful (`200`) requests count toward the monthly quota. Both limits are shared with the Explore tools in the [PeakMetrics MCP server](/mcp/capabilities).




## OpenAPI

````yaml /api/api_docs.yaml post /explore/analytics/timeline
openapi: 3.1.0
info:
  title: PeakMetrics API
  description: >
    The PeakMetrics API provides programmatic access to narrative intelligence
    data.


    Access millions of mentions across news, social media, and online platforms,
    enriched with custom AI-powered

    smart categories and over 50 metadata properties. The API enables you to

    identify, analyze, and act on emerging narratives in real-time.
  version: 2.0.0
servers:
  - url: https://api.peakmetrics.com
    description: Main (production) server
security:
  - BearerAuth: []
tags:
  - name: Authorization
  - name: Workspaces
  - name: Explore
    description: >
      Run an ad-hoc [Explore](/help/get-started-with-peakmetrics/explore) query
      without creating a workspace, and get back Volume Over Time (`POST
      /explore/analytics/timeline`) or a Channel, Language, or Domain
      distribution (`POST /explore/analytics/distribution`).


      Both endpoints use the same Bearer JWT authentication as the rest of the
      API and take their parameters as a JSON body.


      ### Rate limits and quota


      - **5 queries per user per minute**, shared across both Explore endpoints.
      The minute is a fixed window of 60 seconds from the first request in the
      window. Exceeding it returns a `429` with `error: "rate_limited"` and
      `retryAfterSeconds`.

      - **1,000 queries per user per endpoint per month.** Each endpoint has its
      own monthly allowance, which resets at the start of each calendar month
      (UTC). Exceeding it returns a `429` with `error: "quota_exceeded"` and
      `retryAfterSeconds` set to the time until the reset.


      Every request counts toward the per-minute limit; only successful (`200`)
      requests count toward the monthly quota.


      Both limits are shared with the Explore tools in the [PeakMetrics MCP
      server](/mcp/capabilities), so queries your AI assistant runs there count
      toward the same totals.
  - name: Folders
  - name: Channels
  - name: Locations
    description: >
      PeakMetrics resolves a normalized location on mentions across every
      channel, using a

      six-level taxonomy: `region`, `subregion`, `country`, `state`, `county`,
      and `city`.

      `state` and `county` are United States only.


      Look locations up with `GET /locations`, read a mention's resolved
      location from the

      `location` object on `GET /workspaces/{workspaceId}/mentions`, filter the
      mentions,

      timeline, or distribution endpoints with the `locations.<level>`
      parameters, and

      break counts down with the matching `locations.<level>` `group_by` values.
  - name: Custom Channels
  - name: Custom Enrichments
    description: >
      Custom enrichments let you push external context about mentions into
      PeakMetrics,

      attached to individual mentions and used alongside all other mention
      metadata across

      the platform. Once written, enrichment values feed into narrative
      analysis, workspace

      summaries, and notifications, and are available through the customer API
      and the MCP

      server.


      Your team manages its own custom enrichments through the API: create one
      with

      `POST /customEnrichments`, list them with `GET /customEnrichments`, rename
      one or

      replace its option list with `PUT /customEnrichments/{enrichmentId}`,
      retire one with

      `DELETE /customEnrichments/{enrichmentId}`, and push values for individual
      mentions

      with `PUT /mentions/customEnrichments`.
paths:
  /explore/analytics/timeline:
    post:
      tags:
        - Explore
      summary: Explore query volume over time
      description: >
        Executes an Explore query and returns its Volume Over Time: matching
        mention volume aggregated into daily buckets, one per UTC calendar day
        in the requested date range. Use the optional `group_by` field to break
        each bucket down by channel, domain, or language.


        ### Rate limits and quota


        - **5 queries per user per minute**, shared with `POST
        /explore/analytics/distribution`. Exceeding it returns a `429` with
        `error: "rate_limited"`.

        - **1,000 queries per user per month** for this endpoint, resetting at
        the start of each calendar month (UTC). Exceeding it returns a `429`
        with `error: "quota_exceeded"`.


        Every request counts toward the per-minute limit; only successful
        (`200`) requests count toward the monthly quota. Both limits are shared
        with the Explore tools in the [PeakMetrics MCP
        server](/mcp/capabilities).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/ExploreAnalyticsRequest'
                - type: object
                  properties:
                    group_by:
                      type: string
                      enum:
                        - channels
                        - domains
                        - languages
                      description: >
                        Breakdown dimension:


                        - `channels` — Counts by channel. Each group's `key` is
                        a channel id from your `channels` list; Reddit posts and
                        comments are counted together under `reddit`.

                        - `domains` — Counts by domain: each day's top domains,
                        up to 30 per channel and at most 50 in all.

                        - `languages` — Counts by language. English variants
                        (for example, `en-us` and `en-gb`) are reported as `en`.
                        When `channels` includes `twitter`, the breakdown
                        contains exactly two groups, `en` and `non_en`.
                        Otherwise it contains the full breakdown up to each
                        day's top 30 languages per channel; mentions with no
                        detected language are not listed.


                        When omitted, each bucket's `groups` is returned as an
                        empty array. Any other value is rejected with a `400`.
                      example: channels
            example:
              query: '"Delta Airlines" AND delay'
              channels:
                - news
                - reddit
                - twitter
                - vk
                - weibo
              since: '2026-06-14T00:00:00Z'
              to: '2026-09-14T23:59:59Z'
              group_by: channels
              domains:
                - nytimes.com
                - reddit.com
                - twitter.com
                - vk.com
                - weibo.com
              languages:
                - en
      responses:
        '200':
          description: A JSON object containing time-bucketed mention volume.
          content:
            application/json:
              schema:
                type: object
                required:
                  - totalCount
                  - buckets
                properties:
                  totalCount:
                    type: number
                    minimum: 0
                    description: >
                      Total number of matching mentions across all time buckets.
                      Data for some channels may be estimated from a large-scale
                      firehose sample: Reddit comments, VK, and Weibo are
                      sampled (20%, 20%, and 10% of the firehose, respectively)
                      and their counts are extrapolated from the sample, while
                      News, Reddit posts, and Twitter are counted in full.
                    example: 13100
                  buckets:
                    type: array
                    description: >
                      Mention volume aggregated into daily buckets, oldest
                      first: one bucket for every UTC calendar day in the
                      requested date range. A day with no matching mentions is
                      still returned, with a `count` of `0`.
                    items:
                      type: object
                      required:
                        - date
                        - count
                        - groups
                      properties:
                        date:
                          type: string
                          format: date-time
                          description: >-
                            The start of the bucket's UTC calendar day (00:00:00
                            UTC).
                          example: '2026-06-14T00:00:00Z'
                        count:
                          type: number
                          minimum: 0
                          description: >
                            The number of mentions published during this bucket.
                            Data for some channels may be estimated from a
                            large-scale firehose sample: Reddit comments, VK,
                            and Weibo are sampled (20%, 20%, and 10% of the
                            firehose, respectively) and their counts are
                            extrapolated from the sample, while News, Reddit
                            posts, and Twitter are counted in full.
                          example: 430
                        groups:
                          type: array
                          description: >
                            Breakdown of this bucket by the `group_by`
                            dimension. Always present; an empty array when
                            `group_by` is omitted.


                            With `group_by: "channels"`, each entry's `key` is a
                            channel you requested, with one `reddit` entry for
                            Reddit posts and comments. Channel entries always
                            follow the same order (`news`, `reddit`, `vk`,
                            `weibo`, `twitter`), so each channel keeps its
                            position from bucket to bucket.


                            With `group_by: "domains"`, this contains the day's
                            top domains, up to 30 per channel and at most 50 in
                            all, ordered by count, highest first.


                            With `group_by: "languages"` and `twitter` in
                            `channels`, this contains exactly two entries, `en`
                            and `non_en`. Without `twitter`, it contains the
                            full breakdown up to the day's top 30 languages per
                            channel, ordered by count, highest first; mentions
                            with no detected language are not listed. English
                            variants (for example, `en-us` and `en-gb`) are
                            always reported as `en`.


                            Because of these caps, a bucket's domain groups, and
                            its language groups without `twitter`, need not add
                            up to the bucket's `count`.
                          items:
                            type: object
                            properties:
                              key:
                                type: string
                                description: >
                                  The value for this group: a channel you
                                  requested (e.g., `"reddit"`), a domain (e.g.,
                                  `"nytimes.com"`), or a language (e.g., `"en"`,
                                  `"non_en"`).
                                example: reddit
                              count:
                                type: number
                                minimum: 0
                                description: >
                                  The number of mentions in this group for this
                                  bucket. Data for some channels may be
                                  estimated from a large-scale firehose sample:
                                  Reddit comments, VK, and Weibo are sampled
                                  (20%, 20%, and 10% of the firehose,
                                  respectively) and their counts are
                                  extrapolated from the sample, while News,
                                  Reddit posts, and Twitter are counted in full.
                                example: 90
              example:
                totalCount: 13100
                buckets:
                  - date: '2026-06-14T00:00:00Z'
                    count: 1045
                    groups:
                      - key: news
                        count: 225
                      - key: reddit
                        count: 390
                      - key: vk
                        count: 100
                      - key: weibo
                        count: 150
                      - key: twitter
                        count: 180
        '400':
          $ref: '#/components/responses/ExploreBadRequest'
        '401':
          description: Missing or invalid access token.
        '403':
          $ref: '#/components/responses/ExploreForbidden'
        '429':
          $ref: '#/components/responses/ExploreRateLimited'
        '500':
          $ref: '#/components/responses/ExploreInternalServerError'
      security:
        - BearerAuth: []
components:
  schemas:
    ExploreAnalyticsRequest:
      type: object
      description: >
        The JSON request body shared by `POST /explore/analytics/timeline` and
        `POST /explore/analytics/distribution`. Parameters are sent in the body
        rather than the query string because `query` can contain quotes,
        parentheses, and boolean operators that are awkward to URL-encode, and
        `channels` is an array.
      required:
        - query
        - channels
        - since
        - to
      properties:
        query:
          type: string
          description: >
            The search query to execute. Supports a reduced boolean syntax:
            `AND`, `OR`, `NOT`, parenthetical grouping, and the `title:`,
            `author:`, and `domain:` field scopes. An unparseable query (for
            example, unbalanced parentheses or an unsupported field-scope
            operator) is rejected with a `400`.


            A query can be up to 2,000 characters long and contain up to 100
            terms, where a quoted phrase counts as one term. A query over either
            limit is rejected with a `400`.


            `domain:` terms don't apply to Twitter. When `channels` includes
            `twitter`, Twitter counts ignore any `domain:` terms in the query,
            and a query with nothing left for Twitter without them (for example,
            a query made only of `domain:` terms) is rejected with a `400`.
          example: ("Delta Airlines" OR title:Delta) AND delay NOT domain:example.com
        channels:
          type: array
          minItems: 1
          items:
            type: string
            enum:
              - news
              - reddit
              - twitter
              - vk
              - weibo
          description: >
            The channels to search. Access to each channel is governed by your
            account's channel entitlements, consistent with the rest of the
            PeakMetrics platform. Requesting a channel your account is not
            entitled to is rejected with a `403`.


            `reddit` covers the Reddit posts and comments your account is
            entitled to: posts, comments, or both. It is rejected with a `403`
            only when your account is entitled to neither.
          example:
            - news
            - reddit
            - twitter
            - vk
            - weibo
        since:
          oneOf:
            - title: ISO 8601
              type: string
              format: date-time
            - title: Epoch milliseconds
              type: integer
          description: >
            The minimum published date of the mentions to include. Required,
            along with `to`. Send an ISO 8601 date-time or epoch milliseconds;
            any other value is rejected with a `400`. Dates are aligned to UTC
            day boundaries: the range starts at 00:00:00 UTC on the day `since`
            falls on.


            The range can reach back 12 months from the start of the current UTC
            day. A `since` up to one day earlier than that is clamped to the
            start of the 12-month range; a `since` further back is rejected with
            a `400`, and so is a `since` on a later UTC day than `to` or than
            today.
          example: '2026-06-14T00:00:00Z'
        to:
          oneOf:
            - title: ISO 8601
              type: string
              format: date-time
            - title: Epoch milliseconds
              type: integer
          description: >
            The maximum published date of the mentions to include. Required,
            along with `since`. Send an ISO 8601 date-time or epoch
            milliseconds; any other value is rejected with a `400`. Dates are
            aligned to UTC day boundaries: the range includes the whole UTC day
            `to` falls on. A `to` in the future is clamped to today, so the
            range ends with the current UTC day.
          example: '2026-09-14T23:59:59Z'
        domains:
          type: array
          items:
            type: string
          description: >
            Filter to mentions published on the provided domains. Multiple
            values are combined with OR logic. When omitted, all domains are
            included. Up to 50 values are accepted; more are rejected with a
            `400`.


            When `channels` includes `twitter` and you set `domains`, Twitter is
            counted only if `domains` includes `twitter.com`. Otherwise Twitter
            contributes `0` to every count, and the request still succeeds.
            `x.com` is not an alias for `twitter.com`: list `twitter.com` to
            keep Twitter in the results.
          example:
            - nytimes.com
            - reddit.com
            - twitter.com
            - vk.com
            - weibo.com
        languages:
          type: array
          items:
            type: string
          description: >
            Filter to mentions in the provided languages, specified as
            two-letter ISO 639-1 codes. Codes are case-insensitive, so `EN` is
            the same as `en`. Use `non_en` to match every language other than
            English; `en` also matches regional English variants such as `en-us`
            and `en-gb`. Multiple values are combined with OR logic. When
            omitted, all languages are included. Up to 50 values are accepted;
            more are rejected with a `400`.


            When `channels` includes `twitter`, `languages` may only contain
            `en`, `non_en`, or both. Any other value (for example, a specific
            non-English language code) is rejected with a `400`.
          example:
            - en
    ExploreError:
      type: object
      description: The error shape returned by the Explore analytics endpoints.
      required:
        - error
        - message
      properties:
        error:
          type: string
          enum:
            - invalid_request
            - forbidden
            - rate_limited
            - quota_exceeded
            - internal_server_error
          description: >
            A machine-readable error code: `invalid_request` (`400`),
            `forbidden` (`403`), `rate_limited` or `quota_exceeded` (`429`), or
            `internal_server_error` (`500`).
          example: invalid_request
        message:
          type: string
          description: A human-readable description of the error.
          example: >-
            When 'twitter' is included in channels, languages may only contain
            'en' and/or 'non_en'.
        details:
          type: array
          description: >
            Returned with a `400` only, when the problem is with the fields in
            the request body. Lists every problem found, one entry each;
            `message` describes the first of them.
          items:
            type: object
            required:
              - path
              - message
            properties:
              path:
                type: string
                description: >-
                  The field the problem is with (for example, `since` or
                  `languages`), or `body` when the problem is with the request
                  body as a whole.
                example: languages
              message:
                type: string
                description: A human-readable description of the problem.
                example: >-
                  When 'twitter' is included in channels, languages may only
                  contain 'en' and/or 'non_en'.
    ExploreRateLimitError:
      allOf:
        - $ref: '#/components/schemas/ExploreError'
        - type: object
          required:
            - retryAfterSeconds
          properties:
            error:
              enum:
                - rate_limited
                - quota_exceeded
              example: rate_limited
            message:
              example: >-
                Rate limit of 5 queries per minute exceeded. Try again in 42
                seconds.
            retryAfterSeconds:
              type: integer
              minimum: 0
              description: >
                Seconds to wait before retrying. For `quota_exceeded`, the
                seconds until the monthly quota resets at the start of the next
                calendar month (UTC).
              example: 42
  responses:
    ExploreBadRequest:
      description: >
        The request is invalid. Returned for:


        - missing or malformed required fields, or unknown fields

        - a `since`/`to` value that is not ISO 8601 or epoch milliseconds

        - an unparseable `query` (for example, unbalanced parentheses or an
        unsupported field-scope operator)

        - a `query` longer than 2,000 characters or with more than 100 terms

        - more than 50 values in `domains`, or more than 50 in `languages`

        - a query that X cannot run when `twitter` is included in `channels`
        (for example, a query made only of `domain:` terms, which have no X
        equivalent)

        - an unsupported `group_by` value, or a missing `group_by` on `POST
        /explore/analytics/distribution`

        - a `since` more than one day before the start of the trailing 12
        months, or a `since` on a later UTC day than `to` or than today (a `to`
        in the future is clamped to today rather than rejected)

        - a `languages` filter containing anything other than `en`/`non_en` when
        `twitter` is included in `channels`. Language codes are
        case-insensitive, so `EN` and `NON_EN` are accepted.


        `message` describes the first problem found. When the problem is with
        the fields in the request body, `details` lists every problem found, one
        entry each.


        Every request counts toward the per-minute limit; only successful
        (`200`) requests count toward the monthly quota.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ExploreError'
          example:
            error: invalid_request
            message: >-
              When 'twitter' is included in channels, languages may only contain
              'en' and/or 'non_en'.
            details:
              - path: languages
                message: >-
                  When 'twitter' is included in channels, languages may only
                  contain 'en' and/or 'non_en'.
    ExploreForbidden:
      description: >
        Your account's channel entitlements do not include one of the requested
        channels. The `message` lists the channels you are not authorized for;
        remove them from `channels` and retry. For `reddit`, this happens only
        when your account is entitled to neither Reddit posts nor Reddit
        comments.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ExploreError'
          example:
            error: forbidden
            message: 'not authorized for channels: twitter'
    ExploreRateLimited:
      description: >
        A rate limit or quota was exceeded. The `error` code says which:


        - `rate_limited`: you made more than 5 queries within one minute. The
        limit is per user. The minute is a fixed window of 60 seconds from the
        first request in the window, not a rolling one: once it ends, the count
        starts again. The limit is shared by `POST /explore/analytics/timeline`,
        `POST /explore/analytics/distribution`, and the Explore tools in the
        [PeakMetrics MCP server](/mcp/capabilities).

        - `quota_exceeded`: your monthly quota of 1,000 queries for this
        endpoint is used up. The quota is per user, and each endpoint has its
        own, which resets at the start of the next calendar month (UTC). Queries
        run through the Explore tools in the [PeakMetrics MCP
        server](/mcp/capabilities) count toward the same quotas.


        Every request counts toward the per-minute limit; only successful
        (`200`) requests count toward the monthly quota.


        Wait `retryAfterSeconds` before retrying. The same value is sent in the
        `Retry-After` header.
      headers:
        Retry-After:
          description: >-
            Seconds to wait before retrying, the same value as
            `retryAfterSeconds`.
          schema:
            type: integer
            minimum: 0
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ExploreRateLimitError'
          examples:
            rateLimited:
              summary: Per-minute rate limit exceeded
              value:
                error: rate_limited
                message: >-
                  Rate limit of 5 queries per minute exceeded. Try again in 42
                  seconds.
                retryAfterSeconds: 42
            quotaExceeded:
              summary: Monthly quota exceeded
              description: >-
                Returned at 2026-10-28T12:00:00Z, so `retryAfterSeconds` counts
                down to the reset at 2026-11-01T00:00:00Z.
              value:
                error: quota_exceeded
                message: >-
                  Monthly quota of 1000 queries for this endpoint exceeded.
                  Resets 2026-11-01T00:00:00Z.
                retryAfterSeconds: 302400
    ExploreInternalServerError:
      description: >
        Internal server error. Retry with backoff.


        Explore never returns partial results: a request that cannot be
        completed fails with a `500` rather than returning an undercount.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ExploreError'
          example:
            error: internal_server_error
            message: Internal server error.
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````

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