openapi: 3.1.0
info:
  title: WeatherAI.io API
  description: |
    AI-powered weather intelligence API providing real-time weather data, forecasts, historical data, and more with AI-enhanced accuracy.
    
    ## Authentication
    Every endpoint accepts your API key in any of the following three ways (in order of preference):
    1. **`X-API-Key` header** (recommended): `X-API-Key: <api_key>`
    2. **`Authorization: Bearer` header**: `Authorization: Bearer <api_key>`
    3. **`apiKey` query parameter**: `?apiKey=<api_key>`

    All three methods work identically on every endpoint, including `POST /v1/ai`.
    
    ## Base URL
    `https://api.weatherai.io`
    
    ## Free Tier
    - 1,000 free Standard API calls per day
    - 50 free Premium API calls per day
    - Additional calls billed at $0.001 per call from your credit balance
    
    ## Unit System
    Use the `units` query parameter to control the unit system:
    - `metric` — Celsius, km/h, mm, mb, km
    - `imperial` — Fahrenheit, mph, inches, inHg, miles
    - `both` (default) — Returns both unit systems
  version: 1.0.0
  contact:
    name: WeatherAI.io Support
    url: https://weatherai.io/contact
    email: weatherai_support@zoomash.co.uk
  license:
    name: Proprietary
    url: https://weatherai.io/terms
  x-company:
    name: Zoomash Ltd
    address: 3rd Floor, 86-90 Paul Street, London, Hackney, EC2A 4NE, UK
    companyNumber: "7838145"
    vatNumber: "123233754"

servers:
  - url: https://api.weatherai.io
    description: Production API

security:
  - ApiKeyAuth: []

tags:
  - name: Standard
    description: Standard API endpoints (1,000 free calls/day)
  - name: Premium
    description: Premium API endpoints (50 free calls/day)

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Your WeatherAI.io API key passed in the X-API-Key request header (recommended)
    bearerAuth:
      type: http
      scheme: bearer
      description: Your WeatherAI.io API key passed as a Bearer token in the Authorization header
    ApiKeyQuery:
      type: apiKey
      in: query
      name: apiKey
      description: Your WeatherAI.io API key passed as the apiKey query parameter

  schemas:
    Location:
      type: object
      properties:
        name:
          type: string
          example: London
        region:
          type: string
          example: City of London, Greater London
        country:
          type: string
          example: United Kingdom
        lat:
          type: number
          format: float
          example: 51.52
        lon:
          type: number
          format: float
          example: -0.11
        timezone:
          type: string
          example: Europe/London
        localtime:
          type: string
          example: "2026-02-18 14:30"

    Temperature:
      type: object
      description: Temperature values based on selected unit system
      properties:
        celsius:
          type: number
          example: 12.0
        fahrenheit:
          type: number
          example: 53.6

    FeelsLikeTemperature:
      type: object
      properties:
        celsius:
          type: number
          example: 10.5
        fahrenheit:
          type: number
          example: 50.9

    Wind:
      type: object
      properties:
        kph:
          type: number
          example: 16.9
        mph:
          type: number
          example: 10.5
        direction:
          type: string
          example: WSW
        degree:
          type: integer
          example: 250

    WindSpeed:
      type: object
      properties:
        kph:
          type: number
          example: 16.9
        mph:
          type: number
          example: 10.5

    Visibility:
      type: object
      properties:
        km:
          type: number
          example: 10.0
        miles:
          type: number
          example: 6.0

    Pressure:
      type: object
      properties:
        mb:
          type: number
          example: 1012.0
        in:
          type: number
          example: 29.88

    Precipitation:
      type: object
      properties:
        mm:
          type: number
          example: 0.5
        in:
          type: number
          example: 0.02

    Condition:
      type: object
      properties:
        text:
          type: string
          example: Partly cloudy
        icon:
          type: string
          example: //cdn.weatherapi.com/weather/64x64/day/116.png
        code:
          type: integer
          example: 1003

    AirQuality:
      type: object
      properties:
        co:
          type: number
          description: Carbon Monoxide (ug/m3)
          example: 230.3
        no2:
          type: number
          description: Nitrogen Dioxide (ug/m3)
          example: 13.5
        o3:
          type: number
          description: Ozone (ug/m3)
          example: 58.0
        so2:
          type: number
          description: Sulphur Dioxide (ug/m3)
          example: 7.2
        pm2_5:
          type: number
          description: PM2.5 (ug/m3)
          example: 8.1
        pm10:
          type: number
          description: PM10 (ug/m3)
          example: 12.3
        usEpaIndex:
          type: integer
          description: US EPA Air Quality Index (1-6)
          example: 1
        usEpaCategory:
          type: string
          description: US EPA category label
          example: Good
        gbDefraIndex:
          type: integer
          description: UK DEFRA Air Quality Index (1-10+)
          example: 2
        gbDefraCategory:
          type: string
          description: UK DEFRA category label
          example: Low

    Alert:
      type: object
      properties:
        headline:
          type: string
          example: Flood Warning issued February 18 at 9:00AM GMT
        severity:
          type: string
          example: Moderate
        urgency:
          type: string
          example: Expected
        event:
          type: string
          example: Flood Warning
        effective:
          type: string
          format: date-time
          example: "2026-02-18T09:00:00Z"
        expires:
          type: string
          format: date-time
          example: "2026-02-19T09:00:00Z"
        description:
          type: string
          example: Flooding is expected in low-lying areas.
        instruction:
          type: string
          example: Avoid travel to affected areas.

    HourlyData:
      type: object
      properties:
        time:
          type: string
          example: "2026-02-18 00:00"
        temperature:
          $ref: "#/components/schemas/Temperature"
        feelsLike:
          $ref: "#/components/schemas/Temperature"
        condition:
          $ref: "#/components/schemas/Condition"
        wind:
          type: object
          properties:
            kph:
              type: number
            mph:
              type: number
            direction:
              type: string
        humidity:
          type: integer
          example: 78
        cloud:
          type: integer
          example: 45
        chanceOfRain:
          type: integer
          example: 20
        chanceOfSnow:
          type: integer
          example: 0
        precipitation:
          $ref: "#/components/schemas/Precipitation"
        visibility:
          $ref: "#/components/schemas/Visibility"
        pressure:
          $ref: "#/components/schemas/Pressure"
        uv:
          type: number
          example: 3.0

    ForecastDay:
      type: object
      properties:
        date:
          type: string
          format: date
          example: "2026-02-18"
        temperature:
          type: object
          properties:
            max:
              $ref: "#/components/schemas/Temperature"
            min:
              $ref: "#/components/schemas/Temperature"
            avg:
              $ref: "#/components/schemas/Temperature"
        condition:
          $ref: "#/components/schemas/Condition"
        humidity:
          type: integer
          example: 72
        precipitation:
          type: object
          properties:
            mm:
              type: number
            in:
              type: number
            chanceOfRain:
              type: integer
            chanceOfSnow:
              type: integer
        wind:
          type: object
          properties:
            max:
              $ref: "#/components/schemas/WindSpeed"
        visibility:
          $ref: "#/components/schemas/Visibility"
        uv:
          type: number
          example: 3.0
        sunrise:
          type: string
          example: "07:15 AM"
        sunset:
          type: string
          example: "05:22 PM"
        moonrise:
          type: string
          example: "10:30 PM"
        moonset:
          type: string
          example: "08:45 AM"
        moonPhase:
          type: string
          example: Waning Gibbous
        hourly:
          type: array
          items:
            $ref: "#/components/schemas/HourlyData"

    SearchResult:
      type: object
      properties:
        id:
          type: integer
          example: 2801268
        name:
          type: string
          example: London
        region:
          type: string
          example: City of London, Greater London
        country:
          type: string
          example: United Kingdom
        lat:
          type: number
          example: 51.52
        lon:
          type: number
          example: -0.11
        url:
          type: string
          example: london-city-of-london-greater-london-united-kingdom

    SolarHourly:
      type: object
      properties:
        time:
          type: string
          example: "2026-02-18 12:00"
        uv:
          type: number
          example: 4.0
        isDay:
          type: boolean
          example: true
        cloudCover:
          type: integer
          example: 25
        shortwaveRadiation:
          type: number
          description: Shortwave radiation (W/m2)
          example: 450.5
        diffuseRadiation:
          type: number
          description: Diffuse radiation (W/m2)
          example: 120.3
        directNormalIrradiance:
          type: number
          description: Direct normal irradiance (W/m2)
          example: 580.0
        globalTiltedIrradiance:
          type: number
          description: Global tilted irradiance (W/m2)
          example: 490.2

    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          example: Location query (q) is required

  parameters:
    LocationQuery:
      name: q
      in: query
      required: true
      description: |
        Location query. Accepts:
        - City name (e.g., `London`)
        - Latitude,Longitude (e.g., `51.52,-0.11`)
        - UK/US/Canada postcode (e.g., `SW1A 1AA`)
        - IP address (e.g., `100.0.0.1`)
        - `auto:ip` for auto-detection
      schema:
        type: string
      example: London

    Units:
      name: units
      in: query
      required: false
      description: Unit system for temperature, wind, pressure, visibility, precipitation
      schema:
        type: string
        enum: [metric, imperial, both]
        default: both

    Include:
      name: include
      in: query
      required: false
      description: Choose to include daily summaries only, hourly data only, or both
      schema:
        type: string
        enum: [day, hour, all]
        default: all

    Exclude:
      name: exclude
      in: query
      required: false
      description: Comma-separated list of fields to exclude from response (e.g., `humidity,uv,moonPhase`)
      schema:
        type: string
      example: humidity,uv

    Lang:
      name: lang
      in: query
      required: false
      description: Language code for condition text (e.g., `fr`, `de`, `es`)
      schema:
        type: string
      example: en

paths:
  /v1/current:
    get:
      tags: [Standard]
      summary: Current Weather
      description: Get real-time weather conditions for a location, optionally including air quality data.
      operationId: getCurrentWeather
      parameters:
        - $ref: "#/components/parameters/LocationQuery"
        - $ref: "#/components/parameters/Units"
        - $ref: "#/components/parameters/Lang"
        - name: aqi
          in: query
          required: false
          description: Include air quality data
          schema:
            type: string
            enum: ["yes", "no"]
            default: "no"
      responses:
        "200":
          description: Current weather data
          content:
            application/json:
              schema:
                type: object
                properties:
                  location:
                    $ref: "#/components/schemas/Location"
                  temperature:
                    type: object
                    properties:
                      celsius:
                        type: number
                      fahrenheit:
                        type: number
                      feelsLike:
                        $ref: "#/components/schemas/FeelsLikeTemperature"
                  condition:
                    $ref: "#/components/schemas/Condition"
                  wind:
                    $ref: "#/components/schemas/Wind"
                  humidity:
                    type: integer
                  cloud:
                    type: integer
                  visibility:
                    $ref: "#/components/schemas/Visibility"
                  pressure:
                    $ref: "#/components/schemas/Pressure"
                  precipitation:
                    $ref: "#/components/schemas/Precipitation"
                  uv:
                    type: number
                  lastUpdated:
                    type: string
                  airQuality:
                    $ref: "#/components/schemas/AirQuality"
        "400":
          description: Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "402":
          description: Insufficient credits
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Daily free limit reached. Please add credits to continue.

  /v1/forecast:
    get:
      tags: [Standard]
      summary: Weather Forecast
      description: Get AI-enhanced weather forecast for up to 14 days with daily summaries and hourly breakdowns.
      operationId: getForecast
      parameters:
        - $ref: "#/components/parameters/LocationQuery"
        - $ref: "#/components/parameters/Units"
        - $ref: "#/components/parameters/Include"
        - $ref: "#/components/parameters/Exclude"
        - $ref: "#/components/parameters/Lang"
        - name: days
          in: query
          required: false
          description: Number of forecast days (1-14)
          schema:
            type: integer
            minimum: 1
            maximum: 14
            default: 3
        - name: aqi
          in: query
          required: false
          description: Include air quality data
          schema:
            type: string
            enum: ["yes", "no"]
            default: "no"
        - name: alerts
          in: query
          required: false
          description: Include weather alerts
          schema:
            type: string
            enum: ["yes", "no"]
            default: "no"
      responses:
        "200":
          description: Forecast data
          content:
            application/json:
              schema:
                type: object
                properties:
                  location:
                    $ref: "#/components/schemas/Location"
                  current:
                    type: object
                    properties:
                      temperature:
                        type: object
                        properties:
                          celsius:
                            type: number
                          fahrenheit:
                            type: number
                          feelsLike:
                            $ref: "#/components/schemas/Temperature"
                      condition:
                        $ref: "#/components/schemas/Condition"
                      humidity:
                        type: integer
                      wind:
                        type: object
                        properties:
                          kph:
                            type: number
                          mph:
                            type: number
                          direction:
                            type: string
                      lastUpdated:
                        type: string
                  forecast:
                    type: array
                    items:
                      $ref: "#/components/schemas/ForecastDay"
                  alerts:
                    type: array
                    items:
                      $ref: "#/components/schemas/Alert"
        "400":
          description: Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /v1/history:
    get:
      tags: [Premium]
      summary: Historical Weather
      description: |
        Get historical weather data for a specific date or date range (up to 30 days).
        This is a Premium endpoint (50 free calls/day).
      operationId: getHistory
      parameters:
        - $ref: "#/components/parameters/LocationQuery"
        - $ref: "#/components/parameters/Units"
        - $ref: "#/components/parameters/Include"
        - $ref: "#/components/parameters/Exclude"
        - $ref: "#/components/parameters/Lang"
        - name: dt
          in: query
          required: true
          description: Start date in YYYY-MM-DD format
          schema:
            type: string
            format: date
          example: "2026-01-01"
        - name: end_dt
          in: query
          required: false
          description: End date in YYYY-MM-DD format (max 30-day range)
          schema:
            type: string
            format: date
          example: "2026-01-07"
      responses:
        "200":
          description: Historical weather data
          content:
            application/json:
              schema:
                type: object
                properties:
                  location:
                    $ref: "#/components/schemas/Location"
                  history:
                    type: array
                    items:
                      $ref: "#/components/schemas/ForecastDay"
        "400":
          description: Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /v1/future:
    get:
      tags: [Premium]
      summary: Future Weather
      description: |
        Get extended future weather predictions for a date range (up to 30 days).
        This is a Premium endpoint (50 free calls/day).
      operationId: getFuture
      parameters:
        - $ref: "#/components/parameters/LocationQuery"
        - $ref: "#/components/parameters/Units"
        - $ref: "#/components/parameters/Include"
        - $ref: "#/components/parameters/Exclude"
        - $ref: "#/components/parameters/Lang"
        - name: dt
          in: query
          required: true
          description: Start date in YYYY-MM-DD format
          schema:
            type: string
            format: date
          example: "2026-03-01"
        - name: end_dt
          in: query
          required: false
          description: End date in YYYY-MM-DD format (max 30-day range)
          schema:
            type: string
            format: date
          example: "2026-03-07"
      responses:
        "200":
          description: Future weather predictions
          content:
            application/json:
              schema:
                type: object
                properties:
                  location:
                    $ref: "#/components/schemas/Location"
                  forecast:
                    type: array
                    items:
                      $ref: "#/components/schemas/ForecastDay"
        "400":
          description: Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /v1/timezone:
    get:
      tags: [Standard]
      summary: Timezone Information
      description: Get timezone information for a location.
      operationId: getTimezone
      parameters:
        - $ref: "#/components/parameters/LocationQuery"
      responses:
        "200":
          description: Timezone data
          content:
            application/json:
              schema:
                type: object
                properties:
                  name:
                    type: string
                    example: London
                  region:
                    type: string
                    example: City of London, Greater London
                  country:
                    type: string
                    example: United Kingdom
                  lat:
                    type: number
                    example: 51.52
                  lon:
                    type: number
                    example: -0.11
                  timezone:
                    type: string
                    example: Europe/London
                  localtime:
                    type: string
                    example: "2026-02-18 14:30"
                  localtimeEpoch:
                    type: integer
                    example: 1739886600
        "400":
          description: Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /v1/astronomy:
    get:
      tags: [Standard]
      summary: Sun & Moon Data
      description: Get astronomical data including sunrise, sunset, moonrise, moonset, and moon phase.
      operationId: getAstronomy
      parameters:
        - $ref: "#/components/parameters/LocationQuery"
        - name: dt
          in: query
          required: false
          description: Date in YYYY-MM-DD format (defaults to today)
          schema:
            type: string
            format: date
          example: "2026-02-18"
      responses:
        "200":
          description: Astronomy data
          content:
            application/json:
              schema:
                type: object
                properties:
                  location:
                    type: object
                    properties:
                      name:
                        type: string
                      region:
                        type: string
                      country:
                        type: string
                      lat:
                        type: number
                      lon:
                        type: number
                  astronomy:
                    type: object
                    properties:
                      sunrise:
                        type: string
                        example: "07:15 AM"
                      sunset:
                        type: string
                        example: "05:22 PM"
                      moonrise:
                        type: string
                        example: "10:30 PM"
                      moonset:
                        type: string
                        example: "08:45 AM"
                      moonPhase:
                        type: string
                        example: Waning Gibbous
                      moonIllumination:
                        type: string
                        example: "72"
                      isMoonUp:
                        type: boolean
                      isSunUp:
                        type: boolean
        "400":
          description: Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /v1/search:
    get:
      tags: [Standard]
      summary: Location Search
      description: Search for locations by name. Returns matching locations for autocomplete.
      operationId: searchLocations
      parameters:
        - name: q
          in: query
          required: true
          description: Search query (minimum 3 characters)
          schema:
            type: string
          example: London
      responses:
        "200":
          description: List of matching locations
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/SearchResult"
        "400":
          description: Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /v1/alerts:
    get:
      tags: [Standard]
      summary: Weather Alerts
      description: Get active weather alerts and warnings for a location.
      operationId: getAlerts
      parameters:
        - $ref: "#/components/parameters/LocationQuery"
      responses:
        "200":
          description: Weather alerts
          content:
            application/json:
              schema:
                type: object
                properties:
                  location:
                    $ref: "#/components/schemas/Location"
                  alerts:
                    type: array
                    items:
                      $ref: "#/components/schemas/Alert"
        "400":
          description: Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /v1/airquality:
    get:
      tags: [Standard]
      summary: Air Quality
      description: Get air quality index and pollutant data for a location.
      operationId: getAirQuality
      parameters:
        - $ref: "#/components/parameters/LocationQuery"
      responses:
        "200":
          description: Air quality data
          content:
            application/json:
              schema:
                type: object
                properties:
                  location:
                    $ref: "#/components/schemas/Location"
                  airQuality:
                    $ref: "#/components/schemas/AirQuality"
                  lastUpdated:
                    type: string
                    example: "2026-02-18 14:30"
        "400":
          description: Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /v1/solar:
    get:
      tags: [Premium]
      summary: Solar Irradiance
      description: |
        Get solar irradiance data including DNI, GHI, diffuse radiation, and UV index.
        This is a Premium endpoint (50 free calls/day).
      operationId: getSolar
      parameters:
        - $ref: "#/components/parameters/LocationQuery"
        - $ref: "#/components/parameters/Include"
        - $ref: "#/components/parameters/Exclude"
        - $ref: "#/components/parameters/Lang"
        - name: dt
          in: query
          required: false
          description: Date in YYYY-MM-DD format (defaults to today)
          schema:
            type: string
            format: date
          example: "2026-02-18"
      responses:
        "200":
          description: Solar irradiance data
          content:
            application/json:
              schema:
                type: object
                properties:
                  location:
                    $ref: "#/components/schemas/Location"
                  date:
                    type: string
                    format: date
                    example: "2026-02-18"
                  astro:
                    type: object
                    properties:
                      sunrise:
                        type: string
                        example: "07:15 AM"
                      sunset:
                        type: string
                        example: "05:22 PM"
                      moonrise:
                        type: string
                        example: "10:30 PM"
                      moonset:
                        type: string
                        example: "08:45 AM"
                      dayLength:
                        type: string
                        example: "10h 7m"
                  daily:
                    type: object
                    properties:
                      uvIndex:
                        type: number
                        example: 3.0
                      uvCategory:
                        type: string
                        example: Moderate
                      avgCloudCover:
                        type: integer
                        example: 45
                  hourly:
                    type: array
                    items:
                      $ref: "#/components/schemas/SolarHourly"
        "400":
          description: Missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "402":
          description: Insufficient credits for premium endpoint
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Premium daily free limit reached. Please add credits to continue.

  /v1/ai:
    post:
      tags: [Premium]
      summary: AI Natural-Language Weather Query
      description: |
        Submit a free-text weather question in plain English. Claude AI interprets the query,
        fetches the relevant live or historical weather data, and returns a natural-language answer
        alongside the raw JSON data it used.

        Authentication works the same as every other endpoint — use `X-API-Key` header,
        `Authorization: Bearer <api_key>`, or `?apiKey=<api_key>`.

        Each request costs **2 premium calls** against your daily quota. If the AI summary
        generation fails after the weather data has been retrieved, the charge is automatically
        refunded and `summary_error` is set in the response.

        **Streaming (SSE):** Set `Accept: text/event-stream` to receive the natural-language
        answer as Server-Sent Events while it is being generated, ideal for chat UIs.

        **Idempotency:** Pass `X-Request-Id` to safely retry without being charged twice.
      operationId: postAiQuery
      security:
        - ApiKeyAuth: []
        - bearerAuth: []
        - ApiKeyQuery: []
      parameters:
        - name: X-Request-Id
          in: header
          required: false
          description: Optional idempotency key — identical values within a short window return the cached response without re-charging credits
          schema:
            type: string
          example: "req_abc123"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [q]
              properties:
                q:
                  type: string
                  description: Free-text weather question in plain English
                  example: Will it rain in Tokyo next weekend?
      responses:
        "200":
          description: Natural-language answer plus raw weather data. If AI summary failed, `summary_error` is present and `answer` is null — credits are automatically refunded.
          headers:
            X-Idempotent-Replayed:
              description: Present with value `true` when the response was served from idempotency cache
              schema:
                type: string
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  credits_used:
                    type: integer
                    description: Number of premium credits deducted (0 if refunded due to summary_error)
                    example: 2
                  answer:
                    type: string
                    nullable: true
                    description: Natural-language answer to the question. Null when summary_error is present.
                    example: "Tokyo is forecast to have light rain on Saturday with around 60% chance of precipitation."
                  results:
                    type: array
                    description: Raw weather data for each location/date pair identified in the query
                    items:
                      type: object
                      properties:
                        location:
                          type: string
                          example: Tokyo, Japan
                        lat:
                          type: number
                          example: 35.69
                        lon:
                          type: number
                          example: 139.69
                        date:
                          type: string
                          format: date
                          example: "2026-04-27"
                        hour:
                          type: integer
                          nullable: true
                          description: Specific hour (0–23) if the query referenced a time of day; otherwise null
                          example: null
                        label:
                          type: string
                          description: Human-readable label for this location/date (derived from the query)
                          example: Tokyo next Saturday
                        weather:
                          type: object
                          nullable: true
                          properties:
                            temp_c:
                              type: number
                              nullable: true
                              example: 18.0
                            feelslike_c:
                              type: number
                              nullable: true
                              example: 16.5
                            condition:
                              type: string
                              nullable: true
                              example: Light rain
                            precip_mm:
                              type: number
                              nullable: true
                              example: 4.2
                            humidity:
                              type: integer
                              nullable: true
                              example: 82
                            wind_kph:
                              type: number
                              nullable: true
                              example: 14.0
                            wind_dir:
                              type: string
                              nullable: true
                              example: SE
                            cloud_pct:
                              type: integer
                              nullable: true
                              example: 75
                            vis_km:
                              type: number
                              nullable: true
                              example: 8.0
                            uv_index:
                              type: number
                              nullable: true
                              example: 2.0
                        error:
                          type: string
                          nullable: true
                          description: Set when weather lookup failed for this specific entry; other entries may still have data
                          example: null
                  summary_error:
                    type: object
                    nullable: true
                    description: Present only when AI summary generation failed. Credits are automatically refunded when this is set.
                    properties:
                      message:
                        type: string
                        example: AI summary unavailable — your account was not charged for this query.
                      reason:
                        type: string
                        description: Internal reason for the failure (e.g. upstream error, empty stream)
                        example: upstream_error
                      refunded:
                        type: boolean
                        example: true
        "400":
          description: Missing or invalid request body
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "402":
          description: Insufficient credits to process the request
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Insufficient credits. Please top up your account.
        "422":
          description: AI parsing failed — could not extract any location/date pairs from the query
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: AI parsing failed
                  detail:
                    type: string
                    example: Could not extract any location/date pairs from query
        "429":
          description: Premium daily limit exceeded and no payment method available
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Premium API daily limit exceeded
                  message:
                    type: string
                    example: Add a payment method or purchase credits to use the AI weather endpoint.
                  freeCallsRemaining:
                    type: integer
                    example: 0
        "503":
          description: AI service not configured on the server
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
