{
  "openapi": "3.0.3",
  "info": {
    "title": "DataPulse Weather Forecast API",
    "description": "NOAA HRRR 3km surface weather forecast for any contiguous US (CONUS) coordinate. One GET call returns temperature, dew point, wind speed and direction, accumulated precipitation, and total cloud cover up to 18 forecast hours ahead. Data is sourced from NOAA HRRR (High-Resolution Rapid Refresh) via Open-Meteo. Generated from payments/datapulse/packages/data-pulse/src/handlers/api.ts and verified against the live API on Oct 13 2026.\n",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://datapulse.waltsoft.net/v1",
      "description": "DataPulse production endpoint"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/forecast": {
      "get": {
        "operationId": "getWeatherForecast",
        "summary": "NOAA HRRR weather forecast for a CONUS coordinate",
        "description": "Returns NOAA HRRR surface forecast data for the given latitude/longitude. Coverage: contiguous United States (latitude 21-50, longitude -135 to -55). HRRR runs hourly; data is available approximately 2 hours after each cycle. Each call is billed as one unit regardless of the hours parameter.\n",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude in decimal degrees (CONUS coverage 21 to 50).",
            "schema": {
              "type": "number",
              "example": 30.2216
            }
          },
          {
            "name": "lon",
            "in": "query",
            "required": true,
            "description": "Longitude in decimal degrees (CONUS coverage -135 to -55).",
            "schema": {
              "type": "number",
              "example": -97.6206
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Forecast hours ahead from the current hour, 1 to 18 (default 1).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 18,
              "default": 1,
              "example": 6
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Forecast data for the requested coordinate and hour",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForecastResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/SourceDown"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    },
    "parameters": {
      "Lat": {
        "name": "lat",
        "in": "query",
        "required": true,
        "description": "Latitude in decimal degrees (CONUS coverage 21 to 50).",
        "schema": {
          "type": "number",
          "example": 30.2216
        }
      },
      "Lon": {
        "name": "lon",
        "in": "query",
        "required": true,
        "description": "Longitude in decimal degrees (CONUS coverage -135 to -55).",
        "schema": {
          "type": "number",
          "example": -97.6206
        }
      }
    },
    "schemas": {
      "ForecastResponse": {
        "type": "object",
        "properties": {
          "coordinate": {
            "type": "object",
            "properties": {
              "lat": {
                "type": "number",
                "description": "Latitude snapped to grid (decimal degrees)."
              },
              "lon": {
                "type": "number",
                "description": "Longitude snapped to grid (decimal degrees)."
              }
            }
          },
          "forecast_hour": {
            "type": "integer",
            "description": "The requested forecast hour offset (1-18)."
          },
          "valid_time": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 UTC timestamp of the forecast."
          },
          "source": {
            "type": "string",
            "description": "Data source (always \"NOAA HRRR (via open-meteo.com)\")."
          },
          "variables": {
            "type": "object",
            "description": "Weather variable readings at the forecast hour.",
            "properties": {
              "tmp_2m": {
                "$ref": "#/components/schemas/Reading"
              },
              "dpt_2m": {
                "$ref": "#/components/schemas/Reading"
              },
              "apcp": {
                "$ref": "#/components/schemas/Reading"
              },
              "tcdc": {
                "$ref": "#/components/schemas/Reading"
              },
              "wind": {
                "type": "object",
                "properties": {
                  "speed_ms": {
                    "type": "number",
                    "description": "Wind speed at 10m in m/s."
                  },
                  "direction_deg": {
                    "type": "integer",
                    "description": "Wind direction at 10m in degrees (direction FROM)."
                  }
                }
              }
            }
          }
        }
      },
      "Reading": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number"
          },
          "unit": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Missing or invalid parameters (lat/lon out of CONUS bounds or unparseable)",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, invalid or inactive API key",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "integer",
                      "example": 401
                    },
                    "message": {
                      "type": "string",
                      "example": "Invalid or inactive API key"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "No API key sent (x402 pay-per-call challenge in response body)",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded; retry after 60 seconds",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                },
                "retry_after_seconds": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "SourceDown": {
        "description": "NOAA HRRR data temporarily unavailable; not billed",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                },
                "hint": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}