{
  "openapi": "3.1.1",
  "info": {
    "title": "Greenfield Energy Explorer Public API",
    "description": "Machine-to-machine REST API for energy calculation submission and retrieval (version v1).",
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://public-api-prod-greenfield-we.azurewebsites.net/"
    }
  ],
  "paths": {
    "/api/v1/calculations/health": {
      "get": {
        "tags": [
          "Calculations"
        ],
        "summary": "Health check endpoint for monitoring and load balancers.",
        "description": "Verifies service availability without requiring authentication. Used by monitoring systems and load balancers.",
        "responses": {
          "200": {
            "description": "Service is healthy and operational.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSuccessResponseOfHealthCheckResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry after the indicated interval.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/calculations/validate": {
      "post": {
        "tags": [
          "Calculations"
        ],
        "summary": "Validate a wind-simulation submission without submitting a calculation run.",
        "description": "Validates the project configuration in the JSON body. No quota is consumed.",
        "requestBody": {
          "description": "A single wind-simulation project configuration.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WindFarmSimulationRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WindFarmSimulationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Validation succeeded. The project is valid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSuccessResponseOfValidationResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request body failed schema validation (missing/invalid fields).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "API key is missing, invalid, expired, or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "The project failed validation. The `details` array lists each failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded or submission queue is full. Retry after the indicated interval.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/calculations/wind-simulation": {
      "post": {
        "tags": [
          "Calculations"
        ],
        "summary": "Submit a wind-simulation calculation run.",
        "description": "Validates and submits the JSON body for asynchronous processing. Quota enforcement is applied.",
        "requestBody": {
          "description": "A single wind-simulation project configuration.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WindFarmSimulationRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WindFarmSimulationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Calculation accepted for processing. The response contains the created calculation ID and order ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSuccessResponseOfCalculationSubmissionResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request body failed schema validation (missing/invalid fields).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "API key is missing, invalid, expired, or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "The project failed validation, or the tenant quota has been exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded or submission queue is full. Retry after the indicated interval.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/calculations": {
      "get": {
        "tags": [
          "Calculations"
        ],
        "summary": "List calculations for the authenticated tenant.",
        "description": "Returns a paginated list of calculations with automatic tenant isolation.",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-based). Defaults to 1.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "Number of items per page. Defaults to 20, maximum 100.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32",
              "default": 20
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Optional filter by calculation status (e.g., `Pending`, `Completed`, `Failed`, `Expired`).",
            "schema": {
              "$ref": "#/components/schemas/CalculationStatusEnum"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of calculations.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSuccessResponseOfCalculationListResponse"
                }
              }
            }
          },
          "401": {
            "description": "API key is missing, invalid, expired, or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry after the indicated interval.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/calculations/{id}": {
      "get": {
        "tags": [
          "Calculations"
        ],
        "summary": "Get the status and metadata of a single calculation.",
        "description": "Retrieves the current status, type, version, and metadata for a specific calculation.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (GUID) of the calculation.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Calculation found. Returns the calculation detail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSuccessResponseOfCalculationDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "API key is missing, invalid, expired, or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No calculation found with the given id for this tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry after the indicated interval.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/calculations/{id}/results": {
      "get": {
        "tags": [
          "Calculations"
        ],
        "summary": "Download the completed calculation results as a ZIP file.",
        "description": "Downloads the calculation result archive as a binary ZIP file. The response bypasses the unified JSON envelope.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (GUID) of the calculation.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Binary ZIP file containing the calculation results.",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "application/json": { }
            }
          },
          "401": {
            "description": "API key is missing, invalid, expired, or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No calculation found with the given id for this tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "The calculation has not yet completed. Poll the status endpoint until `status` is `Completed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry after the indicated interval.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "ApiError": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable error code (e.g., `VALIDATION_FAILED`, `QUOTA_EXCEEDED`, `NOT_FOUND`)."
          },
          "message": {
            "type": "string",
            "description": "Human-readable error message suitable for display to API consumers."
          },
          "details": {
            "description": "Additional error details — may be an array of strings, validation items, or other structured data."
          },
          "requestId": {
            "type": "string",
            "description": "Per-request correlation identifier. Echo this value when reporting issues to support."
          },
          "apiVersion": {
            "type": "string",
            "description": "The API version that produced this error (e.g., `v1`)."
          }
        },
        "description": "The error detail within an ApiErrorResponse."
      },
      "ApiErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "description": "The error detail object.",
            "$ref": "#/components/schemas/ApiError"
          }
        },
        "description": "Unified error envelope (DESIGN.md §4.2, PRD FR-4.3). All 4xx and 5xx responses from the\npublic API use this shape. string ApiError.Code is always a value from\nApiErrorCode. See DESIGN.md §4.3 for the HTTP-status → error-code mapping."
      },
      "ApiMeta": {
        "type": "object",
        "properties": {
          "apiVersion": {
            "type": "string",
            "description": "The routed API version (e.g., `\"v1\"`)."
          },
          "timestamp": {
            "type": "string",
            "description": "ISO 8601 UTC timestamp of when the response was generated."
          },
          "requestId": {
            "type": "string",
            "description": "Per-request correlation identifier set by `RequestIdMiddleware`.\nEcho this value when reporting issues to support."
          }
        },
        "description": "Metadata included in every ApiSuccessResponse&lt;T&gt;."
      },
      "ApiSuccessResponseOfCalculationDetailResponse": {
        "type": "object",
        "properties": {
          "data": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "The response payload.",
                "$ref": "#/components/schemas/CalculationDetailResponse"
              }
            ]
          },
          "meta": {
            "description": "Request metadata (version, timestamp, correlation ID).",
            "$ref": "#/components/schemas/ApiMeta"
          }
        },
        "description": "Unified success envelope returned by all non-download API responses\n(DESIGN.md §4.1, PRD FR-4.1–4.2)."
      },
      "ApiSuccessResponseOfCalculationListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "The response payload.",
                "$ref": "#/components/schemas/CalculationListResponse"
              }
            ]
          },
          "meta": {
            "description": "Request metadata (version, timestamp, correlation ID).",
            "$ref": "#/components/schemas/ApiMeta"
          }
        },
        "description": "Unified success envelope returned by all non-download API responses\n(DESIGN.md §4.1, PRD FR-4.1–4.2)."
      },
      "ApiSuccessResponseOfCalculationSubmissionResponse": {
        "type": "object",
        "properties": {
          "data": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "The response payload.",
                "$ref": "#/components/schemas/CalculationSubmissionResponse"
              }
            ]
          },
          "meta": {
            "description": "Request metadata (version, timestamp, correlation ID).",
            "$ref": "#/components/schemas/ApiMeta"
          }
        },
        "description": "Unified success envelope returned by all non-download API responses\n(DESIGN.md §4.1, PRD FR-4.1–4.2)."
      },
      "ApiSuccessResponseOfHealthCheckResponse": {
        "type": "object",
        "properties": {
          "data": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "The response payload.",
                "$ref": "#/components/schemas/HealthCheckResponse"
              }
            ]
          },
          "meta": {
            "description": "Request metadata (version, timestamp, correlation ID).",
            "$ref": "#/components/schemas/ApiMeta"
          }
        },
        "description": "Unified success envelope returned by all non-download API responses\n(DESIGN.md §4.1, PRD FR-4.1–4.2)."
      },
      "ApiSuccessResponseOfValidationResponse": {
        "type": "object",
        "properties": {
          "data": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "The response payload.",
                "$ref": "#/components/schemas/ValidationResponse"
              }
            ]
          },
          "meta": {
            "description": "Request metadata (version, timestamp, correlation ID).",
            "$ref": "#/components/schemas/ApiMeta"
          }
        },
        "description": "Unified success envelope returned by all non-download API responses\n(DESIGN.md §4.1, PRD FR-4.1–4.2)."
      },
      "CalculationDetailResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier (GUID) of the calculation.",
            "format": "uuid"
          },
          "orderId": {
            "type": "string",
            "description": "Zero-padded sequential order identifier (e.g., `00042`)."
          },
          "type": {
            "type": "string",
            "description": "Calculation type (e.g., `WindSimulation`)."
          },
          "status": {
            "type": "string",
            "description": "Current status: `Pending`, `Completed`, `Failed`, or `Expired`."
          },
          "count": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Number of profiles/projects in this calculation.",
            "format": "int32"
          },
          "version": {
            "type": "string",
            "description": "Version of the calculation engine used."
          },
          "projectName": {
            "type": "string",
            "description": "Name of the project as parsed from the input file."
          },
          "orderedAt": {
            "type": "string",
            "description": "UTC timestamp when the calculation was submitted.",
            "format": "date-time"
          }
        },
        "description": "Detail view of a single calculation. Used by both the list endpoint\nand the per-id status endpoint."
      },
      "CalculationListResponse": {
        "type": "object",
        "properties": {
          "calculations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CalculationDetailResponse"
            },
            "description": "Calculation detail items for the current page."
          },
          "pagination": {
            "description": "Pagination metadata for the current result set.",
            "$ref": "#/components/schemas/PaginationInfo"
          }
        },
        "description": "Response payload for `GET /api/v1/calculations`.\nWrapped in the unified success envelope by `UnifiedResponseMiddleware`."
      },
      "CalculationStatusEnum": {
        "type": "integer"
      },
      "CalculationSubmissionResponse": {
        "type": "object",
        "properties": {
          "calculations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CalculationSummary"
            },
            "description": "Summaries of the calculations created by this submission."
          }
        },
        "description": "Response payload for `POST /api/v1/calculations/wind-simulation`.\nReturned in the 202 Accepted envelope."
      },
      "CalculationSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier (GUID) of the created calculation.",
            "format": "uuid"
          },
          "orderId": {
            "type": "string",
            "description": "Zero-padded sequential order identifier (e.g., `00042`)."
          },
          "projectName": {
            "type": "string",
            "description": "Name of the project as parsed from the input file."
          },
          "status": {
            "type": "string",
            "description": "Initial status — always `Pending` immediately after submission."
          }
        },
        "description": "Summary of a single submitted calculation."
      },
      "EntityTagHeaderValue": {
        "type": "object",
        "properties": {
          "tag": {
            "$ref": "#/components/schemas/StringSegment"
          },
          "isWeak": {
            "type": "boolean"
          }
        }
      },
      "FileResult": {
        "type": "object",
        "properties": {
          "contentType": {
            "type": [
              "null",
              "string"
            ]
          },
          "fileDownloadName": {
            "type": [
              "null",
              "string"
            ]
          },
          "lastModified": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "entityTag": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/EntityTagHeaderValue"
              }
            ]
          },
          "enableRangeProcessing": {
            "type": "boolean"
          }
        }
      },
      "HealthCheckResponse": {
        "required": [
          "status"
        ],
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LayoutScenarioDto": {
        "required": [
          "windFarms",
          "turbineTypes"
        ],
        "type": "object",
        "properties": {
          "layoutScenarioName": {
            "type": "string"
          },
          "windFarms": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WindFarmDto"
            }
          },
          "turbineTypes": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TurbineTypeDto"
            }
          }
        }
      },
      "PaginationInfo": {
        "type": "object",
        "properties": {
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Current page number (1-based).",
            "format": "int32"
          },
          "pageSize": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Number of items per page.",
            "format": "int32"
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total number of calculations matching the query (across all pages).",
            "format": "int32"
          }
        },
        "description": "Pagination metadata included with list responses."
      },
      "PerformanceTableDto": {
        "required": [
          "powerCurve"
        ],
        "type": "object",
        "properties": {
          "powerCurveInfo": {
            "type": [
              "null",
              "string"
            ]
          },
          "thrustCurveInfo": {
            "type": [
              "null",
              "string"
            ]
          },
          "airDensity": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "turbulence": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "powerCurve": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PowerCurveDataPointDto"
            }
          }
        }
      },
      "PowerControlType": {
        "enum": [
          "Pitch",
          "Stall"
        ]
      },
      "PowerCurveDataPointDto": {
        "type": "object",
        "properties": {
          "windSpeed": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "powerOutput": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "description": "Power output in watts (W), matching the Python PowerCurveDataPoint model.",
            "format": "double"
          },
          "thrustCoefficient": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "rotorSpeed": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          }
        }
      },
      "RotorSpeedType": {
        "enum": [
          "Variable Speed",
          "Fixed Speed",
          "Two Speed"
        ]
      },
      "StartStopStrategyDto": {
        "type": "object",
        "properties": {
          "lowSpeedCutOut": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "lowSpeedCutIn": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "highSpeedCutIn": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "highSpeedCutOut": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "adjustedLowSpeedCutIn": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "adjustedHighSpeedCutOut": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          }
        }
      },
      "StringSegment": {
        "type": "object",
        "properties": {
          "buffer": {
            "type": [
              "null",
              "string"
            ]
          },
          "offset": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "length": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "value": {
            "type": [
              "null",
              "string"
            ]
          },
          "hasValue": {
            "type": "boolean"
          }
        }
      },
      "TurbineDto": {
        "required": [
          "name",
          "utmLocation2D",
          "turbineTypeUuid"
        ],
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 500,
            "type": "string"
          },
          "notes": {
            "type": [
              "null",
              "string"
            ]
          },
          "utmLocation2D": {
            "$ref": "#/components/schemas/UtmLocation2DDto"
          },
          "turbineTypeUuid": {
            "type": "string"
          }
        }
      },
      "TurbineModeDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "startStopStrategy": {
            "$ref": "#/components/schemas/StartStopStrategyDto"
          },
          "performanceTableList": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PerformanceTableDto"
            }
          }
        }
      },
      "TurbineTypeDto": {
        "required": [
          "turbineTypeUuid",
          "turbineModes"
        ],
        "type": "object",
        "properties": {
          "turbineTypeUuid": {
            "type": "string"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "manufacturerName": {
            "type": [
              "null",
              "string"
            ]
          },
          "model": {
            "type": [
              "null",
              "string"
            ]
          },
          "notes": {
            "type": [
              "null",
              "string"
            ]
          },
          "ratedPower": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "description": "Rated power in kilowatts (kW), matching the Python TurbineType model.",
            "format": "double"
          },
          "powerControlType": {
            "$ref": "#/components/schemas/PowerControlType"
          },
          "rotorDiameter": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "rotorSpeedType": {
            "$ref": "#/components/schemas/RotorSpeedType"
          },
          "hubHeight": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "turbineModes": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TurbineModeDto"
            }
          }
        }
      },
      "UtmCoordinateSystemDto": {
        "required": [
          "hemisphere"
        ],
        "type": "object",
        "properties": {
          "zone": {
            "maximum": 60,
            "minimum": 1,
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "hemisphere": {
            "pattern": "^[NS]$",
            "type": "string"
          }
        }
      },
      "UtmLocation2DDto": {
        "required": [
          "utmCoordinateSystem"
        ],
        "type": "object",
        "properties": {
          "easting": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "northing": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "utmCoordinateSystem": {
            "$ref": "#/components/schemas/UtmCoordinateSystemDto"
          }
        }
      },
      "ValidationItem": {
        "type": "object",
        "properties": {
          "projectIndex": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "1-based index of the project within the uploaded file.",
            "format": "int32"
          },
          "isValid": {
            "type": "boolean",
            "description": "Whether the project passed validation."
          },
          "message": {
            "type": [
              "null",
              "string"
            ],
            "description": "Validation message (success or failure description)."
          },
          "isoCode": {
            "type": [
              "null",
              "string"
            ],
            "description": "ISO country code resolved for the project, if applicable."
          }
        },
        "description": "Per-project validation result."
      },
      "ValidationResponse": {
        "type": "object",
        "properties": {
          "validations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationItem"
            },
            "description": "Per-project validation results, in the same order as the input file."
          }
        },
        "description": "Response payload for `POST /api/v1/calculations/validate`.\nWrapped in the unified success envelope by `UnifiedResponseMiddleware`."
      },
      "WindFarmDto": {
        "required": [
          "name",
          "turbines"
        ],
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 500,
            "type": "string"
          },
          "notes": {
            "type": [
              "null",
              "string"
            ]
          },
          "isNeighbour": {
            "type": "boolean"
          },
          "turbines": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TurbineDto"
            }
          }
        }
      },
      "WindFarmSimulationRequest": {
        "required": [
          "projectName",
          "utmCoordinateSystem",
          "layoutScenario"
        ],
        "type": "object",
        "properties": {
          "projectName": {
            "maxLength": 500,
            "type": "string"
          },
          "utmCoordinateSystem": {
            "$ref": "#/components/schemas/UtmCoordinateSystemDto"
          },
          "layoutScenario": {
            "$ref": "#/components/schemas/LayoutScenarioDto"
          }
        },
        "description": "JSON request body for the wind-simulation validate/submit endpoints (replaces the\nformer Excel/CSV multipart upload). Accepts a single project per request.",
        "example": {
          "projectName": "Example Wind Farm Project",
          "utmCoordinateSystem": {
            "zone": 32,
            "hemisphere": "N"
          },
          "layoutScenario": {
            "layoutScenarioName": "Example Layout Scenario",
            "windFarms": [
              {
                "name": "Example Wind Farm",
                "notes": "Two-turbine example layout for API documentation purposes.",
                "isNeighbour": false,
                "turbines": [
                  {
                    "name": "Turbine A",
                    "utmLocation2D": {
                      "easting": 500000.0,
                      "northing": 6000000.0,
                      "utmCoordinateSystem": {
                        "zone": 32,
                        "hemisphere": "N"
                      }
                    },
                    "turbineTypeUuid": "example-turbine-3.6MW-120m"
                  },
                  {
                    "name": "Turbine B",
                    "utmLocation2D": {
                      "easting": 500600.0,
                      "northing": 6000000.0,
                      "utmCoordinateSystem": {
                        "zone": 32,
                        "hemisphere": "N"
                      }
                    },
                    "turbineTypeUuid": "example-turbine-3.6MW-120m"
                  }
                ]
              }
            ],
            "turbineTypes": [
              {
                "turbineTypeUuid": "example-turbine-3.6MW-120m",
                "name": "ETM 3.6 MW / 120m",
                "manufacturerName": "Example Turbine Manufacturer",
                "model": "ETM-3.6-120",
                "notes": "Illustrative turbine type for API documentation purposes only.",
                "ratedPower": 3600,
                "powerControlType": "Pitch",
                "rotorDiameter": 120,
                "rotorSpeedType": "Variable Speed",
                "hubHeight": 100,
                "turbineModes": [
                  {
                    "name": "normal",
                    "startStopStrategy": {
                      "lowSpeedCutOut": 3.0,
                      "lowSpeedCutIn": 3.0,
                      "highSpeedCutIn": 20.0,
                      "highSpeedCutOut": 25.0,
                      "adjustedLowSpeedCutIn": 3.0,
                      "adjustedHighSpeedCutOut": 22.5
                    },
                    "performanceTableList": [
                      {
                        "powerCurveInfo": "Illustrative power curve",
                        "thrustCurveInfo": "Illustrative thrust curve",
                        "airDensity": 1.225,
                        "turbulence": 0.10,
                        "powerCurve": [
                          {
                            "windSpeed": 3,
                            "powerOutput": 0,
                            "thrustCoefficient": 0.80,
                            "rotorSpeed": 6.0
                          },
                          {
                            "windSpeed": 4,
                            "powerOutput": 100000,
                            "thrustCoefficient": 0.82,
                            "rotorSpeed": 7.0
                          },
                          {
                            "windSpeed": 5,
                            "powerOutput": 300000,
                            "thrustCoefficient": 0.83,
                            "rotorSpeed": 8.0
                          },
                          {
                            "windSpeed": 6,
                            "powerOutput": 600000,
                            "thrustCoefficient": 0.82,
                            "rotorSpeed": 9.0
                          },
                          {
                            "windSpeed": 7,
                            "powerOutput": 1050000,
                            "thrustCoefficient": 0.80,
                            "rotorSpeed": 10.0
                          },
                          {
                            "windSpeed": 8,
                            "powerOutput": 1650000,
                            "thrustCoefficient": 0.75,
                            "rotorSpeed": 11.0
                          },
                          {
                            "windSpeed": 9,
                            "powerOutput": 2400000,
                            "thrustCoefficient": 0.65,
                            "rotorSpeed": 12.0
                          },
                          {
                            "windSpeed": 10,
                            "powerOutput": 3100000,
                            "thrustCoefficient": 0.50,
                            "rotorSpeed": 13.0
                          },
                          {
                            "windSpeed": 11,
                            "powerOutput": 3500000,
                            "thrustCoefficient": 0.35,
                            "rotorSpeed": 14.0
                          },
                          {
                            "windSpeed": 12,
                            "powerOutput": 3600000,
                            "thrustCoefficient": 0.25,
                            "rotorSpeed": 14.0
                          },
                          {
                            "windSpeed": 14,
                            "powerOutput": 3600000,
                            "thrustCoefficient": 0.18,
                            "rotorSpeed": 14.0
                          },
                          {
                            "windSpeed": 16,
                            "powerOutput": 3600000,
                            "thrustCoefficient": 0.14,
                            "rotorSpeed": 14.0
                          },
                          {
                            "windSpeed": 18,
                            "powerOutput": 3600000,
                            "thrustCoefficient": 0.11,
                            "rotorSpeed": 14.0
                          },
                          {
                            "windSpeed": 20,
                            "powerOutput": 3600000,
                            "thrustCoefficient": 0.09,
                            "rotorSpeed": 14.0
                          },
                          {
                            "windSpeed": 22,
                            "powerOutput": 3600000,
                            "thrustCoefficient": 0.08,
                            "rotorSpeed": 14.0
                          },
                          {
                            "windSpeed": 25,
                            "powerOutput": 3600000,
                            "thrustCoefficient": 0.07,
                            "rotorSpeed": 14.0
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "description": "Enter your API key (starts with 'gee_'). You can also use: Authorization: ApiKey <key>",
        "name": "X-API-Key",
        "in": "header"
      }
    }
  },
  "tags": [
    {
      "name": "Calculations"
    }
  ]
}