> For the complete documentation index, see [llms.txt](https://api-v2-docs.disasteraware.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://api-v2-docs.disasteraware.com/hazards/requesting-hail.md).

# Requesting Hail Hazards

To request the list of active hail hazards please use the route defined here:

{% openapi src="/files/wYQaKpPZEdPb68ZWOF6w" path="/hail" method="get" %}
[openapi.yaml](https://3664004773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbwQ2AvqpbIy1hD3QFTQG%2Fuploads%2Fgit-blob-4fc8ade7ac9fbaa181ac86605d2bddb657fbc964%2Fopenapi.yaml?alt=media)
{% endopenapi %}

{% hint style="info" %}
See [Authorizing Requests](/authentication/authorizing-requests.md#get-accesstoken-and-refreshtoken) page to get your accessToken.
{% endhint %}

{% hint style="warning" %}
**This endpoint requires a specific role for hail feed access on your credentials.** It is not enabled by default, and credentials that work against the other hazard endpoints will not necessarily work here.

If your token is valid elsewhere but this endpoint returns `403`, your credentials are missing the required role. Contact your sales contact or <support@disasteraware.com> to have it added, or if you are interested in hail data and do not have access today.
{% endhint %}

Hail hazards are DisasterAWARE hazards of type `STORM` with `incident.properties.subType` of `HAIL`. Each one is built from the NWS severe thunderstorm warnings carrying a hail tag, the MRMS radar hail swaths, and the ground hail reports that belong to the same storm, so a single hazard carries the warning text, the radar footprint and the reports together. DisasterAWARE `STORM` and `TORNADO` records are not returned here.

## How the feed works

The endpoint serves a file, not a query result:

* **No parameters** — a `302` redirect to the current gzipped NDJSON file, one hazard per line, with every active hail hazard included. The link is valid for **1 hour**.
* **With parameters** — a `302` to a filtered file, valid for **5 minutes**, plus an `X-Match-Count` header. Zero matches is still a `302`, to an empty file.
* **Freshness headers on every `302`** — `X-Feed`, `X-Generated-At` (when the file was last written) and `X-Heartbeat-At` (the feed's last heartbeat), as ISO 8601 UTC.
* **The file carries the same values as S3 metadata** — `x-amz-meta-generated-at` and `x-amz-meta-heartbeat-at`, plus `x-amz-meta-record-count` on the unfiltered file. This matters because **most HTTP clients discard the first response's headers when they follow a redirect**, so read the freshness from the file's metadata if your client follows the `302` for you.
* **Staleness** — the file is rewritten when something changes, at most every 2 minutes, so polling faster than that gains nothing. The feed publishes a heartbeat to prove it is running; if that heartbeat is more than **15 minutes** old the endpoint returns `503 {"error": "Live feed temporarily unavailable"}` with `Retry-After: 60` rather than serving stale data. A `503` is not routine — it means the feed is not current. Each feed is monitored separately, so a `503` on `/hail` says nothing about `/wind`: a client polling both should handle each response on its own.
* **Scope** — `scope=active` is the default and the only value available. `scope=historical` and `scope=all` return `501` naming the available scopes.

### Polling

Take the `X-Generated-At` value from your last response and pass it back as `updated_since` to receive only the hazards that have changed since then. `updatedAt` changes only when a hazard's content changes, and `version` counts those changes.

### When a hazard leaves the feed

This is an **active-only** feed. A hazard leaves the file on the first write after it ends, and moves to the history archive — which `scope=historical` will serve when it becomes available.

{% hint style="info" %}
A hazard that has disappeared from the file has **ended**; it has not been deleted. Because the file holds only current hazards, a client that needs to detect endings should compare successive files rather than waiting for a final record. Merged hazards also leave: the absorbed hazard ends with `end_basis` of `merged` and `incident.properties.supersededBy` set to the surviving hazard's uuid.
{% endhint %}

## Query Parameters

All parameters are optional, combine with AND, and take comma-separated lists meaning "any of", matched case-insensitively. Anything that works as a `country` value on [`/active-hazards-query`](/hazards/requesting-active-hazards.md) works here, and these endpoints also accept ISO 3166 codes. Timestamps are UTC, as `YYYY-MM-DD HH:MM:SS` or `YYYY-MM-DDTHH:MM:SSZ`.

A misspelled parameter or a value outside a closed set returns `400` with the offending parameter, its value, and either `allowed_values`, `allowed_parameters` or `expected_format`. **A bad value is never a silent empty result.**

A `403` means one of three things — no token, an invalid token, or a credential without the required role — and the response is identical in all three cases:

```json
{"Message": "User is not authorized to access this resource with an explicit deny in an identity-based policy"}
```

So a `403` cannot be read as "my role is missing". Check the token first, then ask whether the credential carries the required role.

### Hail-specific

| Parameter                   | Description                                                                                   |
| --------------------------- | --------------------------------------------------------------------------------------------- |
| **min\_hail\_in**           | `hailAssessment.best_estimate_in` at or above this size, in inches.                           |
| **min\_reported\_hail\_in** | `hailAssessment.max_reported_in` at or above this size — ground reports only, ignoring radar. |
| **hail\_basis**             | One or more of `report`, `radar`, `radar_brief`, `warning`. See [Hail basis](#hail-basis).    |

### Common

| Parameter                                      | Description                                                             |
| ---------------------------------------------- | ----------------------------------------------------------------------- |
| **uuid**, **type**, **severity**, **category** | As on [`/active-hazards-query`](/hazards/requesting-active-hazards.md). |

\| **country** | ISO 3166 alpha-2 code, alpha-3 code, or country name. The length decides: two characters is matched as an alpha-2 code, three as an alpha-3 code, and four or more as a case-insensitive substring of `location.admin0`. So `US`, `USA`, `United States` and `United States of America` all match the same records, while `US` never matches Australia because short values are only ever compared as codes. Comma-separated list, any of. | | **state** | State as `TX` or `US-TX`. | | **name**, **comment** | Substring match. | | **started\_at**, **created\_at**, **updated\_at** | On or after the given time. | | **ended\_at** | On or before the given time. | | **updated\_since** | Strictly after the given time. The polling parameter. | | **latitude**, **longitude** | `min,max` range, tested against the hazard's own point. | | **scope** | `active` only; see above. |

## Hail basis

`hailAssessment.hail_basis` is never null and says what the hazard rests on, strongest evidence first:

| `hail_basis`     | Meaning                                                                                                                                                                          |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **report**       | At least one ground hail report.                                                                                                                                                 |
| **radar**        | A radar hail signature of 1 inch or more.                                                                                                                                        |
| **warning**      | Only an NWS warning with a hail tag of 1 inch or more.                                                                                                                           |
| **radar\_brief** | Radar-only hail, with no warning and no report, whose 1-inch signature lasted under 10 minutes. Published but labelled, and the hazard's own description says it is unconfirmed. |

Filter on `hail_basis=report` for hazards confirmed from the ground, and exclude `radar_brief` if you only want signatures that persisted.

## The hail record

Standard V2 hazard fields as documented under [Requesting Active Hazards](/hazards/requesting-active-hazards.md#response-fields), with `type` `STORM`, `severity` `WARNING` and `category` `EVENT`. Timestamps are epoch seconds. `latitude`/`longitude` is the radar peak, or the largest report, or a point inside the warning.

### Geometry

**`alertGeometry`** is a GeoJSON FeatureCollection with one Feature per linked NWS warning, at that warning's current polygon, with `properties` null. A hazard with no warning carries one Feature holding the lowest-level observed outline.

**`exposureAreas`** is a GeoJSON FeatureCollection of where hail was actually observed, each Feature carrying `properties.exposureLevel`. It is literally an empty object when nothing has been observed yet, which is the case for a warning-only hazard:

```json
"exposureAreas": {}
```

Not `null`, and not an empty FeatureCollection — so test for an absent `features` array rather than for a null. Warning-only hazards are common: in live history a little over half the hail records and roughly two thirds of the wind records carry `{}` here.

Levels 1 to 6 are the cumulative radar swaths for 1, 1.25, 1.5, 1.75, 2 and 2.5 inches. Rather than hard-coding that scale, read `hailAssessment.exposure_levels`, which maps each level present to its inch threshold. Report-only hail carries a single Feature around the reports, at the level of the largest one.

### `hailAssessment`

The summary block: `hail_event_key`, `max_warning_hail_tag_in`, `max_reported_in`, `max_measured_in` (reports qualified as measured), `mesh_max_swath_in` (largest swath threshold reached), `mesh_size_at_location_in` (the radar peak), `best_estimate_in` with `best_estimate_source` (`report` or `mesh` — whichever is larger), `hail_basis`, `radar_duration_min`, `total_reports`, `total_measured`, `exposure_levels`, `end_basis`, `sources_consulted` (each source with a status of `observed` or `none_observed`), `enhancedAt` and `enhancer`.

### `hailDetails`

The evidence behind the summary: `mesh_swaths` (area and outline per size threshold), `mesh_product`, `radar_timeline` (per radar frame: time, peak size, area per threshold, centroid), `swath_growth` (when each threshold's outline first appeared and how it grew, at 10-minute steps), `hail_reports`, and `warnings` — each linked NWS warning with its VTEC, tags, damage threat, current polygon and every version.

## Lifecycle

A hail hazard stays active until every part of it is finished: its warnings have expired or been cancelled, radar has been quiet for 30 minutes, and hail reports have been quiet for 30 minutes.

While it is active, `endedAt` is a **projection**, `incident.properties.endedAtKind` is `projected`, and `hailAssessment.end_basis` is `null`. When it ends, `endedAt` becomes the last part's end time, `endedAtKind` becomes `observed`, and `end_basis` says why:

| `end_basis`          | Meaning                                                                              |
| -------------------- | ------------------------------------------------------------------------------------ |
| **warning\_expired** | The linked warnings expired or were cancelled.                                       |
| **radar\_quiet**     | No radar hail signature for 30 minutes.                                              |
| **reports\_quiet**   | No hail reports for 30 minutes.                                                      |
| **merged**           | Absorbed into another hazard; `incident.properties.supersededBy` names the survivor. |

The day after, once late reports have arrived, the history record is finalised as a new version. There is no archive of every intermediate version: the active file holds each hazard's current version, and history holds its ended and finalised version.

## Sample

See [Hail Sample](/hazards/hazard-samples/hail-sample.md) for a complete record.
