openapi: "3.1.0"
info:
  title: GridAct Romanian Power Grid (SEN) Imbalance Forecasting API
  description: >
    Enterprise API for monitoring the Romanian electricity grid (SEN), forecasting
    the 15-minute Imbalance Settlement Period (ISP) imbalance sign (Deficit vs Surplus),
    retrieving Transelectrica estimated imbalance prices, and calculating BRP financial ROI.
  version: "1.1.0"
servers:
  - url: https://gridact.app
    description: Public Portal & Telemetry Host
  - url: https://api.gridact.app
    description: High-throughput API Host

paths:
  /api/market/live-sen-summary:
    get:
      operationId: getLiveSenSummary
      summary: Get real-time Romanian grid balance and forecast summary
      description: >
        Returns the active 15-minute ISP interval, projected deficit/surplus sign and MW,
        Transelectrica estimated imbalance prices, and foundation model fleet consensus.
      responses:
        "200":
          description: Real-time SEN telemetry and forecast status
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LiveSenSummary"
        "503":
          description: Live grid telemetry temporarily unavailable
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/market/track-record:
    get:
      operationId: getTrackRecord
      summary: Get historical accuracy on settled days
      description: >
        Returns the empirical weighted accuracy of the GridAct foundation model fleet
        over settled days (7 to 90 days) compared to the persistence baseline.
      parameters:
        - name: days
          in: query
          required: false
          description: Rolling evaluation window in days (7 to 90, default 30)
          schema:
            type: integer
            default: 30
      responses:
        "200":
          description: Verified track record metrics
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TrackRecord"
        "503":
          description: Track record temporarily unavailable
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/pricing/calculate-roi:
    post:
      operationId: calculateImbalanceRoi
      summary: Calculate BRP annual imbalance penalty reduction
      description: >
        Simulates annual cost savings for a Balance Responsible Party (BRP) or trading desk
        based on portfolio MWh, acted share, and GridAct forecast accuracy edge.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RoiRequest"
      responses:
        "200":
          description: Calculated ROI range and breakeven metrics
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RoiResult"
        "400":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/copilot/chat:
    post:
      operationId: chatWithGridCopilot
      summary: Chat with the specialized SEN Grid Copilot
      description: >
        Sends a query to the GridAct AI Copilot with domain knowledge of Romanian
        power regulations (ANRE), Transelectrica balancing rules, and OPCOM markets.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [message]
              properties:
                message:
                  type: string
                  example: "What causes extreme deficit prices during evening peak hours in SEN?"
      responses:
        "200":
          description: AI Copilot analysis and suggested actions
          content:
            application/json:
              schema:
                type: object
                properties:
                  reply:
                    type: string
                  suggested_actions:
                    type: array
                    items:
                      type: object

  /v1/forecasts/latest:
    get:
      operationId: getLatestImbalanceForecast
      summary: Get full 96-interval day-ahead or intraday forecast vector
      description: >
        Retrieves 15-minute imbalance sign predictions, confidence scores, and individual
        foundation model votes (TiRex-2, TimesFM, Chronos-2, LightGBM) for a delivery date.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: delivery_date
          in: query
          required: false
          description: Delivery date in YYYY-MM-DD format (defaults to current/next day)
          schema:
            type: string
            format: date
            example: "2026-10-06"
        - name: vintage
          in: query
          required: false
          description: Forecast vintage (e.g. "day-ahead" published at 12:00 D-1 or "intraday")
          schema:
            type: string
            enum: [day-ahead, intraday]
            default: day-ahead
      responses:
        "200":
          description: Full day forecast vector
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ForecastResponse"
        "401":
          description: Missing or invalid API Key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /v1/datasets/catalog:
    get:
      operationId: getDatasetsCatalog
      summary: List 35 available market and grid datasets
      description: >
        Lists ingested data streams across Transelectrica SCADA, OPCOM PZU/PI, ENTSO-E,
        and numerical weather prediction models.
      security:
        - ApiKeyAuth: []
      responses:
        "200":
          description: Catalog of dataset descriptors
          content:
            application/json:
              schema:
                type: object
                properties:
                  datasets:
                    type: array
                    items:
                      type: object

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key

  schemas:
    LiveSenSummary:
      type: object
      required: [available]
      properties:
        available:
          type: boolean
          example: true
        sen_sign:
          type: string
          enum: [DEFICIT, SURPLUS]
          nullable: true
          example: "DEFICIT"
        projected_imbalance_mw:
          type: number
          nullable: true
          example: 342.5
        forecast_model_version:
          type: integer
          nullable: true
          example: 2
        forecast_scored_at:
          type: string
          format: date-time
          nullable: true
        deficit_price_ron_mwh:
          type: number
          nullable: true
          example: 1420.50
        surplus_price_ron_mwh:
          type: number
          nullable: true
          example: 210.10
        spread_ron_mwh:
          type: number
          nullable: true
          example: 1210.40
        fleet_consensus_direction:
          type: string
          enum: [DEFICIT, SURPLUS]
          nullable: true
          example: "DEFICIT"
        fleet_consensus_confidence:
          type: number
          nullable: true
          example: 0.84
        active_isp:
          type: string
          example: "2026-10-05T18:15:00Z"
        minutes_to_next_isp:
          type: integer
          example: 8
        generated_at:
          type: string
          format: date-time

    TrackRecord:
      type: object
      required: [window_days, settled_days, acc_w, baseline_acc_w, delta_pp]
      properties:
        window_days:
          type: integer
          example: 30
        settled_days:
          type: integer
          example: 30
        acc_w:
          type: number
          example: 0.764
        baseline_acc_w:
          type: number
          example: 0.671
        delta_pp:
          type: number
          example: 9.3
        days_ahead_of_baseline:
          type: integer
          example: 27
        definition:
          type: string

    RoiRequest:
      type: object
      required: [annual_imbalance_mwh, acted_share_pct, imbalance_price_eur_mwh, plan]
      properties:
        annual_imbalance_mwh:
          type: number
          description: Total annual portfolio imbalance energy in MWh
          example: 25000
        acted_share_pct:
          type: number
          description: Percentage of imbalance intervals acted upon (1 to 100)
          example: 60
        imbalance_price_eur_mwh:
          type: number
          description: Average spread or reference imbalance cost in EUR/MWh
          example: 110
        plan:
          type: string
          enum: [signal, trader]
          example: "trader"
        window_days:
          type: integer
          default: 30

    RoiResult:
      type: object
      properties:
        window_days:
          type: integer
        model_acc_w:
          type: number
        baseline_acc_w:
          type: number
        gross_value_eur:
          type: object
          properties:
            low: { type: number }
            expected: { type: number }
            high: { type: number }
        net_value_eur:
          type: object
          properties:
            low: { type: number }
            expected: { type: number }
            high: { type: number }
        breakeven_edge_pp:
          type: number

    ForecastResponse:
      type: object
      properties:
        delivery_date:
          type: string
          format: date
        vintage:
          type: string
        intervals:
          type: array
          items:
            type: object
            properties:
              interval_index: { type: integer }
              start_utc: { type: string, format: date-time }
              end_utc: { type: string, format: date-time }
              sign: { type: string, enum: [DEFICIT, SURPLUS] }
              confidence: { type: number }
              expected_imbalance_mw: { type: number }

    Error:
      type: object
      required: [code, detail]
      properties:
        type:
          type: string
        title:
          type: string
        status:
          type: integer
        code:
          type: string
          example: "not_found"
        detail:
          type: string
          example: "Resource could not be located."

