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

# API request numbers per tenant and UTC day

> From `api.metrics_daily`. For each tenant and service the source is
chosen over the whole range: metric rows when the service has any,
otherwise span rows (control-plane-api 7.3); the two are never added.
One item per tenant and day with requests, over every service or the
one named by `service`. Equal to the daily series of
`GET /api/operator/api/compare` for the same range.




## OpenAPI

````yaml /reference/openapi/metrics-v1.yaml get /api/daily
openapi: 3.1.0
info:
  title: Veristar machine metrics API
  version: 1.0.0
  summary: Read-only aggregate web and API metrics for downstream machine consumers.
  description: |
    The contract of `/api/metrics/v1/` (plan phase 12,
    docs/reference/control-plane-api.md section 9). Every request carries an
    operator API key as `Authorization: Bearer sa_op_<40 base62 characters>`.
    Console session cookies are never accepted here, and keys are accepted
    nowhere else.

    Conventions shared by every route:

    * Only `GET` is defined. Every answer carries `Cache-Control: no-store`
      and `X-Request-Id`.
    * A query parameter that the route does not list, or one given twice, is
      400 `invalid_query`.
    * Days are UTC days `yyyy-mm-dd`; hours are RFC 3339 UTC hour starts such
      as `2026-11-12T09:00:00Z`. Ranges include both ends.
    * A key scoped to one tenant reads only that tenant. Naming another
      tenant is 403 `scope_forbidden`. A key for all tenants never sees
      internal tenants (the monitoring probe); naming one is 404.
    * List routes return at most `limit` items (1 to 500, default 500) and an
      opaque `next_cursor`, `null` on the last page. A cursor is bound to the
      route and every other query parameter; with any other combination it
      is 400 `invalid_cursor`. The range a cursor carries is checked again on
      every page with the limits of a first page; a cursor that breaks them
      is 400 `invalid_cursor`.
    * Each key may make 10 requests per second per control plane instance
      (token bucket, burst 20). Above that the answer is 429 `rate_limited`
      with `Retry-After` in seconds.
    * Percentiles come from summed histogram buckets and are never averaged.
      A percentile in the open bucket above 10 s has `*_seconds: null` and
      `*_over_10s: true`.
  license:
    name: Apache-2.0
    identifier: Apache-2.0
servers:
  - url: /api/metrics/v1
security:
  - operatorKey: []
paths:
  /api/daily:
    get:
      summary: API request numbers per tenant and UTC day
      description: |
        From `api.metrics_daily`. For each tenant and service the source is
        chosen over the whole range: metric rows when the service has any,
        otherwise span rows (control-plane-api 7.3); the two are never added.
        One item per tenant and day with requests, over every service or the
        one named by `service`. Equal to the daily series of
        `GET /api/operator/api/compare` for the same range.
      operationId: apiDaily
      parameters:
        - $ref: '#/components/parameters/tenant'
        - $ref: '#/components/parameters/service'
        - $ref: '#/components/parameters/fromDay'
        - $ref: '#/components/parameters/toDay'
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/cursor'
      responses:
        '200':
          description: One page of daily rows.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIDailyList'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/Internal'
components:
  parameters:
    tenant:
      name: tenant
      in: query
      required: false
      description: >-
        One tenant id. A scoped key defaults to its own tenant; a key for all
        tenants reads every non-internal tenant when absent.
      schema:
        $ref: '#/components/schemas/ID'
    service:
      name: service
      in: query
      required: false
      description: >-
        Exact `service.name`. An empty value matches points without one. At most
        128 bytes, no control characters.
      schema:
        type: string
        maxLength: 128
    fromDay:
      name: from
      in: query
      required: false
      description: First UTC day (included). Default 29 days before `to`.
      schema:
        $ref: '#/components/schemas/Day'
    toDay:
      name: to
      in: query
      required: false
      description: >-
        Last UTC day (included), not after today. Default today. At most 366
        days in one request.
      schema:
        $ref: '#/components/schemas/Day'
    limit:
      name: limit
      in: query
      required: false
      schema:
        type: integer
        minimum: 1
        maximum: 500
        default: 500
    cursor:
      name: cursor
      in: query
      required: false
      description: The `next_cursor` of the previous page.
      schema:
        type: string
        minLength: 1
  headers:
    X-Request-Id:
      description: The id of the request, also in the error envelope and the server log.
      schema:
        type: string
    Retry-After:
      description: Seconds to wait before the next request.
      required: true
      schema:
        type: string
        pattern: ^[1-9][0-9]*$
  schemas:
    APIDailyList:
      type: object
      additionalProperties: false
      required:
        - from
        - to
        - items
        - next_cursor
      properties:
        from:
          $ref: '#/components/schemas/Day'
        to:
          $ref: '#/components/schemas/Day'
        items:
          type: array
          items:
            $ref: '#/components/schemas/APIDaily'
        next_cursor:
          $ref: '#/components/schemas/Cursor'
    ID:
      type: string
      pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
    Day:
      type: string
      pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}$
    APIDaily:
      type: object
      additionalProperties: false
      required:
        - tenant_id
        - day
        - services
        - span_services
        - source
        - requests
        - requests_4xx
        - requests_5xx
        - rate_4xx
        - rate_5xx
        - p50_seconds
        - p50_over_10s
        - p95_seconds
        - p95_over_10s
        - p99_seconds
        - p99_over_10s
        - lossy
      allOf:
        - $ref: '#/components/schemas/APINumbers'
      properties:
        tenant_id:
          $ref: '#/components/schemas/ID'
        day:
          $ref: '#/components/schemas/Day'
        services:
          $ref: '#/components/schemas/Count'
        span_services:
          description: Services whose numbers are derived from spans.
          allOf:
            - $ref: '#/components/schemas/Count'
        source:
          type: string
          enum:
            - metric
            - span
            - mixed
        requests: true
        requests_4xx: true
        requests_5xx: true
        rate_4xx: true
        rate_5xx: true
        p50_seconds: true
        p50_over_10s: true
        p95_seconds: true
        p95_over_10s: true
        p99_seconds: true
        p99_over_10s: true
        lossy: true
    Cursor:
      type:
        - string
        - 'null'
      description: Opaque position of the next page, `null` on the last page.
    Error:
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          type: object
          additionalProperties: false
          required:
            - code
            - message
            - request_id
          properties:
            code:
              type: string
              enum:
                - invalid_query
                - invalid_cursor
                - unauthenticated
                - scope_forbidden
                - not_found
                - method_not_allowed
                - rate_limited
                - internal
                - unavailable
            message:
              type: string
            request_id:
              type: string
    APINumbers:
      type: object
      required:
        - requests
        - requests_4xx
        - requests_5xx
        - rate_4xx
        - rate_5xx
        - p50_seconds
        - p50_over_10s
        - p95_seconds
        - p95_over_10s
        - p99_seconds
        - p99_over_10s
        - lossy
      properties:
        requests:
          $ref: '#/components/schemas/Count'
        requests_4xx:
          $ref: '#/components/schemas/Count'
        requests_5xx:
          $ref: '#/components/schemas/Count'
        rate_4xx:
          $ref: '#/components/schemas/Rate'
        rate_5xx:
          $ref: '#/components/schemas/Rate'
        p50_seconds:
          type:
            - number
            - 'null'
          minimum: 0
        p50_over_10s:
          type: boolean
        p95_seconds:
          type:
            - number
            - 'null'
          minimum: 0
        p95_over_10s:
          type: boolean
        p99_seconds:
          type:
            - number
            - 'null'
          minimum: 0
        p99_over_10s:
          type: boolean
        lossy:
          type: boolean
          description: Some row was re-bucketed inexactly, so percentiles are approximate.
    Count:
      type: integer
      minimum: 0
    Rate:
      type:
        - number
        - 'null'
      minimum: 0
      maximum: 1
      description: A fraction of requests; `null` without requests.
  responses:
    BadRequest:
      description: >-
        A malformed or unknown query parameter (`invalid_query`) or cursor
        (`invalid_cursor`).
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthenticated:
      description: >-
        No key, a malformed or unknown key, or an expired or revoked key
        (`unauthenticated`).
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
        WWW-Authenticate:
          required: true
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: The key is scoped to another tenant (`scope_forbidden`).
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: >-
        Unknown path, or a tenant that does not exist or is internal
        (`not_found`).
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: The key's token bucket is empty (`rate_limited`).
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
        Retry-After:
          $ref: '#/components/headers/Retry-After'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Internal:
      description: Anything unexpected (`internal`); details only in the server log.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    operatorKey:
      type: http
      scheme: bearer
      description: An operator API key, `sa_op_` followed by 40 base62 characters.

````

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