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

# Run analytics query

> Runs a batch of 1 to 12 query specs and returns a `columns` and `rows` table for each item. The server applies the caller's organization and hub scope. A malformed spec fails the whole request (422), while a cost limit or engine failure fails only that item inside a 200 response. Rate-limited to 60 requests per minute per user. See the [Dashboard overview](/api-reference/analytics/dashboard-overview) for time ranges, limits and item statuses.



## OpenAPI

````yaml /openapi/public/openapi-analytics.json post /analytics/query
openapi: 3.0.0
info:
  title: MileApp API - Analytics
  version: 3.0.0
  description: MileApp API Documentation - RESTful API for field operations management.
servers:
  - url: https://apiweb.mile.app/api/v3
security:
  - bearerAuth: []
tags:
  - name: Dashboard
    description: >-
      Dashboard lets a user compose their own dashboard from any number of
      cards, start from a template, duplicate a dashboard, share it with roles,
      and save it back as an organization template. Each card owns its own
      widget row (a chart type plus a query spec), cloned from the widget
      catalogue (built-in widgets plus the organization's custom widgets), so
      renaming or editing a card never touches the catalogue or another
      dashboard. Dashboards are owned by their creator: roles they are shared
      with can view, duplicate and save as template, but only the owner can edit
      or delete. Every write reuses the dashboard permission family (view, add,
      edit and delete dashboard).


      The numbers behind each card come from one generic aggregation endpoint
      instead of one endpoint per chart: the client sends a batch of up to 12
      declarative query specs, the server injects the caller's organization, hub
      and soft-delete scope from the session, runs each spec read-only, and
      returns a flat columns and rows table per item. The catalog endpoints
      describe the data sources, fields and limits a client may use.
paths:
  /analytics/query:
    post:
      tags:
        - Dashboard
      summary: Run analytics query
      description: >-
        Runs a batch of 1 to 12 query specs and returns a `columns` and `rows`
        table for each item. The server applies the caller's organization and
        hub scope. A malformed spec fails the whole request (422), while a cost
        limit or engine failure fails only that item inside a 200 response.
        Rate-limited to 60 requests per minute per user. See the [Dashboard
        overview](/api-reference/analytics/dashboard-overview) for time ranges,
        limits and item statuses.
      operationId: runAnalyticsQuery
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - queries
              properties:
                queries:
                  type: array
                  minItems: 1
                  maxItems: 12
                  items:
                    type: object
                    required:
                      - id
                      - spec
                    properties:
                      id:
                        type: string
                        description: >-
                          Any non-empty string, echoed verbatim (normally the
                          card's `cardId`)
                      widgetId:
                        type: string
                        description: Optional; echoed and logged only
                      spec:
                        type: object
                        required:
                          - dataSourceId
                          - timeField
                          - measures
                        properties:
                          specVersion:
                            type: integer
                            enum:
                              - 1
                            default: 1
                          dataSourceId:
                            type: string
                            description: >-
                              `task`, `user`, `task_detail` (always unavailable
                              today), or a 24-hex ObjectId
                          timeField:
                            type: string
                            description: >-
                              Required on every spec. Must be one of the
                              source's `timeFieldCandidates` (task: createdTime,
                              updatedTime, startTime, endTime, doneTime; user:
                              createdTime, updatedTime - recorded but not
                              applied, the user source is timeless).
                          timeRange:
                            type: object
                            description: >-
                              Either `preset`, or both `from` and `to` as
                              calendar dates `YYYY-MM-DD` (anything else,
                              including `2026-02-30`, relative words and
                              datetimes, is `422 time_range_invalid`), widened
                              to whole days on the batch `utcOffset`. Maximum 31
                              days, inclusive.
                            properties:
                              preset:
                                type: string
                                enum:
                                  - today
                                  - yesterday
                                  - last_7d
                                  - last_30d
                              from:
                                type: string
                              to:
                                type: string
                          measures:
                            type: array
                            minItems: 1
                            maxItems: 3
                            items:
                              type: object
                              required:
                                - id
                                - fn
                              properties:
                                id:
                                  type: string
                                  description: Stable id, unique within `measures`
                                fn:
                                  type: string
                                  enum:
                                    - count
                                    - cardinality
                                    - avg
                                    - sum
                                    - min
                                    - max
                                field:
                                  type: string
                                  description: >-
                                    Required for every `fn` except `count`.
                                    `cardinality` needs a distinct-countable
                                    field; `avg`/`sum`/`min`/`max` a metricable
                                    one.
                                missing:
                                  type: string
                                  enum:
                                    - skip
                                    - zero
                                  default: skip
                                label:
                                  type: string
                                  description: Echoed only
                          dimensions:
                            type: array
                            maxItems: 2
                            items:
                              type: object
                              required:
                                - id
                                - kind
                                - field
                              properties:
                                id:
                                  type: string
                                kind:
                                  type: string
                                  enum:
                                    - terms
                                    - dateHistogram
                                    - geoGrid
                                  description: >-
                                    Explicit discriminator; never inferred from
                                    the field type
                                field:
                                  type: string
                                limit:
                                  type: integer
                                  minimum: 1
                                  maximum: 1000
                                  description: >-
                                    Mandatory for `terms`; never defaulted. A
                                    high-cardinality field is capped at 50 and
                                    may only be the first dimension.
                                granularity:
                                  type: string
                                  enum:
                                    - minute
                                    - hour
                                    - day
                                    - week
                                    - month
                                    - quarter
                                    - year
                                  description: '`dateHistogram` only'
                                timezone:
                                  type: string
                                  description: >-
                                    Accepted for stored specs and ignored:
                                    buckets are cut on the batch `utcOffset`,
                                    the same clock as the time range
                                gapFill:
                                  type: string
                                  enum:
                                    - 'null'
                                    - none
                                  default: 'null'
                                  description: >-
                                    `null` keeps empty buckets as rows of nulls;
                                    `none` drops them
                                precision:
                                  type: integer
                                  minimum: 0
                                  maximum: 6
                                  default: 3
                                  description: >-
                                    `geoGrid` only: decimal places of the
                                    rounded cell centre
                                label:
                                  type: string
                          filters:
                            type: array
                            items:
                              type: object
                              required:
                                - id
                                - field
                                - operator
                              properties:
                                id:
                                  type: string
                                field:
                                  type: string
                                operator:
                                  type: string
                                  enum:
                                    - eq
                                    - in
                                    - range
                                    - exists
                                value:
                                  description: >-
                                    Scalar for `eq`, array for `in`, object with
                                    any of `gte`/`gt`/`lte`/`lt` for `range`,
                                    ignored for `exists`. Option values are
                                    case-sensitive (`DONE`, not `Done`).
                          sort:
                            type: array
                            items:
                              type: object
                              properties:
                                by:
                                  type: string
                                  description: A measure or dimension id of this spec
                                direction:
                                  type: string
                                  enum:
                                    - asc
                                    - desc
                                  default: desc
                          limit:
                            type: integer
                            minimum: 1
                            maximum: 1000
                            description: Row limit on the flattened result
                          joins:
                            type: array
                            items:
                              type: object
                              additionalProperties: true
                            description: >-
                              Reserved. Absent or `[]` only; a non-empty array
                              is `422 anlyt-006`.
                timeRange:
                  type: object
                  description: >-
                    Either `preset`, or both `from` and `to` as calendar dates
                    `YYYY-MM-DD` (anything else, including `2026-02-30`,
                    relative words and datetimes, is `422 time_range_invalid`),
                    widened to whole days on the batch `utcOffset`. Maximum 31
                    days, inclusive.
                  properties:
                    preset:
                      type: string
                      enum:
                        - today
                        - yesterday
                        - last_7d
                        - last_30d
                    from:
                      type: string
                    to:
                      type: string
                hubIds:
                  type: array
                  items:
                    type: string
                  description: >-
                    Narrow to these hubs: a list of 24-character hex hub ids
                    (anything else is `422 hub_ids_invalid`), each one of the
                    caller's hubs (otherwise `403 hub_not_allowed`). Omitted or
                    `[]` = every hub the caller belongs to; a caller with no hub
                    sees no rows.
                utcOffset:
                  type: string
                  pattern: ^[+-]\d{2}:\d{2}$
                  example: '+07:00'
                  description: >-
                    Optional. The UTC offset (`±HH:MM`) day boundaries and
                    `dateHistogram` buckets are cut on. Absent = the
                    organization calendar (`Asia/Jakarta`, +07:00). Anything
                    else is `422 utc_offset_invalid`.
                mode:
                  type: string
                  enum:
                    - debug
                  description: >-
                    Request the compiled engine query (internal accounts only;
                    ignored otherwise)
                specVersion:
                  type: integer
                  description: >-
                    Accepted at batch level; the spec-level value is the one
                    validated
              example:
                timeRange:
                  preset: last_30d
                hubIds:
                  - 6650c2a1f3b9e4001c7d2c30
                queries:
                  - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3E
                    widgetId: 66f9a1c2e4b0a7d3c1f20b01
                    spec:
                      specVersion: 1
                      dataSourceId: task
                      timeField: startTime
                      measures:
                        - id: m1
                          fn: count
                      dimensions:
                        - id: d1
                          kind: dateHistogram
                          field: startTime
                          granularity: day
                          gapFill: 'null'
                      filters:
                        - id: f1
                          field: status
                          operator: eq
                          value: DONE
                  - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3F
                    spec:
                      specVersion: 1
                      dataSourceId: task
                      timeField: startTime
                      measures:
                        - id: m1
                          fn: count
                      dimensions:
                        - id: d1
                          kind: terms
                          field: flow
                          limit: 10
                      filters: []
                      sort:
                        - by: m1
                          direction: desc
                  - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3G
                    spec:
                      specVersion: 1
                      dataSourceId: task
                      timeField: doneTime
                      timeRange:
                        from: '2026-08-01'
                        to: '2026-09-15'
                      measures:
                        - id: m1
                          fn: avg
                          field: travelDuration
                      dimensions: []
                      filters: []
                  - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3H#active
                    spec:
                      specVersion: 1
                      dataSourceId: task
                      timeField: startTime
                      measures:
                        - id: m1
                          fn: cardinality
                          field: assignee
                      dimensions: []
                      filters: []
                  - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3H#total
                    spec:
                      specVersion: 1
                      dataSourceId: user
                      timeField: createdTime
                      measures:
                        - id: m1
                          fn: count
                      dimensions: []
                      filters: []
                  - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3J
                    spec:
                      specVersion: 1
                      dataSourceId: task
                      timeField: doneTime
                      measures:
                        - id: count
                          fn: count
                      dimensions:
                        - id: cell
                          kind: geoGrid
                          field: doneCoordinate
                          precision: 3
                      filters: []
        description: Batch of up to 12 queries
        required: true
      responses:
        '200':
          description: >-
            Success - one result per item, in request order. Individual items
            can still be `error`, `timeout`, `no_data` or `no_permission`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: true
                  specVersion:
                    type: integer
                    example: 1
                  resolvedTimeRange:
                    type: object
                    properties:
                      from:
                        type: string
                        format: date-time
                      to:
                        type: string
                        format: date-time
                      timezone:
                        type: string
                      preset:
                        type: string
                        description: '`null` for an absolute range'
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: The request item's `id`, echoed verbatim
                        status:
                          type: string
                          enum:
                            - ok
                            - no_data
                            - error
                            - timeout
                            - no_permission
                        widgetId:
                          type: string
                          description: Present only when the request item carried one
                        columns:
                          type: array
                          items:
                            type: object
                            description: >-
                              Every column is `{id, role, fn, type, field,
                              unit}` (`fn` on measures only). `type` is the
                              platform type of the column's field - `dateTime`,
                              `option`, `text`, `number` - and is always
                              `number` for a measure. (`type` is left out of the
                              schema and example on this page only because the
                              docs build rewrites keys named `type`; the API
                              does return it.)
                            properties:
                              id:
                                type: string
                              role:
                                type: string
                                enum:
                                  - dimension
                                  - measure
                              fn:
                                type: string
                                description: Measures only
                              field:
                                type: string
                              unit:
                                type: string
                        rows:
                          type: array
                          items:
                            type: array
                            items:
                              type: object
                              additionalProperties: true
                          description: >-
                            Positional arrays matching `columns`. A missing
                            value is `null`, never 0.
                        meta:
                          type: object
                          properties:
                            bucketCount:
                              type: integer
                            rowCount:
                              type: integer
                            truncated:
                              type: boolean
                              description: >-
                                A `terms` bucket list or the root `limit` cut
                                rows
                            fanOut:
                              type: boolean
                              description: >-
                                A dimension groups by an array field
                                (`assignee`): bucket totals can exceed the
                                document total
                            partial:
                              type: boolean
                              description: >-
                                Elasticsearch timed out and returned partial
                                results
                            tookMs:
                              type: integer
                        error:
                          type: object
                          properties:
                            code:
                              type: string
                            message:
                              type: string
                          description: >-
                            On `error` and `no_permission`; on `timeout` only
                            `message`
                        debug:
                          type: object
                          description: 'Only for `mode: "debug"` from an internal account'
                          properties:
                            engine:
                              type: string
                            indices:
                              type: array
                              items:
                                type: string
                            query:
                              type: object
                              additionalProperties: true
                            appliedVisibility:
                              type: array
                              items:
                                type: string
                            estimatedBuckets:
                              type: integer
                            tookMs:
                              type: integer
              examples:
                response:
                  value:
                    status: true
                    specVersion: 1
                    resolvedTimeRange:
                      from: '2026-09-01T00:00:00+07:00'
                      to: '2026-09-30T23:59:59+07:00'
                      timezone: Asia/Jakarta
                      preset: last_30d
                    results:
                      - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3E
                        status: ok
                        widgetId: 66f9a1c2e4b0a7d3c1f20b01
                        columns:
                          - id: d1
                            role: dimension
                            field: startTime
                            unit: null
                          - id: m1
                            role: measure
                            fn: count
                            field: null
                            unit: plain
                        rows:
                          - - '2026-09-01T00:00:00+07:00'
                            - 212
                          - - '2026-09-02T00:00:00+07:00'
                            - null
                          - - '2026-09-03T00:00:00+07:00'
                            - 198
                        meta:
                          bucketCount: 30
                          rowCount: 30
                          truncated: false
                          fanOut: false
                          partial: false
                          tookMs: 4
                      - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3F
                        status: ok
                        columns:
                          - id: d1
                            role: dimension
                            field: flow
                            unit: null
                          - id: m1
                            role: measure
                            fn: count
                            field: null
                            unit: plain
                        rows:
                          - - Delivery
                            - 812
                          - - Pickup
                            - 140
                        meta:
                          bucketCount: 2
                          rowCount: 2
                          truncated: false
                          fanOut: false
                          partial: false
                          tookMs: 3
                      - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3G
                        status: error
                        error:
                          code: time_range_exceeded
                          message: >-
                            This widget asked for a 46 day range, but the limit
                            is 31 days. Narrow the range rather than expecting a
                            trimmed result.
                      - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3H#active
                        status: ok
                        columns:
                          - id: m1
                            role: measure
                            fn: cardinality
                            field: assignee
                            unit: plain
                        rows:
                          - - 37
                        meta:
                          bucketCount: 1
                          rowCount: 1
                          truncated: false
                          fanOut: false
                          partial: false
                          tookMs: 2
                      - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3H#total
                        status: ok
                        columns:
                          - id: m1
                            role: measure
                            fn: count
                            field: null
                            unit: plain
                        rows:
                          - - 52
                        meta:
                          bucketCount: 1
                          rowCount: 1
                          truncated: false
                          fanOut: false
                          partial: false
                          tookMs: 1
                      - id: crd_01J8ZQ4R5W6X7Y8Z9A0B1C2D3J
                        status: ok
                        columns:
                          - id: lat
                            role: dimension
                            field: doneCoordinate
                            unit: latitude
                          - id: lng
                            role: dimension
                            field: doneCoordinate
                            unit: longitude
                          - id: count
                            role: measure
                            fn: count
                            field: null
                            unit: plain
                        rows:
                          - - -6.2
                            - 106.817
                            - 318
                          - - -6.914
                            - 107.609
                            - 201
                        meta:
                          scanned: 519
                          scanCap: 10000
                          scanTruncated: false
                          parsed: 519
                          skipped: 0
                          returned: 2
                          cellCap: 5000
                          cellTruncated: false
                          precision: 3
        '401':
          description: >-
            Unauthorized - no valid token (`auth-034`), or an authenticated user
            with no organization
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    description: Human-readable reason
                  failedCode:
                    type: string
                    description: Structured error code, see Status Codes
              examples:
                response:
                  value:
                    status: false
                    message: Unauthenticated.
                    failedCode: auth-034
        '403':
          description: >-
            Forbidden - `hub_not_allowed` when `hubIds` names a hub the caller
            does not belong to (no query runs). A role without `view/dashboard`
            gets `sys-035` instead.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Descriptive string code, e.g. `batch_too_large`,
                          `field_unknown`, `hub_not_allowed`
                      message:
                        type: string
                      field:
                        type: string
                        description: Offending key, when known
              examples:
                response:
                  value:
                    status: false
                    message: >-
                      You do not have access to hub(s):
                      6650c2a1f3b9e4001c7d2c31.
                    error:
                      code: hub_not_allowed
                      message: >-
                        You do not have access to hub(s):
                        6650c2a1f3b9e4001c7d2c31.
        '422':
          description: >-
            Unprocessable - the batch or one of its specs is malformed; nothing
            ran. `error.code` names the rule, e.g. `batch_too_large`,
            `queries_empty`, `unknown_key`, `time_range_missing`,
            `time_range_preset_unknown`, `field_unknown`, `field_blocked`,
            `protected_field_rejected`, `terms_limit_required`,
            `too_many_measures`, `option_value_unknown`, `anlyt-006` (non-empty
            `joins`).
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Descriptive string code, e.g. `batch_too_large`,
                          `field_unknown`, `hub_not_allowed`
                      message:
                        type: string
                      field:
                        type: string
                        description: Offending key, when known
              examples:
                response:
                  value:
                    status: false
                    message: This request carries 14 queries, but the limit is 12.
                    error:
                      code: batch_too_large
                      message: This request carries 14 queries, but the limit is 12.
        '429':
          description: Too Many Requests - more than 60 requests in a minute
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    description: Human-readable reason
                  failedCode:
                    type: string
                    description: Structured error code, see Status Codes
              examples:
                response:
                  value:
                    status: false
                    message: Too Many Attempts.
                    failedCode: sys-036
      security:
        - bearerAuth: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Use a valid Bearer token to authenticate.

````

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