openapi: 3.1.0
info:
  title: Storm Evidence Weather API
  version: 1.0.0
  license:
    name: Proprietary
    url: https://www.getstormevidence.com/terms/
  summary: Observed and forecast severe weather lookup and report API for U.S. locations.
  description: >
    Storm Evidence provides customer-facing weather lookup and report endpoints
    for U.S. addresses and coordinates. Use the observed endpoint for historical
    and current severe-weather evidence, the forecast endpoint for model guidance
    and outlook polygons, the catalog endpoint for supported filter values, and
    the reports endpoints for Pro weather evidence PDFs.
servers:
  - url: https://api.getstormevidence.com
    description: Production
tags:
  - name: Weather
    description: API-key authenticated weather lookup endpoints.
  - name: Reports
    description: API-key authenticated Pro weather report endpoints.
paths:
  /v1/weather/observed:
    get:
      tags: [Weather]
      operationId: getObservedWeather
      summary: Query observed severe-weather evidence.
      description: >
        Returns observed severe-weather evidence near a coordinate or geocoded
        U.S. address. Either lat/lng or address is required. If both are
        supplied, coordinates take precedence. Evidence is paged with opaque
        cursors when the result set exceeds the requested limit.
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: "#/components/parameters/Lat"
        - $ref: "#/components/parameters/Lng"
        - $ref: "#/components/parameters/Address"
        - $ref: "#/components/parameters/ObservedDate"
        - $ref: "#/components/parameters/ObservedHour"
        - $ref: "#/components/parameters/ObservedStartTime"
        - $ref: "#/components/parameters/ObservedEndTime"
        - $ref: "#/components/parameters/Timezone"
        - $ref: "#/components/parameters/RadiusMiles"
        - $ref: "#/components/parameters/RadiusAlias"
        - $ref: "#/components/parameters/Perils"
        - $ref: "#/components/parameters/ObservedProviders"
        - $ref: "#/components/parameters/ObservedProducts"
        - $ref: "#/components/parameters/ObservedInclude"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Cursor"
      responses:
        "200":
          description: Observed weather response.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WeatherEnvelope"
              examples:
                observed_hail:
                  summary: Observed hail response
                  value:
                    data:
                      query:
                        endpoint: /v1/weather/observed
                        location:
                          input_type: coordinates
                          lat: 39.7392
                          lng: -104.9903
                        window:
                          start: "2024-05-31T01:00:00Z"
                          end: "2024-05-31T02:00:00Z"
                          timezone: America/Denver
                          granularity: hour
                        radius_miles: 2
                        perils: [hail]
                        providers: []
                        products: [hail_hourly_max]
                      summary:
                        has_observed_weather: true
                        event_count: 1
                        evidence_count: 1
                        perils_detected: [hail]
                        providers: [MRMS]
                        max_values:
                          hail:
                            value: 1.72
                            units: in
                            aggregation: max
                        rotation_context_detected: false
                        rotation_context_max_value: null
                      events:
                        - id: evt_1
                          peril: hail
                          event_start: "2024-05-31T01:00:00Z"
                          event_end: "2024-05-31T02:00:00Z"
                          max_value:
                            value: 1.72
                            units: in
                            aggregation: max
                          confidence: radar_estimate
                          providers: [MRMS]
                          evidence_count: 1
                          nearest_distance_miles: 0
                          evidence_ids: [obs_mrms_01j5example]
                      evidence:
                        - id: obs_mrms_01j5example
                          event_id: evt_1
                          provider: MRMS
                          source: hail_hourly_max
                          peril: hail
                          evidence_type: radar_estimate
                          valid_start: "2024-05-31T01:00:00Z"
                          valid_end: "2024-05-31T02:00:00Z"
                          value:
                            value: 1.72
                            units: in
                            aggregation: max
                          location_match:
                            match_type: raster_radius
                            distance_miles: 0
                            radius_miles: 2
                          quality:
                            completeness_status: complete
                            quality_status: final
                          artifact:
                            id: artifact_01j5example
                            product: hail_hourly_max
                            version: v1
                    meta:
                      request_id: 5f6d5f1a-7c6a-4c46-95bb-3d4a9ecb9b17
                      rate_limit:
                        limit: 100
                        remaining: 99
                        reset_at: "2026-05-20T12:01:00Z"
                      lookup_quota:
                        limit: 100000
                        used: 42
                        remaining: 99958
                        period_start: "2026-05-01"
                        period_end: "2026-06-01"
                        unlimited: false
                      pagination:
                        collection: evidence
                        limit: 500
                        returned: 1
                        has_more: false
                        scope: complete
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "422":
          $ref: "#/components/responses/UnsupportedLocation"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

  /v1/weather/forecast:
    get:
      tags: [Weather]
      operationId: getForecastWeather
      summary: Query forecast severe-weather guidance.
      description: >
        Returns forecast model guidance and outlook polygons near a coordinate
        or geocoded U.S. address. The valid window describes the period being
        forecast. as_of, run_time, and issued_at describe which forecast
        issuance should be selected.
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: "#/components/parameters/Lat"
        - $ref: "#/components/parameters/Lng"
        - $ref: "#/components/parameters/Address"
        - $ref: "#/components/parameters/ForecastDate"
        - $ref: "#/components/parameters/ForecastHour"
        - $ref: "#/components/parameters/ValidStart"
        - $ref: "#/components/parameters/ValidEnd"
        - $ref: "#/components/parameters/Timezone"
        - $ref: "#/components/parameters/AsOf"
        - $ref: "#/components/parameters/RunTime"
        - $ref: "#/components/parameters/IssuedAt"
        - $ref: "#/components/parameters/ForecastSources"
        - $ref: "#/components/parameters/RadiusMiles"
        - $ref: "#/components/parameters/RadiusAlias"
        - $ref: "#/components/parameters/Perils"
        - $ref: "#/components/parameters/ForecastProviders"
        - $ref: "#/components/parameters/Models"
        - $ref: "#/components/parameters/ForecastProducts"
        - $ref: "#/components/parameters/IncludeGeneral"
        - $ref: "#/components/parameters/ForecastInclude"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Cursor"
      responses:
        "200":
          description: Forecast response.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ForecastEnvelope"
              examples:
                forecast_guidance:
                  summary: Forecast guidance response
                  value:
                    data:
                      query:
                        endpoint: /v1/weather/forecast
                        location:
                          input_type: coordinates
                          lat: 35.4676
                          lng: -97.5164
                        valid_window:
                          start: "2026-05-20T18:00:00Z"
                          end: "2026-05-20T21:00:00Z"
                          timezone: UTC
                        forecast_time:
                          selection: latest_as_of
                          description: latest forecast available at or before as_of
                          as_of: "2026-05-20T12:00:00Z"
                        radius_miles: 1
                        perils: [hail, wind]
                        include_general: true
                        forecast_sources: [models, outlooks]
                        providers: []
                        models: []
                        products: []
                      summary:
                        forecast_count: 2
                        has_forecast_guidance: true
                        providers: [NOAA, SPC]
                        models: [hrrr]
                        perils: [hail, wind]
                        hazard_families: []
                        max_probabilities:
                          hail:
                            value: 15
                            units: percent
                            source: outlooks
                        max_values:
                          wind:
                            value: 58
                            units: mph
                            source: models
                        context_values: {}
                      forecasts:
                        - id: forecast_01j5example
                          provider: NOAA
                          source: models
                          model: hrrr
                          product: hrrr_gust_hourly_max
                          forecast_type: model_raster
                          forecast_kind: model_guidance
                          peril: wind
                          run_time: "2026-05-20T12:00:00Z"
                          forecast_hour: 6
                          valid_start: "2026-05-20T18:00:00Z"
                          valid_end: "2026-05-20T19:00:00Z"
                          lead_time_hours: 6
                          value:
                            value: 58
                            units: mph
                            aggregation: max
                          location_match:
                            match_type: raster_radius
                            distance_miles: 0
                            radius_miles: 1
                        - id: fcst_polygon_spc_01j5example
                          provider: SPC
                          source: outlooks
                          product: spc_hail_probability
                          forecast_type: outlook_polygon
                          forecast_kind: probability
                          hazard_family: convective
                          peril: hail
                          issued_at: "2026-05-20T12:00:00Z"
                          valid_start: "2026-05-20T18:00:00Z"
                          valid_end: "2026-05-20T21:00:00Z"
                          lead_time_hours: 6
                          outlook_day: 1
                          probability: 15
                          threshold: severe
                          location_match:
                            match_type: polygon_contains
                            distance_miles: 0
                    meta:
                      request_id: 5f6d5f1a-7c6a-4c46-95bb-3d4a9ecb9b17
                      rate_limit:
                        limit: 100
                        remaining: 99
                        reset_at: "2026-05-20T12:01:00Z"
                      lookup_quota:
                        limit: 100000
                        used: 43
                        remaining: 99957
                        period_start: "2026-05-01"
                        period_end: "2026-06-01"
                        unlimited: false
                      pagination:
                        collection: forecasts
                        limit: 500
                        returned: 2
                        has_more: false
                        scope: complete
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "422":
          $ref: "#/components/responses/UnsupportedLocation"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

  /v1/weather/catalog:
    get:
      tags: [Weather]
      operationId: getWeatherCatalog
      summary: List supported weather lookup values.
      description: >
        Returns supported perils, observed providers and products, forecast
        sources, forecast providers, forecast models, forecast products,
        include values, and pagination defaults. This endpoint is API-key
        authenticated and rate limited, but it does not consume monthly lookup
        quota.
      security:
        - ApiKeyAuth: []
      responses:
        "200":
          description: Weather catalog response.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WeatherCatalogEnvelope"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

  /v1/weather/reports/preview:
    post:
      tags: [Reports]
      operationId: previewWeatherReport
      summary: Preview report candidates.
      description: >
        Returns normalized report query details, report quota metadata, coverage
        context, and selectable candidate events. Preview does not generate or
        store a PDF.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ReportRequest"
            examples:
              preview_report:
                summary: Preview a single-date report
                value:
                  report_type: date_of_loss
                  address: 7420 Meadow Ridge Dr, Plano, TX
                  loss_date: "2026-05-20"
                  timezone: America/Chicago
                  radius_miles: 5
                  perils: [hail, wind, tornado]
                  include_forecast_context: true
      responses:
        "200":
          description: Report preview response.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReportPreviewEnvelope"
              examples:
                preview_report:
                  summary: Preview response
                  value:
                    data:
                      location:
                        input: 7420 Meadow Ridge Dr, Plano, TX
                        display_address: 7420 Meadow Ridge Dr, Plano, TX
                        lat: 33.0711
                        lng: -96.7683
                        confidence: rooftop
                      query:
                        report_type: date_of_loss
                        address: 7420 Meadow Ridge Dr, Plano, TX
                        lat: 33.0711
                        lng: -96.7683
                        display_address: 7420 Meadow Ridge Dr, Plano, TX
                        coarse_display_address: Plano, TX
                        location:
                          input: 7420 Meadow Ridge Dr, Plano, TX
                          display_address: 7420 Meadow Ridge Dr, Plano, TX
                          lat: 33.0711
                          lng: -96.7683
                          confidence: rooftop
                        window_start: "2026-05-20T05:00:00Z"
                        window_end: "2026-05-21T05:00:00Z"
                        timezone: America/Chicago
                        perils: [hail, wind, tornado]
                        radius_miles: 5
                        radius_bands_miles: [0, 1, 3, 5]
                        include_forecast_context: true
                        selected_event_date: "2026-05-20"
                      report_quota:
                        limit: 100
                        used: 12
                        remaining: 88
                        period_start: "2026-05-01"
                        period_end: "2026-06-01"
                        unlimited: false
                      coverage:
                        radar_estimates: true
                        rotation_context: false
                        storm_reports: true
                        warnings: false
                        official_history: false
                        forecast_context: false
                        truncated: false
                      candidates:
                        - id: candidate_2026-05-20_hail
                          event_start: "2026-05-20T22:30:00Z"
                          event_end: "2026-05-20T23:45:00Z"
                          date: "2026-05-20"
                          perils: [hail]
                          max_values:
                            hail:
                              value: 1.75
                              units: in
                          nearest_distance_miles: 0.4
                          radius_bands_hit: [1, 3, 5]
                          source_categories: [radar_estimate, official_storm_report]
                          confidence: radar_and_report
                          evidence_count: 2
                          evidence_ids: [obs_mrms_01j5example, obs_spc_01j5example]
                      warnings: []
                      preview_token: uIB2zA7Rc8qS5mXvN9pL0w
                      request_hash: cf2b7c...
                    meta:
                      request_id: 5f6d5f1a-7c6a
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

  /v1/weather/reports:
    post:
      tags: [Reports]
      operationId: createWeatherReport
      summary: Start weather evidence report generation.
      description: >
        Starts asynchronous generation for an immutable report snapshot and
        customer-ready PDF. Poll the report detail endpoint until status is
        ready or failed. Date-of-loss preview uses daily radar artifacts for
        speed, while generated reports use hourly radar artifacts for final
        precision. When selected_event_ids are supplied, preview_token must
        reference a valid preview for the same normalized request; generated
        date-of-loss reports may contain fewer selected events if hourly
        evidence does not confirm a daily preview match inside the selected
        24-hour window.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ReportRequest"
            examples:
              create_report:
                summary: Generate report from selected preview candidates
                value:
                  report_type: date_of_loss
                  address: 7420 Meadow Ridge Dr, Plano, TX
                  loss_date: "2026-05-20"
                  timezone: America/Chicago
                  radius_miles: 5
                  perils: [hail, wind, tornado]
                  preview_token: uIB2zA7Rc8qS5mXvN9pL0w
                  selected_event_ids: [candidate_2026-05-20_hail]
      responses:
        "202":
          description: Report generation accepted.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReportEnvelope"
              examples:
                accepted_report:
                  summary: Accepted report generation
                  value:
                    data:
                      id: d735185b-2eb7-4a84-ac75-88fc31152ecc
                      status: processing
                      report_type: date_of_loss
                      title: Weather Evidence Report
                      display_address: 7420 Meadow Ridge Dr, Plano, TX
                      claim_reference: ""
                      perils: [hail, wind, tornado]
                      window_start: "2026-05-20T05:00:00Z"
                      window_end: "2026-05-21T05:00:00Z"
                      summary: {}
                      event_count: 0
                      evidence_count: 0
                      created_at: "2026-05-22T18:12:08Z"
                      completed_at: null
                      poll_after_seconds: 5
                      links:
                        self: /v1/weather/reports/d735185b-2eb7-4a84-ac75-88fc31152ecc
                    meta:
                      request_id: 5f6d5f1a-7c6a
                      report_quota:
                        limit: 100
                        used: 13
                        remaining: 87
                        period_start: "2026-05-01"
                        period_end: "2026-06-01"
                        unlimited: false
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

  /v1/weather/reports/{id}:
    get:
      tags: [Reports]
      operationId: getWeatherReport
      summary: Retrieve report metadata and snapshot.
      description: >
        Returns report metadata. Ready reports may include the stored snapshot
        when the snapshot object is available.
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: "#/components/parameters/ReportID"
      responses:
        "200":
          description: Report detail response.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReportEnvelope"
              examples:
                report_detail:
                  summary: Ready report detail
                  value:
                    data:
                      id: d735185b-2eb7-4a84-ac75-88fc31152ecc
                      status: ready
                      report_type: date_of_loss
                      title: Weather Evidence Report
                      display_address: 7420 Meadow Ridge Dr, Plano, TX
                      claim_reference: ""
                      perils: [hail, wind, tornado]
                      window_start: "2026-05-20T05:00:00Z"
                      window_end: "2026-05-21T05:00:00Z"
                      selected_event_date: "2026-05-20"
                      summary:
                        event_count: 1
                        evidence_count: 2
                      event_count: 1
                      evidence_count: 2
                      snapshot_sha256: 8ad4e6...
                      created_at: "2026-05-22T18:12:08Z"
                      completed_at: "2026-05-22T18:12:08Z"
                      links:
                        self: /v1/weather/reports/d735185b-2eb7-4a84-ac75-88fc31152ecc
                        pdf: /v1/weather/reports/d735185b-2eb7-4a84-ac75-88fc31152ecc/pdf
                      snapshot:
                        id: d735185b-2eb7-4a84-ac75-88fc31152ecc
                        query:
                          report_type: date_of_loss
                          address: 7420 Meadow Ridge Dr, Plano, TX
                          lat: 33.0711
                          lng: -96.7683
                          display_address: 7420 Meadow Ridge Dr, Plano, TX
                          coarse_display_address: Plano, TX
                          location:
                            input: 7420 Meadow Ridge Dr, Plano, TX
                            display_address: 7420 Meadow Ridge Dr, Plano, TX
                            lat: 33.0711
                            lng: -96.7683
                            confidence: rooftop
                          window_start: "2026-05-20T05:00:00Z"
                          window_end: "2026-05-21T05:00:00Z"
                          timezone: America/Chicago
                          perils: [hail, wind, tornado]
                          radius_miles: 5
                          radius_bands_miles: [0, 1, 3, 5]
                          include_forecast_context: true
                          selected_event_ids: [candidate_2026-05-20_hail]
                          selected_event_date: "2026-05-20"
                        summary:
                          event_count: 1
                          evidence_count: 2
                        coverage:
                          radar_estimates: true
                          rotation_context: false
                          storm_reports: true
                          warnings: false
                          official_history: false
                          forecast_context: false
                          truncated: false
                        warnings: []
                        events:
                          - id: candidate_2026-05-20_hail
                            event_start: "2026-05-20T22:30:00Z"
                            event_end: "2026-05-20T23:45:00Z"
                            date: "2026-05-20"
                            perils: [hail]
                            max_values:
                              hail:
                                value: 1.75
                                units: in
                            nearest_distance_miles: 0.4
                            radius_bands_hit: [1, 3, 5]
                            source_categories: [radar_estimate, official_storm_report]
                            confidence: radar_and_report
                            evidence_count: 2
                            evidence_ids: [obs_mrms_01j5example, obs_spc_01j5example]
                        evidence:
                          - id: obs_mrms_01j5example
                            peril: hail
                            evidence_type: radar_estimate
                            source_category: radar_estimate
                            observed_at: "2026-05-20T22:30:00Z"
                            value:
                              value: 1.75
                              units: in
                              aggregation: max
                            distance_miles: 0.4
                            radius_band_miles: 1
                            quality:
                              status: final
                          - id: obs_spc_01j5example
                            peril: hail
                            evidence_type: storm_report
                            source_category: official_storm_report
                            observed_at: "2026-05-20T23:10:00Z"
                            value:
                              value: 1.75
                              units: in
                            distance_miles: 0.7
                            radius_band_miles: 1
                        generated_at: "2026-05-22T18:12:08Z"
                    meta:
                      request_id: 5f6d5f1a-7c6a
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

  /v1/weather/reports/{id}/pdf:
    get:
      tags: [Reports]
      operationId: downloadWeatherReportPDF
      summary: Download report PDF.
      description: Returns the generated report PDF as an attachment. Processing or failed reports return a conflict response.
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: "#/components/parameters/ReportID"
      responses:
        "200":
          description: Generated report PDF.
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          description: Report is still processing or failed generation.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorEnvelope"
              examples:
                processing:
                  summary: Report is still generating.
                  value:
                    error:
                      code: report_processing
                      message: Report is still processing
                    meta:
                      request_id: req_01HV0Y9B7K3TE4V2Z7M7J9T8C1
                failed:
                  summary: Report generation failed.
                  value:
                    error:
                      code: report_failed
                      message: Report generation failed
                    meta:
                      request_id: req_01HV0Y9B7K3TE4V2Z7M7J9T8C1
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

components:
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: Storm Evidence API key
      description: Account API key used for customer-facing weather lookup and report endpoints.

  parameters:
    Lat:
      name: lat
      in: query
      schema:
        type: number
        minimum: -90
        maximum: 90
      description: Required with lng when address is omitted. Coordinates take precedence over address.
    Lng:
      name: lng
      in: query
      schema:
        type: number
        minimum: -180
        maximum: 180
      description: Required with lat when address is omitted. Coordinates take precedence over address.
    Address:
      name: address
      in: query
      schema:
        type: string
      description: U.S. address to geocode when lat/lng are omitted.
    Timezone:
      name: timezone
      in: query
      schema:
        type: string
        default: UTC
        examples: ["UTC", "America/Chicago"]
      description: IANA timezone used to interpret date and hour.
    ObservedDate:
      name: date
      in: query
      schema:
        type: string
        format: date
      description: YYYY-MM-DD in the requested timezone. Cannot be combined with start_time or end_time.
    ObservedHour:
      name: hour
      in: query
      schema:
        type: string
        pattern: '^([01][0-9]|2[0-3]):00$'
        examples: ["07:00", "21:00"]
      description: Forward-looking hour in 24-hour HH:00 format. Requires date. For example, 04:00 covers 04:00 to before 05:00 in the requested timezone.
    ObservedStartTime:
      name: start_time
      in: query
      schema:
        type: string
        format: date-time
      description: Explicit observed search-window start. Requires end_time. Cannot be combined with date or hour. Raster products are returned when their valid window overlaps the request.
    ObservedEndTime:
      name: end_time
      in: query
      schema:
        type: string
        format: date-time
      description: Explicit observed search-window end. Requires start_time and must be after start_time. Observed windows cannot exceed 31 days. Partial-hour ranges can return overlapping hourly artifacts with their own valid_start and valid_end.
    ForecastDate:
      name: date
      in: query
      schema:
        type: string
        format: date
      description: YYYY-MM-DD in the requested timezone. Cannot be combined with valid_start or valid_end.
    ForecastHour:
      name: hour
      in: query
      schema:
        type: string
        pattern: '^([01][0-9]|2[0-3]):00$'
        examples: ["07:00", "21:00"]
      description: Forecast valid hour in 24-hour HH:00 format. Requires date.
    ValidStart:
      name: valid_start
      in: query
      schema:
        type: string
        format: date-time
      description: Explicit forecast valid-window start. Requires valid_end. Cannot be combined with date or hour.
    ValidEnd:
      name: valid_end
      in: query
      schema:
        type: string
        format: date-time
      description: Explicit forecast valid-window end. Requires valid_start and must be after valid_start.
    AsOf:
      name: as_of
      in: query
      schema:
        type: string
        format: date-time
      description: Latest forecast available at or before this timestamp. Cannot be combined with run_time or issued_at.
    RunTime:
      name: run_time
      in: query
      schema:
        type: string
        format: date-time
      description: Select a specific forecast model run. Requires forecast_sources=models if forecast_sources is supplied.
    IssuedAt:
      name: issued_at
      in: query
      schema:
        type: string
        format: date-time
      description: Select a specific outlook issue time. Requires forecast_sources=outlooks if forecast_sources is supplied.
    RadiusMiles:
      name: radius_miles
      in: query
      schema:
        type: number
        default: 1
        exclusiveMinimum: 0
      description: Positive radius in miles. Plan limits apply.
    RadiusAlias:
      name: radius
      in: query
      schema:
        type: number
        exclusiveMinimum: 0
      description: Compatibility alias for radius_miles. Prefer radius_miles in new integrations.
    Perils:
      name: perils
      in: query
      schema:
        type: string
        default: hail,rain,wind,tornado
        examples: ["hail", "hail,wind", "rain"]
      description: Comma-separated subset of hail,rain,wind,tornado. rainfall is accepted as rain.
    ObservedProviders:
      name: providers
      in: query
      schema:
        type: string
        examples: ["mrms", "spc,lsr", "storm_events,warnings"]
      description: Comma-separated observed provider filter. Allowed values are mrms,spc,lsr,storm_events,warnings.
    ForecastProviders:
      name: providers
      in: query
      schema:
        type: string
        examples: ["noaa", "spc,wpc"]
      description: Comma-separated forecast provider filter. Allowed values are noaa,spc,wpc.
    Models:
      name: models
      in: query
      schema:
        type: string
        examples: ["hrrr", "nbm", "hrrr,nbm"]
      description: Comma-separated forecast model filter. Allowed values are hrrr,nbm.
    ObservedProducts:
      name: products
      in: query
      schema:
        type: string
        examples: ["hail_hourly_max", "rain_daily_total,rotation_low_daily_max"]
      description: Comma-separated observed product IDs. Use /v1/weather/catalog for the current list.
    ForecastProducts:
      name: products
      in: query
      schema:
        type: string
        examples: ["hrrr_hail_hourly_max", "spc_hail_probability,wpc_excessive_rainfall_outlook"]
      description: Comma-separated forecast product IDs. Use /v1/weather/catalog for the current list.
    ForecastSources:
      name: forecast_sources
      in: query
      schema:
        type: string
        default: models,outlooks
        examples: ["models", "outlooks", "models,outlooks"]
      description: Comma-separated subset of models,outlooks.
    IncludeGeneral:
      name: include_general
      in: query
      schema:
        type: boolean
        default: false
      description: Include broad convective products such as thunder probability and categorical outlooks.
    ObservedInclude:
      name: include
      in: query
      schema:
        type: string
        default: summary,events
        examples: ["summary", "summary,events", "summary,events,evidence"]
      description: Comma-separated subset of summary,events,evidence.
    ForecastInclude:
      name: include
      in: query
      schema:
        type: string
        default: summary,forecasts
        examples: ["summary", "forecasts", "summary,forecasts"]
      description: Comma-separated subset of summary,forecasts.
    Limit:
      name: limit
      in: query
      schema:
        type: integer
        default: 500
        minimum: 1
        maximum: 500
      description: Maximum records returned for the paged collection.
    Cursor:
      name: cursor
      in: query
      schema:
        type: string
        pattern: "^cur_[A-Za-z0-9_-]+$"
      description: Opaque cursor from meta.pagination.next_cursor. Cursor requests may include only cursor and the same limit.
    ReportID:
      name: id
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Public report ID returned by the create report endpoint.

  responses:
    BadRequest:
      description: Query parameters are invalid or the query is too broad.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
    Forbidden:
      description: The active plan does not allow the requested lookup.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
    UnsupportedLocation:
      description: The location could not be used for weather lookup.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
    NotFound:
      description: Report not found.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
    RateLimited:
      description: Per-minute rate limit or monthly lookup quota exceeded.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
    InternalError:
      description: Lookup failed after the request was accepted.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
    ServiceUnavailable:
      description: A required platform service is unavailable.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"

  schemas:
    Meta:
      type: object
      additionalProperties: true
      required: [request_id]
      properties:
        request_id:
          type: string
        rate_limit:
          $ref: "#/components/schemas/RateLimitMeta"
        lookup_quota:
          $ref: "#/components/schemas/LookupQuotaMeta"
        pagination:
          $ref: "#/components/schemas/PaginationMeta"
        warnings:
          type: array
          items:
            type: string
    RateLimitMeta:
      type: object
      required: [limit, remaining, reset_at]
      properties:
        limit:
          type: integer
        remaining:
          type: integer
        reset_at:
          type: string
          format: date-time
    LookupQuotaMeta:
      type: object
      required: [limit, used, remaining, period_start, period_end, unlimited]
      properties:
        limit:
          type: [integer, "null"]
          description: Monthly lookup limit. Null for custom or unlimited plans.
        used:
          type: [integer, "null"]
          description: Successful weather lookups used in the current UTC month.
        remaining:
          type: [integer, "null"]
          description: Remaining monthly lookups.
        period_start:
          type: string
          format: date
        period_end:
          type: string
          format: date
        unlimited:
          type: boolean
    PaginationMeta:
      type: object
      required: [collection, limit, returned, has_more, scope]
      properties:
        collection:
          type: string
          enum: [evidence, forecasts]
        limit:
          type: integer
          minimum: 1
          maximum: 500
        returned:
          type: integer
          minimum: 0
        has_more:
          type: boolean
        scope:
          type: string
          enum: [complete, page]
          description: complete means the response includes all records in the collection; page means the collection was explicitly paged or has another page.
        next_cursor:
          type: string
          description: Opaque cursor for the next page. Present only when has_more is true.
    Error:
      type: object
      required: [code, message]
      properties:
        code:
          type: string
        message:
          type: string
    ErrorEnvelope:
      type: object
      required: [error, meta]
      properties:
        error:
          $ref: "#/components/schemas/Error"
        meta:
          $ref: "#/components/schemas/Meta"
    WeatherEnvelope:
      type: object
      required: [data, meta]
      properties:
        data:
          $ref: "#/components/schemas/WeatherResponse"
        meta:
          $ref: "#/components/schemas/Meta"
    ForecastEnvelope:
      type: object
      required: [data, meta]
      properties:
        data:
          $ref: "#/components/schemas/ForecastResponse"
        meta:
          $ref: "#/components/schemas/Meta"
    WeatherCatalogEnvelope:
      type: object
      required: [data, meta]
      properties:
        data:
          $ref: "#/components/schemas/WeatherCatalog"
        meta:
          $ref: "#/components/schemas/Meta"
    ReportPreviewEnvelope:
      type: object
      required: [data, meta]
      properties:
        data:
          type: object
          required: [location, query, report_quota, coverage, candidates, warnings, preview_token, request_hash]
          properties:
            location:
              $ref: "#/components/schemas/ReportLocation"
            query:
              $ref: "#/components/schemas/ReportQuery"
            report_quota:
              $ref: "#/components/schemas/ReportQuotaMeta"
            coverage:
              type: object
              additionalProperties: true
            candidates:
              type: array
              items:
                $ref: "#/components/schemas/ReportCandidate"
            warnings:
              type: array
              items:
                type: string
            preview_token:
              type: string
            request_hash:
              type: string
        meta:
          $ref: "#/components/schemas/Meta"
    ReportEnvelope:
      type: object
      required: [data, meta]
      properties:
        data:
          $ref: "#/components/schemas/Report"
        meta:
          allOf:
            - $ref: "#/components/schemas/Meta"
            - type: object
              properties:
                report_quota:
                  $ref: "#/components/schemas/ReportQuotaMeta"
    ReportRequest:
      type: object
      properties:
        report_type:
          type: string
          enum: [property_history, date_of_loss]
          default: property_history
        address:
          type: string
        lat:
          type: number
          minimum: -90
          maximum: 90
        lng:
          type: number
          minimum: -180
          maximum: 180
        claim_reference:
          type: string
          maxLength: 120
        insured_or_customer_name:
          type: string
          maxLength: 160
        private_notes:
          type: string
          maxLength: 500
          description: Accepted on requests but intentionally not returned in report query payloads or PDFs.
        start_date:
          type: string
          format: date
        end_date:
          type: string
          format: date
        loss_date:
          type: string
          format: date
          description: Required for date_of_loss reports.
        timezone:
          type: string
          default: UTC
        perils:
          type: array
          items:
            type: string
            enum: [hail, wind, tornado]
          default: [hail, wind, tornado]
        radius_miles:
          type: number
          exclusiveMinimum: 0
          default: 5
        include_forecast_context:
          type: boolean
          default: false
        selected_event_id:
          type: string
          deprecated: true
          description: Backward-compatible single selected event ID. Prefer selected_event_ids.
        selected_event_ids:
          type: array
          items:
            type: string
          description: Candidate event IDs selected from a preview response. Date-of-loss candidate IDs are stable date/peril values such as candidate_2026-05-20_hail.
        preview_token:
          type: string
          description: Required when selected_event_ids are supplied. If supplied with an empty selection, generation preserves the empty/no-event selection.
    ReportQuery:
      type: object
      additionalProperties: true
      required: [report_type, lat, lng, display_address, location, window_start, window_end, timezone, perils, radius_miles, radius_bands_miles, include_forecast_context]
      properties:
        report_type:
          type: string
          enum: [property_history, date_of_loss]
        address:
          type: string
        lat:
          type: number
        lng:
          type: number
        display_address:
          type: string
        coarse_display_address:
          type: string
        location:
          $ref: "#/components/schemas/ReportLocation"
        claim_reference:
          type: string
        insured_or_customer_name:
          type: string
        window_start:
          type: string
          format: date-time
        window_end:
          type: string
          format: date-time
        timezone:
          type: string
        perils:
          type: array
          items:
            type: string
            enum: [hail, wind, tornado]
        radius_miles:
          type: number
        radius_bands_miles:
          type: array
          items:
            type: number
        include_forecast_context:
          type: boolean
        selected_event_id:
          type: string
        selected_event_ids:
          type: array
          items:
            type: string
        selected_event_date:
          type: string
          format: date
    ReportLocation:
      type: object
      additionalProperties: true
      properties:
        input:
          type: string
        display_address:
          type: string
        lat:
          type: number
        lng:
          type: number
        type:
          type: string
        confidence:
          type: string
    ReportCandidate:
      type: object
      required: [id, event_start, event_end, date, perils, max_values, nearest_distance_miles, radius_bands_hit, source_categories, confidence, evidence_count, evidence_ids]
      properties:
        id:
          type: string
        event_start:
          type: string
          format: date-time
        event_end:
          type: string
          format: date-time
        date:
          type: string
          format: date
        perils:
          type: array
          items:
            type: string
            enum: [hail, wind, tornado]
        max_values:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/ValueMeasurement"
        nearest_distance_miles:
          type: number
        radius_bands_hit:
          type: array
          items:
            type: number
        source_categories:
          type: array
          items:
            type: string
        confidence:
          type: string
        evidence_count:
          type: integer
        evidence_ids:
          type: array
          items:
            type: string
    ReportSnapshot:
      type: object
      required: [query, summary, coverage, warnings, events, evidence, generated_at]
      properties:
        id:
          type: string
        query:
          $ref: "#/components/schemas/ReportQuery"
        summary:
          type: object
          additionalProperties: true
        coverage:
          type: object
          additionalProperties: true
        warnings:
          type: array
          items:
            type: string
        events:
          type: array
          items:
            $ref: "#/components/schemas/ReportCandidate"
        evidence:
          type: array
          items:
            $ref: "#/components/schemas/ReportEvidence"
        generated_at:
          type: string
          format: date-time
    ReportEvidence:
      type: object
      required: [id, peril, evidence_type, source_category, distance_miles, radius_band_miles]
      properties:
        id:
          type: string
        peril:
          type: string
          enum: [hail, wind, tornado]
        evidence_type:
          type: string
        source_category:
          type: string
        observed_at:
          type: string
          format: date-time
        valid_start:
          type: string
          format: date-time
        valid_end:
          type: string
          format: date-time
        value:
          $ref: "#/components/schemas/ValueMeasurement"
        distance_miles:
          type: number
        radius_band_miles:
          type: number
        quality:
          type: object
          additionalProperties:
            type: string
    Report:
      type: object
      required: [id, status, report_type, title, display_address, perils, window_start, window_end, summary, event_count, evidence_count, created_at, completed_at, links]
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
          enum: [processing, ready, failed, deleted]
        report_type:
          type: string
          enum: [property_history, date_of_loss]
        title:
          type: string
        display_address:
          type: string
        claim_reference:
          type: string
        perils:
          type: array
          items:
            type: string
            enum: [hail, wind, tornado]
        window_start:
          type: string
          format: date-time
        window_end:
          type: string
          format: date-time
        selected_event_date:
          type: string
          format: date
        summary:
          type: object
          additionalProperties: true
        event_count:
          type: integer
        evidence_count:
          type: integer
        snapshot_sha256:
          type: string
        created_at:
          type: string
          format: date-time
        completed_at:
          type: [string, "null"]
          format: date-time
        poll_after_seconds:
          type: integer
          description: Recommended polling interval in seconds while status is processing.
        links:
          $ref: "#/components/schemas/ReportLinks"
        error_code:
          type: string
        error_message:
          type: string
        snapshot:
          $ref: "#/components/schemas/ReportSnapshot"
    ReportLinks:
      type: object
      required: [self]
      properties:
        self:
          type: string
        pdf:
          type: string
    ReportQuotaMeta:
      type: object
      required: [limit, used, remaining, period_start, period_end, unlimited]
      properties:
        limit:
          type: [integer, "null"]
          description: Monthly report limit. Null for custom or unlimited plans.
        used:
          type: [integer, "null"]
          description: Reports used in the current UTC month.
        remaining:
          type: [integer, "null"]
          description: Remaining monthly reports.
        period_start:
          type: string
          format: date
        period_end:
          type: string
          format: date
        unlimited:
          type: boolean
    WeatherResponse:
      type: object
      required: [query]
      properties:
        query:
          $ref: "#/components/schemas/ObservedQueryEcho"
        summary:
          $ref: "#/components/schemas/ObservedSummary"
        events:
          type: array
          items:
            $ref: "#/components/schemas/Event"
        evidence:
          type: array
          items:
            $ref: "#/components/schemas/Evidence"
    ForecastResponse:
      type: object
      required: [query]
      properties:
        query:
          $ref: "#/components/schemas/ForecastQueryEcho"
        summary:
          $ref: "#/components/schemas/ForecastSummary"
        forecasts:
          type: array
          items:
            $ref: "#/components/schemas/Forecast"
    ObservedQueryEcho:
      type: object
      additionalProperties: true
      properties:
        endpoint:
          type: string
        location:
          $ref: "#/components/schemas/Location"
        window:
          $ref: "#/components/schemas/Window"
        radius_miles:
          type: number
        perils:
          type: array
          items:
            type: string
        providers:
          type: array
          items:
            type: string
        products:
          type: array
          items:
            type: string
    ForecastQueryEcho:
      type: object
      additionalProperties: true
      properties:
        endpoint:
          type: string
        location:
          $ref: "#/components/schemas/Location"
        valid_window:
          $ref: "#/components/schemas/Window"
        forecast_time:
          $ref: "#/components/schemas/ForecastTime"
        radius_miles:
          type: number
        perils:
          type: array
          items:
            type: string
        include_general:
          type: boolean
        forecast_sources:
          type: array
          items:
            type: string
        providers:
          type: array
          items:
            type: string
        models:
          type: array
          items:
            type: string
        products:
          type: array
          items:
            type: string
    Location:
      type: object
      additionalProperties: true
      required: [input_type]
      properties:
        input_type:
          type: string
          examples: ["coordinates", "address"]
        input:
          type: string
        lat:
          type: number
        lng:
          type: number
        resolved:
          type: object
          additionalProperties: true
    Window:
      type: object
      required: [start, end, timezone]
      properties:
        start:
          type: string
          format: date-time
        end:
          type: string
          format: date-time
        timezone:
          type: string
        granularity:
          type: string
          enum: [hour, day]
    ForecastTime:
      type: object
      additionalProperties: false
      properties:
        selection:
          type: string
          enum: [latest_as_of, run_time, issued_at, exact_run_and_issue]
        description:
          type: string
        as_of:
          type: string
          format: date-time
        run_time:
          type: string
          format: date-time
        issued_at:
          type: string
          format: date-time
    ObservedSummary:
      type: object
      required: [has_observed_weather, event_count, evidence_count, perils_detected, rotation_context_detected]
      properties:
        has_observed_weather:
          type: boolean
        event_count:
          type: integer
        evidence_count:
          type: integer
        perils_detected:
          type: array
          items:
            type: string
        providers:
          type: array
          items:
            type: string
        max_values:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/ValueMeasurement"
        rotation_context_detected:
          type: boolean
        rotation_context_max_value:
          anyOf:
            - $ref: "#/components/schemas/ValueMeasurement"
            - type: "null"
    ForecastSummary:
      type: object
      additionalProperties: true
      properties:
        forecast_count:
          type: integer
        has_forecast_guidance:
          type: boolean
        providers:
          type: array
          items:
            type: string
        models:
          type: array
          items:
            type: string
        perils:
          type: array
          items:
            type: string
        hazard_families:
          type: array
          items:
            type: string
        max_probabilities:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/SummaryMetric"
        max_values:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/SummaryMetric"
        context_values:
          type: object
          additionalProperties:
            type: object
            additionalProperties:
              $ref: "#/components/schemas/SummaryMetric"
    SummaryMetric:
      type: object
      additionalProperties: true
      properties:
        value:
          type: number
        units:
          type: string
        source:
          type: string
    Event:
      type: object
      required: [id, peril, event_start, event_end, confidence, providers, evidence_count, nearest_distance_miles, evidence_ids]
      properties:
        id:
          type: string
        peril:
          type: string
          enum: [hail, rain, wind, tornado]
        event_start:
          type: string
          format: date-time
        event_end:
          type: string
          format: date-time
        max_value:
          $ref: "#/components/schemas/ValueMeasurement"
        confidence:
          type: string
        providers:
          type: array
          items:
            type: string
        evidence_count:
          type: integer
        nearest_distance_miles:
          type: number
        evidence_ids:
          type: array
          items:
            type: string
        rotation_context_only:
          type: boolean
    Evidence:
      type: object
      required: [id, provider, source, peril, evidence_type, location_match]
      properties:
        id:
          type: string
        event_id:
          type: string
        provider:
          type: string
          description: Provider display name. This field is intentionally not an enum.
        source:
          type: string
        peril:
          type: string
          enum: [hail, rain, wind, tornado]
        evidence_type:
          type: string
        confidence_tier:
          type: string
        observed_at:
          type: string
          format: date-time
        valid_start:
          type: string
          format: date-time
        valid_end:
          type: string
          format: date-time
        value:
          $ref: "#/components/schemas/ValueMeasurement"
        location_match:
          $ref: "#/components/schemas/LocationMatch"
        quality:
          $ref: "#/components/schemas/Quality"
        artifact:
          $ref: "#/components/schemas/ArtifactRef"
    Forecast:
      type: object
      required: [id, provider, source, product, forecast_type, forecast_kind, valid_start, valid_end, location_match]
      additionalProperties: true
      properties:
        id:
          type: string
        provider:
          type: string
        source:
          type: string
          enum: [models, outlooks]
        model:
          type: string
        product:
          type: string
        forecast_type:
          type: string
        forecast_kind:
          type: string
        hazard_family:
          type: string
        peril:
          type: [string, "null"]
        applies_to_perils:
          type: array
          items:
            type: string
        issued_at:
          type: string
          format: date-time
        run_time:
          type: string
          format: date-time
        forecast_hour:
          type: integer
        valid_start:
          type: string
          format: date-time
        valid_end:
          type: string
          format: date-time
        lead_time_hours:
          type: number
        outlook_day:
          type: integer
        category:
          type: string
        probability:
          type: number
        threshold:
          type: string
        value:
          $ref: "#/components/schemas/ValueMeasurement"
        location_match:
          $ref: "#/components/schemas/LocationMatch"
        quality:
          $ref: "#/components/schemas/Quality"
        artifact:
          $ref: "#/components/schemas/ArtifactRef"
        context_type:
          type: string
        tornado_context_only:
          type: boolean
    ValueMeasurement:
      type: object
      additionalProperties: true
      properties:
        value:
          type: [number, "null"]
        units:
          type: string
        aggregation:
          type: string
        sampled_cell_count:
          type: integer
        valid_cell_count:
          type: integer
        min:
          type: number
        max:
          type: number
        sum:
          type: number
    LocationMatch:
      type: object
      additionalProperties: true
      properties:
        match_type:
          type: string
        distance_miles:
          type: number
        radius_miles:
          type: number
    Quality:
      type: object
      additionalProperties: true
      properties:
        completeness_status:
          type: string
        quality_status:
          type: string
        generation_status:
          type: string
    ArtifactRef:
      type: object
      required: [id, product, version]
      properties:
        id:
          type: string
        product:
          type: string
        version:
          type: string
    WeatherCatalog:
      type: object
      required: [perils, observed, forecast, query]
      properties:
        perils:
          type: array
          items:
            $ref: "#/components/schemas/CatalogItem"
        observed:
          type: object
          required: [providers, products]
          properties:
            providers:
              type: array
              items:
                $ref: "#/components/schemas/ProviderCatalogItem"
            products:
              type: array
              items:
                $ref: "#/components/schemas/ObservedProductCatalogItem"
        forecast:
          type: object
          required: [sources, providers, models, products]
          properties:
            sources:
              type: array
              items:
                $ref: "#/components/schemas/ProviderCatalogItem"
            providers:
              type: array
              items:
                $ref: "#/components/schemas/ProviderCatalogItem"
            models:
              type: array
              items:
                $ref: "#/components/schemas/ForecastModelCatalogItem"
            products:
              type: array
              items:
                $ref: "#/components/schemas/ForecastProductCatalogItem"
        query:
          type: object
          additionalProperties: true
    CatalogItem:
      type: object
      required: [id, label]
      additionalProperties: false
      properties:
        id:
          type: string
        label:
          type: string
    ProviderCatalogItem:
      type: object
      required: [id, label, description]
      additionalProperties: false
      properties:
        id:
          type: string
        label:
          type: string
        description:
          type: string
    ForecastModelCatalogItem:
      type: object
      required: [id, label, provider]
      additionalProperties: false
      properties:
        id:
          type: string
        label:
          type: string
        provider:
          type: string
    ObservedProductCatalogItem:
      type: object
      required: [id, label, peril, evidence_type, granularity, aggregation]
      additionalProperties: false
      properties:
        id:
          type: string
        label:
          type: string
        peril:
          type: string
        evidence_type:
          type: string
        granularity:
          type: string
        aggregation:
          type: string
    ForecastProductCatalogItem:
      type: object
      required: [id, label, provider, source, forecast_type, forecast_kind, general]
      additionalProperties: false
      properties:
        id:
          type: string
        label:
          type: string
        provider:
          type: string
        source:
          type: string
        model:
          type: string
        peril:
          type: string
        forecast_type:
          type: string
        forecast_kind:
          type: string
        hazard_family:
          type: string
        applies_to_perils:
          type: array
          items:
            type: string
        aggregation:
          type: string
        context_type:
          type: string
        tornado_context_only:
          type: boolean
        general:
          type: boolean
