openapi: 3.1.0
info:
  title: Fluxtail Stream API
  version: 1.0.0
  description: Public account-isolated log and analytics reads.
servers:
  - url: https://stream.fluxtail.io
security:
  - bearerAuth: []
    activeAccount: []
paths:
  /api/v1/logs:
    get:
      summary: Read retained logs
      parameters:
        - $ref: '#/components/parameters/ActiveAccount'
        - { name: streamId, in: query, schema: { type: string }, description: Comma-separated or repeated stream UUIDs }
        - { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 1000, default: 100 } }
        - { name: since, in: query, schema: { type: string }, description: Cursor for newer logs }
        - { name: cursor, in: query, schema: { type: string }, description: Cursor for older logs }
        - { name: logId, in: query, schema: { type: string, format: uuid } }
        - { name: sinceTime, in: query, schema: { type: string, format: date-time } }
        - { name: untilTime, in: query, schema: { type: string, format: date-time } }
        - { name: search, in: query, schema: { type: string } }
        - { name: severity, in: query, schema: { type: string } }
        - { name: host, in: query, schema: { type: string } }
        - { name: serviceName, in: query, schema: { type: string } }
        - { name: serviceNamespace, in: query, schema: { type: string } }
        - { name: label, in: query, schema: { type: array, items: { type: string } }, style: form, explode: true }
      responses:
        '200':
          description: Retained logs and a continuation cursor
          content:
            application/json:
              schema:
                type: object
                required: [logs]
                properties:
                  logs: { type: array, items: { type: object, additionalProperties: true } }
                  cursor:
                    oneOf:
                      - $ref: '#/components/schemas/Cursor'
                      - type: 'null'
        '401': { description: Token is missing or invalid }
        '403': { description: Account or scope is denied }
  /api/v1/histogram:
    get:
      summary: Read a log histogram
      parameters:
        - $ref: '#/components/parameters/ActiveAccount'
        - { name: startTime, in: query, required: true, schema: { type: string, format: date-time } }
        - { name: endTime, in: query, required: true, schema: { type: string, format: date-time } }
        - { name: buckets, in: query, schema: { type: integer, minimum: 1, maximum: 500, default: 60 } }
      responses:
        '200': { description: Start-relative histogram buckets }
        '401': { description: Token is missing or invalid }
        '403': { description: Account or scope is denied }
  /api/v1/facets:
    get:
      summary: Read one facet
      parameters:
        - $ref: '#/components/parameters/ActiveAccount'
        - { name: field, in: query, required: true, schema: { $ref: '#/components/schemas/FacetField' } }
        - { name: topK, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 10 } }
      responses:
        '200': { description: Facet values and counts }
        '401': { description: Token is missing or invalid }
        '403': { description: Account or scope is denied }
  /api/v1/facets/batch:
    get:
      summary: Read multiple facets
      parameters:
        - $ref: '#/components/parameters/ActiveAccount'
        - { name: fields, in: query, schema: { type: string } }
        - { name: topK, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 15 } }
      responses:
        '200': { description: Map of facet names to values and counts }
        '401': { description: Token is missing or invalid }
        '403': { description: Account or scope is denied }
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
    activeAccount:
      type: apiKey
      in: header
      name: X-Active-Account
  parameters:
    ActiveAccount:
      name: X-Active-Account
      in: header
      required: true
      schema: { type: string, format: uuid }
  schemas:
    Cursor:
      type: object
      required: [timestamp, logId]
      properties:
        timestamp: { type: string, format: date-time }
        logId: { type: string, format: uuid }
    FacetField:
      type: string
      enum: [severity, host, service_name, service_namespace, stream, k8s_namespace, k8s_deployment_name, k8s_pod_name, k8s_container_name, k8s_node_name, k8s_cluster_name]
