openapi: 3.1.0
info:
  title: Azuce Solar Forecasting API
  version: "1.1.0"
  description: |
    Professional solar production forecasting API for solar installers.
    Generate defensible monthly and annual kWh production estimates using
    satellite-derived irradiance data and physics-based modeling.

    ## Features
    - Monthly and annual production estimates with conservative/optimistic ranges
    - Optional financial analysis (savings, payback, 25-year ROI)
    - Optional carbon impact reporting (CO2 avoided, equivalents)
    - Real-time weather notes
    - Global coverage with satellite irradiance data

    ## Pricing
    - **Free tier**: 500 API calls per month
    - **Overage**: $0.001 USD per call beyond 500
    - Enable metered billing from the API Access dashboard

    ## Support
    Contact azuce_support@zoomash.co.uk for assistance.
  contact:
    name: Azuce API Support
    url: https://azuce.com/api-docs
    email: azuce_support@zoomash.co.uk
  license:
    name: Proprietary
    url: https://azuce.com/terms

servers:
  - url: https://azuce.com
    description: Production

security:
  - BearerAuth: []
  - ApiKeyHeader: []

paths:
  /api/v1/forecast:
    get:
      operationId: getForecastInfo
      summary: Get API information
      description: Returns API endpoint information, available fields, and current pricing. No authentication required.
      tags:
        - Forecast
      security: []
      responses:
        "200":
          description: API information
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiInfo"

    post:
      operationId: createForecast
      summary: Generate solar production forecast
      description: |
        Generate a solar production forecast for a given location and system configuration.
        Returns monthly and annual kWh estimates with conservative/optimistic ranges.

        Optionally include financial analysis (set `enableFinancials: true`) and/or
        carbon impact reporting (set `enableCarbon: true`) for enriched response data.
      tags:
        - Forecast
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ForecastRequest"
            examples:
              basic:
                summary: Basic forecast
                value:
                  latitude: 51.5074
                  longitude: -0.1278
                  systemSizeKw: 4.0
                  panelAzimuth: 180
                  panelTilt: 35
              withFinancials:
                summary: With financial analysis
                value:
                  latitude: 51.5074
                  longitude: -0.1278
                  systemSizeKw: 4.0
                  panelAzimuth: 180
                  panelTilt: 35
                  enableFinancials: true
                  installedCost: 8000
                  electricityRate: 0.28
                  exportRate: 0.05
                  selfConsumptionPct: 40
                  annualDegradationPct: 0.5
                  currencyCode: GBP
                  currencySymbol: "£"
                  countryCode: GB
              withCarbon:
                summary: With carbon impact
                value:
                  latitude: 51.5074
                  longitude: -0.1278
                  systemSizeKw: 4.0
                  panelAzimuth: 180
                  panelTilt: 35
                  enableCarbon: true
                  gridKgCo2PerKwh: 0.233
              full:
                summary: Full request with all options
                value:
                  latitude: 51.5074
                  longitude: -0.1278
                  address: "London, UK"
                  customerName: "Acme Solar Project"
                  systemSizeKw: 4.0
                  panelAzimuth: 180
                  panelTilt: 35
                  shadingLoss: 5
                  systemLosses: 14
                  tempCoefficient: -0.35
                  enableFinancials: true
                  installedCost: 8000
                  electricityRate: 0.28
                  exportRate: 0.05
                  selfConsumptionPct: 40
                  annualMaintenanceCost: 150
                  annualDegradationPct: 0.5
                  enableCarbon: true
                  gridKgCo2PerKwh: 0.233
                  currencyCode: GBP
                  currencySymbol: "£"
                  countryCode: GB
      responses:
        "200":
          description: Forecast generated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ForecastResponse"
        "400":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ValidationError"
              example:
                error: Validation Error
                message: Invalid input parameters
                details:
                  - field: latitude
                    message: Number must be greater than or equal to -90
                  - field: systemSizeKw
                    message: Required
        "401":
          description: Unauthorized - missing or invalid API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: Unauthorized
                message: "Invalid or missing API key. Include your key via Authorization: Bearer <key> or x-api-key header."
        "429":
          description: Rate limited - external data source temporarily unavailable
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: Rate Limited
                message: External data source is temporarily rate-limited. Please retry in a few seconds.
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: Internal Server Error
                message: Failed to generate forecast. Please try again.

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: "API key as Bearer token: `Authorization: Bearer azk_...`"
    ApiKeyHeader:
      type: apiKey
      in: header
      name: x-api-key
      description: "API key via custom header: `x-api-key: azk_...`"

  schemas:
    ForecastRequest:
      type: object
      required:
        - latitude
        - longitude
        - systemSizeKw
        - panelAzimuth
        - panelTilt
      properties:
        latitude:
          type: number
          minimum: -90
          maximum: 90
          description: Site latitude in decimal degrees.
          example: 51.5074
        longitude:
          type: number
          minimum: -180
          maximum: 180
          description: Site longitude in decimal degrees.
          example: -0.1278
        systemSizeKw:
          type: number
          minimum: 0.1
          maximum: 10000
          description: Total system size in kilowatts (kWp).
          example: 4.0
        panelAzimuth:
          type: number
          minimum: 0
          maximum: 360
          description: Panel compass bearing in degrees (180 = south-facing in northern hemisphere).
          example: 180
        panelTilt:
          type: number
          minimum: 0
          maximum: 90
          description: Panel tilt angle from horizontal in degrees.
          example: 35
        address:
          type: string
          description: Human-readable address for the installation site. Stored for reference only, does not affect calculations.
          example: "London, UK"
        customerName:
          type: string
          description: Customer or project name for reference. Does not affect calculations.
          example: "Acme Solar Project"
        shadingLoss:
          type: number
          minimum: 0
          maximum: 30
          default: 0
          description: "Shading loss percentage. Accounts for nearby obstructions. Range: 0 to 30."
          example: 5
        systemLosses:
          type: number
          minimum: 0
          maximum: 50
          default: 14
          description: "Total system losses percentage. Includes wiring, inverter, soiling, mismatch losses. Range: 0 to 50."
          example: 14
        tempCoefficient:
          type: number
          minimum: -1
          maximum: 0
          default: -0.35
          description: "Temperature coefficient of power (%/°C). Typical range: -0.5 to -0.3 for crystalline silicon. Range: -1 to 0."
          example: -0.35
        enableFinancials:
          type: boolean
          default: false
          description: "Set to true to include a financialAnalysis object in the response."
        installedCost:
          type: number
          minimum: 0
          description: Total installed cost of the solar system in the specified currency.
          example: 8000
        electricityRate:
          type: number
          minimum: 0
          description: Electricity purchase rate per kWh in the specified currency. Default 0.28 when enableFinancials is true.
          example: 0.28
        exportRate:
          type: number
          minimum: 0
          description: Feed-in / export tariff per kWh in the specified currency. Default 0.05 when enableFinancials is true.
          example: 0.05
        selfConsumptionPct:
          type: number
          minimum: 0
          maximum: 100
          description: "Estimated percentage of generated energy consumed on-site. Default 30 when enableFinancials is true. Range: 0 to 100."
          example: 40
        annualMaintenanceCost:
          type: number
          minimum: 0
          description: Annual maintenance cost in the specified currency. Default 150 when enableFinancials is true.
          example: 150
        annualDegradationPct:
          type: number
          minimum: 0
          maximum: 5
          description: "Annual panel degradation rate. Typical: 0.5-0.7%. Default 0.5 when enableFinancials is true. Range: 0 to 5."
          example: 0.5
        enableCarbon:
          type: boolean
          default: false
          description: "Set to true to include a carbonImpact object in the response."
        gridKgCo2PerKwh:
          type: number
          minimum: 0
          description: Grid carbon intensity in kg CO2 per kWh. Default 0.233 when enableCarbon is true.
          example: 0.233
        currencyCode:
          type: string
          default: USD
          description: ISO 4217 currency code for financial values.
          example: GBP
        currencySymbol:
          type: string
          default: "$"
          description: Currency symbol for display.
          example: "£"
        countryCode:
          type: string
          default: US
          description: ISO 3166-1 alpha-2 country code. Used for auto-detecting carbon intensity and currency defaults.
          example: GB

    ForecastResponse:
      type: object
      required:
        - forecast
        - usage
      properties:
        forecast:
          $ref: "#/components/schemas/ForecastData"
        financialAnalysis:
          allOf:
            - $ref: "#/components/schemas/FinancialAnalysis"
            - description: Included only when enableFinancials is true in the request.
        carbonImpact:
          allOf:
            - $ref: "#/components/schemas/CarbonImpact"
            - description: Included only when enableCarbon is true in the request.
        usage:
          $ref: "#/components/schemas/UsageData"

    ForecastData:
      type: object
      required:
        - monthlyKwh
        - annualKwh
        - conservativeAnnual
        - optimisticAnnual
        - weatherNote
        - modelVersion
        - location
        - system
      properties:
        monthlyKwh:
          type: array
          items:
            type: number
          minItems: 12
          maxItems: 12
          description: Estimated kWh production for each month (January through December).
          example: [120.5, 145.2, 210.8, 280.3, 340.1, 365.7, 370.2, 345.6, 270.4, 195.3, 135.6, 105.8]
        annualKwh:
          type: number
          description: Expected annual production in kWh (sum of monthlyKwh).
          example: 2885.5
        conservativeAnnual:
          type: number
          description: Conservative annual estimate (-10% from expected).
          example: 2597.0
        optimisticAnnual:
          type: number
          description: Optimistic annual estimate (+10% from expected).
          example: 3174.1
        weatherNote:
          type: string
          description: Human-readable weather conditions at the site.
          example: "Current conditions: partly cloudy, 18°C. Short-term forecast suggests average solar conditions."
        modelVersion:
          type: string
          description: Version of the forecasting model used.
          example: "1.0.0"
        location:
          type: object
          required:
            - latitude
            - longitude
          properties:
            latitude:
              type: number
              example: 51.5074
            longitude:
              type: number
              example: -0.1278
            address:
              type:
                - string
                - "null"
              example: "London, UK"
        system:
          type: object
          required:
            - systemSizeKw
            - panelAzimuth
            - panelTilt
            - shadingLoss
            - systemLosses
          properties:
            systemSizeKw:
              type: number
              example: 4.0
            panelAzimuth:
              type: number
              example: 180
            panelTilt:
              type: number
              example: 35
            shadingLoss:
              type: number
              example: 0
            systemLosses:
              type: number
              example: 14

    FinancialAnalysis:
      type: object
      description: "Financial projections for the solar system. Only present when enableFinancials is true."
      required:
        - annualSavings
        - annualExportIncome
        - annualMaintenanceCost
        - annualNetBenefit
        - simplePaybackYears
        - totalBenefit25Years
        - roi25YearPercent
        - selfConsumption
        - inputs
        - yearlyBreakdown
      properties:
        annualSavings:
          type: number
          description: Annual savings from self-consumed energy in the specified currency.
          example: 242.38
        annualExportIncome:
          type: number
          description: Annual income from exported energy in the specified currency.
          example: 100.99
        annualMaintenanceCost:
          type: number
          description: Annual maintenance cost in the specified currency.
          example: 150
        annualNetBenefit:
          type: number
          description: Net annual benefit (savings + export income - maintenance).
          example: 193.37
        simplePaybackYears:
          type:
            - number
            - "null"
          description: Simple payback period in years. Null if installed cost is zero or net benefit is non-positive.
          example: 10.34
        totalBenefit25Years:
          type: number
          description: Total cumulative benefit over 25 years accounting for annual panel degradation.
          example: 4381.52
        roi25YearPercent:
          type:
            - number
            - "null"
          description: 25-year return on investment as a percentage. Null if installed cost is zero.
          example: 119.08
        selfConsumption:
          type: object
          description: Breakdown of energy self-consumption versus export.
          required:
            - selfUsedKwh
            - exportedKwh
            - selfConsumptionPercent
          properties:
            selfUsedKwh:
              type: number
              description: Annual energy consumed on-site in kWh.
              example: 865.65
            exportedKwh:
              type: number
              description: Annual energy exported to the grid in kWh.
              example: 2019.85
            selfConsumptionPercent:
              type: number
              description: Percentage of production consumed on-site.
              example: 30
        inputs:
          type: object
          description: Echo of financial input parameters used for calculation, including defaults.
          required:
            - installedCost
            - electricityRate
            - exportRate
            - selfConsumptionPct
            - annualMaintenanceCost
            - annualDegradationPct
          properties:
            installedCost:
              type: number
              example: 2000
            electricityRate:
              type: number
              example: 0.28
            exportRate:
              type: number
              example: 0.05
            selfConsumptionPct:
              type: number
              example: 30
            annualMaintenanceCost:
              type: number
              example: 150
            annualDegradationPct:
              type: number
              example: 0.5
        yearlyBreakdown:
          type: array
          description: Year-by-year projection for 25 years with degradation applied.
          minItems: 25
          maxItems: 25
          items:
            type: object
            required:
              - year
              - productionKwh
              - netBenefit
              - cumulativeBenefit
            properties:
              year:
                type: integer
                description: Year number (1-25).
                example: 1
              productionKwh:
                type: number
                description: Estimated production in kWh for this year (with degradation).
                example: 2885.5
              netBenefit:
                type: number
                description: Net financial benefit for this year.
                example: 193.37
              cumulativeBenefit:
                type: number
                description: Running total of net benefit up to and including this year.
                example: 193.37

    CarbonImpact:
      type: object
      description: "Environmental impact analysis. Only present when enableCarbon is true."
      required:
        - annualCo2AvoidedKg
        - equivalentMilesDriven
        - equivalentTreesPlanted
        - gridKgCo2PerKwh
        - lifetimeCo2AvoidedKg
      properties:
        annualCo2AvoidedKg:
          type: number
          description: Annual CO2 emissions avoided in kilograms.
          example: 672.32
        equivalentMilesDriven:
          type: integer
          description: Equivalent car miles offset annually (at 0.404 kg CO2 per mile).
          example: 1664
        equivalentTreesPlanted:
          type: number
          description: Equivalent number of trees planted (based on 21 kg CO2 absorbed per tree over 10 years).
          example: 32.02
        gridKgCo2PerKwh:
          type: number
          description: Grid carbon intensity value used for calculation in kg CO2 per kWh.
          example: 0.233
        lifetimeCo2AvoidedKg:
          type: number
          description: Estimated 25-year lifetime CO2 avoided in kilograms.
          example: 16808.0

    UsageData:
      type: object
      description: API usage and billing information for the current month.
      required:
        - callsThisMonth
        - freeCallsRemaining
        - billableCallsThisMonth
        - estimatedCostUsd
      properties:
        callsThisMonth:
          type: integer
          description: Total API calls made this billing period.
          example: 42
        freeCallsRemaining:
          type: integer
          description: Remaining free calls this month (out of 500).
          example: 458
        billableCallsThisMonth:
          type: integer
          description: Number of calls exceeding the free tier this month.
          example: 0
        estimatedCostUsd:
          type: number
          description: Estimated charges in USD for billable calls at $0.001 per call.
          example: 0

    ApiInfo:
      type: object
      properties:
        name:
          type: string
          example: Azuce Solar Forecasting API
        version:
          type: string
          example: v1
        endpoint:
          type: string
          example: POST /api/v1/forecast
        documentation:
          type: string
          example: /api-docs
        pricing:
          type: object
          properties:
            freeCallsPerMonth:
              type: integer
              example: 500
            costPerCallAfterFree:
              type: string
              example: "$0.001"
        authentication:
          type: string
          example: "Include your API key via 'Authorization: Bearer <key>' or 'x-api-key' header"
        requiredFields:
          type: object
          additionalProperties:
            type: string
        optionalFields:
          type: object
          additionalProperties:
            type: string

    Error:
      type: object
      required:
        - error
        - message
      properties:
        error:
          type: string
          description: Error type identifier.
          example: Unauthorized
        message:
          type: string
          description: Human-readable error description.
          example: "Invalid or missing API key."

    ValidationError:
      type: object
      required:
        - error
        - message
        - details
      properties:
        error:
          type: string
          example: Validation Error
        message:
          type: string
          example: Invalid input parameters
        details:
          type: array
          description: List of specific field validation errors.
          items:
            type: object
            required:
              - field
              - message
            properties:
              field:
                type: string
                description: Dot-notation path to the invalid field.
                example: latitude
              message:
                type: string
                description: Validation error message.
                example: Number must be greater than or equal to -90
