openapi: 3.1.0
info:
  title: APEX Quantum API
  version: 0.1.0
  summary: Analytics engine of the APEX Suite.
  description: |
    Quantum is the APEX Suite's analytics engine. It runs analytical models
    (anomaly detection, clustering, correlation, trend decomposition, network
    analysis), detects recurring patterns across data dimensions, serves
    trained prediction models, and exposes a model catalog.

    **Quantum is in Preview: analytical outputs are demonstration-grade in the
    current release, and authentication hardening is in progress. Contract
    shapes are stable to build against.**

    Quantum has no cloud deployment yet — it is available for local evaluation
    only, on port 9130.

    ## Tenant carriage

    Every request (except `/health`) must carry the tenant in the
    `X-Tenant-ID` header:

    - Missing header → `400` with error code `MISSING_TENANT`
    - Unknown tenant → `404` with error code `UNKNOWN_TENANT`

    ## Field naming

    Request bodies use camelCase field names (for example `analysisType`,
    `includeVisualization`, `patternTypes`). Prediction responses also use
    camelCase (`changePercent`, `topFactors`, `vectorVerification`); analysis,
    pattern, and model-catalog responses use snake_case fields as documented
    per operation.

    ## Response envelope and errors

    Successful responses are wrapped as `{"ok": true, "data": ..., "requestId": ...}`.
    Errors are wrapped as `{"ok": false, "error": {"code", "message", "detail"?}, "requestId"}`.
    Error codes: `VALIDATION_ERROR` (status 422), `INTERNAL_ERROR` (status
    500), `MODEL_NOT_FOUND` (returned in the error envelope when a requested
    model does not exist — check the `ok` field, as the current release
    delivers it with HTTP status 200), plus the tenant errors above.

    Every response carries `X-Request-ID` and `X-Response-Time` headers.
servers:
  - url: http://localhost:9130
    description: Local
tags:
  - name: Analysis
    description: Analytical model runs and pattern detection.
  - name: Prediction
    description: Trained prediction model serving.
  - name: Models
    description: Model catalog and discovery.
  - name: Health
    description: Service liveness.
paths:
  /api/v1/analyze:
    post:
      operationId: runAnalysis
      tags: [Analysis]
      summary: Run an analytical model
      description: >-
        Runs the requested analysis type over a dataset and returns findings,
        a summary, and optional visualization data. Analytical outputs are
        demonstration-grade in the current release.
      x-apex-availability: preview
      parameters:
        - $ref: '#/components/parameters/TenantIdHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AnalysisRequest'
            example:
              analysisType: anomaly_detection
              dataset: supplier-transactions
              entity: Acme Holdings
              parameters:
                sensitivity: 0.8
              includeVisualization: true
      responses:
        '200':
          description: Analysis result.
          headers:
            X-Request-ID:
              $ref: '#/components/headers/XRequestId'
            X-Response-Time:
              $ref: '#/components/headers/XResponseTime'
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SuccessEnvelope'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/AnalysisResult'
        '400':
          $ref: '#/components/responses/MissingTenant'
        '404':
          $ref: '#/components/responses/UnknownTenant'
        '422':
          $ref: '#/components/responses/ValidationError'
        '500':
          $ref: '#/components/responses/InternalError'
  /api/v1/patterns:
    post:
      operationId: detectPatterns
      tags: [Analysis]
      summary: Detect recurring patterns
      description: >-
        Detects recurring patterns (seasonal, cyclical, structural break,
        correlation, lead-lag, regime change) across entities and dimensions
        over a timeframe.
      x-apex-availability: preview
      parameters:
        - $ref: '#/components/parameters/TenantIdHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatternRequest'
            example:
              entities: [Acme Holdings, Northwind Manufacturing]
              dimensions: [order_volume, payment_delay]
              timeframe: 1y
              patternTypes: [seasonal, correlation]
      responses:
        '200':
          description: Detected patterns.
          headers:
            X-Request-ID:
              $ref: '#/components/headers/XRequestId'
            X-Response-Time:
              $ref: '#/components/headers/XResponseTime'
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SuccessEnvelope'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/PatternResponse'
        '400':
          $ref: '#/components/responses/MissingTenant'
        '404':
          $ref: '#/components/responses/UnknownTenant'
        '422':
          $ref: '#/components/responses/ValidationError'
        '500':
          $ref: '#/components/responses/InternalError'
  /api/v1/predict:
    post:
      operationId: runPrediction
      tags: [Prediction]
      summary: Run a prediction model
      description: >-
        Runs a trained prediction model against the provided input features.
        If the requested model does not exist, the response is an error
        envelope with code `MODEL_NOT_FOUND` — check the `ok` field, as the
        current release delivers it with HTTP status 200.
      x-apex-availability: preview
      parameters:
        - $ref: '#/components/parameters/TenantIdHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PredictionRequest'
            example:
              model: revenue-forecast
              inputs:
                region: gauteng
                trailing_12m_revenue: 1400000
              horizon: 2q
              includeExplanation: true
      responses:
        '200':
          description: >-
            Prediction result, or an error envelope with code `MODEL_NOT_FOUND`
            when the model does not exist.
          headers:
            X-Request-ID:
              $ref: '#/components/headers/XRequestId'
            X-Response-Time:
              $ref: '#/components/headers/XResponseTime'
          content:
            application/json:
              schema:
                oneOf:
                  - allOf:
                      - $ref: '#/components/schemas/SuccessEnvelope'
                      - type: object
                        properties:
                          data:
                            $ref: '#/components/schemas/PredictionResponse'
                  - $ref: '#/components/schemas/ErrorEnvelope'
        '400':
          $ref: '#/components/responses/MissingTenant'
        '404':
          $ref: '#/components/responses/UnknownTenant'
        '422':
          $ref: '#/components/responses/ValidationError'
        '500':
          $ref: '#/components/responses/InternalError'
  /api/v1/models:
    get:
      operationId: listModels
      tags: [Models]
      summary: List available models
      description: Lists the models available to the tenant, with schemas and metrics.
      x-apex-availability: preview
      parameters:
        - $ref: '#/components/parameters/TenantIdHeader'
        - name: category
          in: query
          description: Filter by model category.
          schema:
            type: string
            enum: [forecasting, classification, regression, clustering, anomaly]
        - name: domain
          in: query
          description: Filter by business domain.
          schema:
            type: string
      responses:
        '200':
          description: Model catalog.
          headers:
            X-Request-ID:
              $ref: '#/components/headers/XRequestId'
            X-Response-Time:
              $ref: '#/components/headers/XResponseTime'
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SuccessEnvelope'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/ModelsListResponse'
        '400':
          $ref: '#/components/responses/MissingTenant'
        '404':
          $ref: '#/components/responses/UnknownTenant'
        '500':
          $ref: '#/components/responses/InternalError'
  /api/v1/models/{model_name}:
    get:
      operationId: getModel
      tags: [Models]
      summary: Get model details
      description: >-
        Returns the full record for one model, including its versions. If the
        model does not exist, the response is an error envelope with code
        `MODEL_NOT_FOUND` — check the `ok` field, as the current release
        delivers it with HTTP status 200.
      x-apex-availability: preview
      parameters:
        - $ref: '#/components/parameters/TenantIdHeader'
        - name: model_name
          in: path
          required: true
          description: Model name.
          schema:
            type: string
      responses:
        '200':
          description: >-
            Model record, or an error envelope with code `MODEL_NOT_FOUND` when
            the model does not exist.
          headers:
            X-Request-ID:
              $ref: '#/components/headers/XRequestId'
            X-Response-Time:
              $ref: '#/components/headers/XResponseTime'
          content:
            application/json:
              schema:
                oneOf:
                  - allOf:
                      - $ref: '#/components/schemas/SuccessEnvelope'
                      - type: object
                        properties:
                          data:
                            $ref: '#/components/schemas/RegisteredModel'
                  - $ref: '#/components/schemas/ErrorEnvelope'
        '400':
          $ref: '#/components/responses/MissingTenant'
        '404':
          $ref: '#/components/responses/UnknownTenant'
        '500':
          $ref: '#/components/responses/InternalError'
  /health:
    get:
      operationId: getHealth
      tags: [Health]
      summary: Liveness check
      description: Minimal liveness probe. Requires no tenant header.
      x-apex-availability: preview
      responses:
        '200':
          description: Service is alive.
          content:
            application/json:
              schema:
                type: object
                description: Liveness status.
components:
  parameters:
    TenantIdHeader:
      name: X-Tenant-ID
      in: header
      required: true
      description: Tenant identifier.
      schema:
        type: string
      example: your-tenant
  headers:
    XRequestId:
      description: Correlation identifier for the request.
      schema:
        type: string
    XResponseTime:
      description: Server processing time for the request.
      schema:
        type: string
  responses:
    MissingTenant:
      description: The `X-Tenant-ID` header is missing.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            ok: false
            error:
              code: MISSING_TENANT
              message: X-Tenant-ID header is required
    UnknownTenant:
      description: The tenant is not configured.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            ok: false
            error:
              code: UNKNOWN_TENANT
              message: Tenant not found
    ValidationError:
      description: Request body failed validation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            ok: false
            error:
              code: VALIDATION_ERROR
              message: Request validation failed
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            ok: false
            error:
              code: INTERNAL_ERROR
              message: An unexpected error occurred
  schemas:
    SuccessEnvelope:
      type: object
      properties:
        ok:
          type: boolean
          const: true
        data:
          description: Operation payload.
        requestId:
          type: string
        meta:
          type: object
    ErrorEnvelope:
      type: object
      properties:
        ok:
          type: boolean
          const: false
        error:
          type: object
          properties:
            code:
              type: string
              enum: [MISSING_TENANT, UNKNOWN_TENANT, VALIDATION_ERROR, INTERNAL_ERROR, MODEL_NOT_FOUND]
            message:
              type: string
            detail:
              description: Optional structured detail.
        requestId:
          type: string
    AnalysisRequest:
      type: object
      required: [analysisType, dataset]
      properties:
        analysisType:
          type: string
          enum: [anomaly_detection, clustering, correlation, trend_decomposition, network_analysis]
        dataset:
          type: string
          description: Dataset identifier to analyse.
        entity:
          type: [string, 'null']
          description: Optional entity to focus the analysis on.
        parameters:
          type: object
          additionalProperties: true
          description: Analysis-type-specific parameters.
        includeVisualization:
          type: boolean
          default: false
    AnalysisResult:
      type: object
      description: Analysis outcome. Fields are snake_case.
      properties:
        analysis_type:
          type: string
          enum: [anomaly_detection, clustering, correlation, trend_decomposition, network_analysis]
        findings:
          type: array
          items:
            type: object
        summary:
          type: string
        visualization_data:
          type: [object, 'null']
          description: Present when `includeVisualization` was requested.
        vector_confidence:
          type: [number, 'null']
          description: Confidence signal sourced from the Vector verification engine, when available.
    PatternRequest:
      type: object
      required: [entities, dimensions]
      properties:
        entities:
          type: array
          items:
            type: string
        dimensions:
          type: array
          items:
            type: string
        timeframe:
          type: string
          default: 1y
        patternTypes:
          type: array
          items:
            type: string
            enum: [seasonal, cyclical, structural_break, correlation, lead_lag, regime_change]
          default: [seasonal, cyclical, correlation]
    PatternResponse:
      type: object
      description: Pattern detection outcome. Fields are snake_case.
      properties:
        patterns:
          type: array
          items:
            type: object
            properties:
              pattern_type:
                type: string
                enum: [seasonal, cyclical, structural_break, correlation, lead_lag, regime_change]
              entities:
                type: array
                items:
                  type: string
              dimensions:
                type: array
                items:
                  type: string
              strength:
                type: number
                minimum: 0
                maximum: 1
              description:
                type: string
              evidence:
                type: object
        entity_count:
          type: integer
        dimension_count:
          type: integer
        timeframe:
          type: string
    PredictionRequest:
      type: object
      required: [model, inputs]
      properties:
        model:
          type: string
          description: Model name. Discover via `GET /api/v1/models`.
        inputs:
          type: object
          additionalProperties: true
          description: Input features for the model.
        horizon:
          type: [string, 'null']
          description: Forecast horizon, for forecasting models.
        includeExplanation:
          type: boolean
          default: false
    PredictionResponse:
      type: object
      description: Prediction outcome. Fields are camelCase.
      properties:
        model:
          type: string
        prediction:
          type: object
          properties:
            value:
              description: Predicted value.
            unit:
              type: [string, 'null']
            confidence:
              type: [object, 'null']
              properties:
                level:
                  type: number
                lower:
                  type: number
                upper:
                  type: number
            horizon:
              type: [string, 'null']
            direction:
              type: [string, 'null']
            changePercent:
              type: [number, 'null']
        explanation:
          type: [object, 'null']
          description: Present when `includeExplanation` was requested.
          properties:
            topFactors:
              type: array
              items:
                type: object
                properties:
                  feature:
                    type: string
                  impact:
                    type: number
                  direction:
                    type: string
            modelVersion:
              type: string
            trainingDate:
              type: [string, 'null']
        vectorVerification:
          type: [object, 'null']
          description: Input quality signal from the Vector verification engine, when available.
          properties:
            dataQualityScore:
              type: number
            inputsVerified:
              type: boolean
    ModelsListResponse:
      type: object
      description: Model catalog. Fields are snake_case.
      properties:
        models:
          type: array
          items:
            $ref: '#/components/schemas/ModelInfo'
        total:
          type: integer
        category_filter:
          type: [string, 'null']
        domain_filter:
          type: [string, 'null']
    ModelInfo:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        category:
          type: string
          enum: [forecasting, classification, regression, clustering, anomaly]
        domain:
          type: [string, 'null']
        description:
          type: string
        input_schema:
          type: object
          description: Expected input features.
        metrics:
          type: [object, 'null']
          description: Evaluation metrics for the serving version.
        version:
          type: [string, 'null']
        status:
          type: string
          enum: [experiment, staging, production, archived]
    RegisteredModel:
      type: object
      description: Full model record including version history. Fields are snake_case.
      properties:
        id:
          type: string
        tenant_id:
          type: string
        name:
          type: string
        description:
          type: string
        category:
          type: string
          enum: [forecasting, classification, regression, clustering, anomaly]
        domain:
          type: [string, 'null']
        latest_version:
          type: integer
        production_version_id:
          type: [string, 'null']
        versions:
          type: array
          items:
            type: object
            description: Model version with stage, framework, metrics, and lineage.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
