01 / OVERVIEW
API docs
One base URL, one main route, and a free preview on every dataset. You build the app, dashboard or bot. We supply the weather and storm data.
- Base URL
https://data.truefixr.com - Main route
GET /v1/data, picks the data withdataset= - Coverage US addresses. 10 forecast perils: tornado, hail, wind, flash flood, heavy rain, winter, ice, coastal surge, hurricane, wildfire.
- History back to 2003, 11 peril categories, address level.
- Forecast windows from 24 hours out to 10 days, refreshed 4 times a day.
- Machine-readable openapi.json, llms.txt, x402.json
Storm data here means storms that were reported and radar-detected and matched to street addresses. It is not an inspection and not a damage assessment. Forecasts show what could happen, not what will, and can be wrong. Not affiliated with NOAA or the National Weather Service.
Quickstart, no SDK needed
No library needed, any HTTP client works. The three snippets below make the same two calls: the free menu, then live weather at one point. No key.
curl -s https://data.truefixr.com/v1/data | head -c 400
curl -s "https://data.truefixr.com/v1/data?dataset=weather&lat=32.78&lon=-96.80"import requests # pip install requests
BASE = "https://data.truefixr.com/v1/data"
print(list(requests.get(BASE).json()["datasets"]))
wx = requests.get(BASE, params={"dataset": "weather", "lat": 32.78, "lon": -96.80}).json()
print(wx["temperature_f"], wx["alerts"], wx["billed"])const BASE = "https://data.truefixr.com/v1/data";
console.log(Object.keys((await (await fetch(BASE)).json()).datasets));
const q = new URLSearchParams({ dataset: "weather", lat: 32.78, lon: -96.8 });
const wx = await (await fetch(`${BASE}?${q}`)).json();
console.log(wx.temperature_f, wx.alerts, wx.billed);If it prints a temperature, you are set up. Next: recipes in four languages, or grab the starter kit.
Starter workflow
- Call the menu with no parameters. It lists every dataset, an example call and the price.
- Run the free preview of the dataset you want. Read
estimated_cost_usd(or the line count and price). - Buy a key if you want the full records. Minimum purchase is $25, prepaid, no subscription.
- Add
addresses=trueand theAuthorizationheader to run the paid pull. Start with a smalllimit.
Authentication
Free previews need no key and no header. Paid pulls need your API key as a Bearer token. Keys look like tfx_live_... and are shown once when you buy, so put yours in a password manager or an environment variable right away.
curl -s -G https://data.truefixr.com/v1/data \
-d dataset=hazard_score -d addresses=true \
--data-urlencode "address=891 Lake Hollow Blvd SW, Marietta, GA 30064" \
-H "Authorization: Bearer $GETFIXN_KEY"Wrong or missing key on a paid pull? You get a 402 with the price, not a 401. See Errors.
No account at all: an AI agent can pay per call in USDC on Base with x402. See x402.
Your key and balance
Keys are tied to a prepaid balance. These routes exist in the OpenAPI spec: GET /v1/billing/account (the key goes in the api_key query parameter, so keep that URL out of shared logs), POST /v1/billing/rotate-key with body {"api_key": "..."} to get a new key, and POST /v1/billing/recover with body {"email": "..."} to recover a key. The My key page does the same without code.
Datasets
Choose the data with dataset=NAME. Every dataset has a free preview. Add addresses=true (or details=true for weather) and your key to buy the full pull.
The five products: ML Storm Forecast by Address (dataset=risk), Model-Based Weather by Address (dataset=weather), Model-Based Hourly Forecast by Address (dataset=weather with hours_ahead), Storm History by Address: Reported and Radar-Detected Events Since 2003 (dataset=history) and Past Storm Leads by Address: Reported and Radar-Detected, Last 365 Days (dataset=storms). The first three are model outputs. The last two are recorded events matched to addresses. Forecasts describe what could happen, not what will happen.
| dataset | What it is | Locate it with | Paid price |
|---|---|---|---|
storms | Past Storm Leads by Address: Reported and Radar-Detected, Last 365 Days. | county + state, or lat + lon | $0.05 per address |
risk | ML Storm Forecast by Address: per-peril machine-learning forecasts for 10 perils, 24 hours to 10 days. Each record carries structure replacement value, people, storm type, forecast time and a risk label. The free preview adds a county grade as a teaser. | county + state, or lat + lon | $0.05 per address |
address | One property: its reported and radar-detected events over the last 365 days, with the county forecast label as secondary context. | lat + lon | $0.05 per address |
history | Storm History by Address: Reported and Radar-Detected Events Since 2003, 11 event categories, optional date-of-loss mode. | address or lat + lon | $0.05 per line, $10 minimum per report |
hazard_score | One property summarized by peril: counts, most recent event, years since last. | address or lat + lon | $0.50 per property |
weather | Model-Based Weather by Address: current conditions, rain outlook, severe alerts, free lean response. Add hours_ahead (0 to 48) for Model-Based Hourly Forecast by Address. | address or lat + lon | Free lean. $0.0002 per call with details=true |
facilities | Schools, hospitals and other facilities currently under an active risk window. | county + state (both) | $0.05 per facility |
wildfire | County-level wildfire risk for the coming days, one record per county. Not address-level. | state | $0.05 per county |
at_risk | Schools and businesses at risk, by peril and window. | state, kind, peril | $0.05 per record |
daily | Daily county digest: counts, storm types, dollar exposure. No address records. | rank, limit | Always free |
coverage | Which states and counties have data on file. | state (optional) | Always free |
The free preview of GET /v1/data shows the full menu. Datasets are described live there, and the live response wins if it ever disagrees with this page.
Parameters
All parameters are query parameters on GET /v1/data. Unknown combinations return a 400 whose detail tells you what is missing. The OpenAPI spec also lists months, category, format and counties without further description. Check the free menu before relying on them.
| Parameter | Type | What it does |
|---|---|---|
dataset | string | Which data. See the table above. Omit it to get the free menu. |
county | string | County name, such as Dallas. Send with state. |
state | string | Two-letter state, such as TX. A state alone is a 400 for storms and facilities. |
lat | number | Latitude. Use with lon. |
lon | number | Longitude. Use with lat. |
address | string | Street address. Geocoded for you. Accepted by history, hazard_score and weather. |
addresses | boolean | true runs the paid pull and returns records. Default false, the free preview. |
peril | string | Filter by storm type, such as HAIL. Fewer addresses means a lower price. Use a key from storm_types in the preview. |
days | integer | Look-back window in days for storms (up to 365). |
window | string | Forecast window for risk. Default 24h. Values that returned data when tested: 24h, 48h, 7d, 10d. |
limit | integer | Max records on a paid pull. Default 2000, max 5000. Your spend cap. Also the number of rows for daily. |
radius_mi | number | history and hazard_score: search radius in miles. Default 5, min 1, max 25. |
date_of_loss | YYYY-MM-DD | history: anchor the report on one date. Free preview returns a yes or no (date_of_loss_supported) and a plain answer. |
hours_ahead | integer | weather: 0 to 48. Returns a point forecast. The response says which forecast hour it used. |
details | boolean | weather: true returns the full detail pull. $0.0002 per call, needs a key. |
rank | string | daily: exposure_value_usd, exposure_people, new_leads or unique_addresses. Returns the top counties nationwide, sorted. |
kind | string | at_risk: for example schools. |
min_severity | number | storms: minimum severity. Some storm types carry two units, see below. |
max_severity | number | storms: maximum severity. |
severity_unit | string | Required when severity_by_type shows mixed_units: true. Pick a key under by_unit, such as pct or mph. Without it a mixed-unit filter returns a 400. |
Narrower filters mean fewer addresses and a lower price. Always read the preview first.
Response fields
Everything is JSON. These are real free-preview responses from the live API, trimmed. Numbers change as the data refreshes. The county grade is a free-preview teaser, not a property score. Grade scale: A no or low risk, B moderate, C elevated, D severe, F extreme.
weather (free lean response)
{
"location": { "lat": 32.784859, "lon": -96.802979 },
"generated_at": "2026-10-03T13:00:00+00:00",
"valid_time": "2026-10-03T14:00:00+00:00",
"alerts": [],
"nowcast": { "precip_rate_inhr": 0.051, "raining_now": true, "source": "precipitation nowcast" },
"wind_gust_mph": 13.7615, "precip_in": 0.0209, "dewpoint_f": 69.9195, "temperature_f": 72.4259,
"wind_speed_mph": 6.77, "wind_direction_deg": 14.1, "humidity_pct": 91.8,
"precip_type": "rain", "pressure_mb": 999.5, "visibility_mi": 8.3885,
"dataset": "weather", "billed": false
}risk (free preview)
{
"dataset": "risk", "county": "Dallas", "state": "TX", "window": "24h",
"grade": "B", "grade_label": "Moderate risk",
"total_leads": 660,
"storm_types": { "HEAVY_RAIN": 501, "FLASH_FLOOD": 386 },
"generated": "2026-10-03T09:27:00.496555Z",
"data_age_hours": 5.8,
"estimated_cost_usd": 33.0
}total_leads is the number of address-level forecast records in that window. estimated_cost_usd is the price of the paid pull at your current filters. Check data_age_hours: forecasts refresh 4 times a day.
risk (paid record, trimmed)
{
"county": "Dallas", "state": "TX", "window": "24h", "returned": 1,
"value_basis": "Replacement cost of structure (not market value)",
"leads": [{
"structure_value": 300882, "people": 3.5,
"full_address": "405 Evergreen Trail, Cedar Hill, TX 75104",
"storm_type": "HEAVY_RAIN", "forecast_time": "2026-10-04T12:27:00Z",
"risk_label": "Extreme", "storm_hits": 2
}],
"reference_id": "TFX-202610-6A3B8262"
}structure_value is replacement cost (what it costs to rebuild), not market value. people is the estimated occupancy of the address. The risk label is a word tier. Forecasts describe what could happen, not what will happen.
address (free preview)
{
"dataset": "address", "county": "dallas", "state": "TX",
"matched_by": "lat/lon (~150m radius)",
"storm_event_count": 297,
"storm_types": { "HEAVY_RAIN": 297 },
"current_forecast_risk": { "grade": "B", "grade_label": "Moderate risk" },
"severity_by_type": { "HEAVY_RAIN": { "min": 1.04, "max": 1.04, "unit": "in", "with_severity": 297 } }
}history (free preview, with date of loss)
{
"dataset": "history",
"geocoded_address": "891 Lake Hollow Blvd SW, Marietta, GA 30064, USA",
"radius_mi": 5.0,
"real_line_count": 362,
"estimated_cost_usd": 18.1,
"by_peril": { "hail": 65, "wind": 123, "flood": 10, "lightning": 7, "tornado": 2, "hurricane": 19,
"winter": 67, "extreme_temp": 24, "drought": 40, "wildfire": 1, "coastal": 0 },
"date_of_loss": "2026-04-14",
"date_of_loss_supported": false,
"answer": "No severe-weather event is on file within 5.0 miles of this address on 2026-04-14."
}daily (free, ranked)
{
"dataset": "daily", "generated": "2026-10-03T09:34:36Z", "ranked_by": "exposure_value_usd", "returned": 2,
"counties": [
{ "state": "TX", "county": "Harris", "new_leads": 2073075, "unique_addresses": 1680254,
"exposure_value_usd": 523921470966, "exposure_people": 3490900,
"storms": [ { "type": "HAIL", "count": 112748 } ], "has_hot": true }
]
} // trimmed to one countyPaid pulls (addresses=true) return the matching records as a list in the response. The record fields differ by dataset (for example facilities return name, category, city, state, coordinates and risk label). Make one small paid call with a low limit and inspect the shape before you write a parser. Paid record shapes were not exercised for these docs.
Storm types and units. storm_types counts are per event, not per address, so they can add up to more than total_leads. Some storm types report severity in more than one unit. severity_by_type on a free preview tells you; if it shows mixed_units: true, send severity_unit=.
Batch routes
Two POST routes take up to 500 locations per call. You send your own list each time and it is never stored. They have no free preview, so they need a key (or an x402 payment) from the first call.
| Route | Does | Price |
|---|---|---|
POST /v1/weather/batch | Current conditions and active severe alerts for each location. | $0.0002 per location |
POST /v1/portfolio/risk | County forecast status for each location (county-level, not address-level). Optional "window". | $0.05 per location |
curl -X POST https://data.truefixr.com/v1/portfolio/risk \
-H "Authorization: Bearer $GETFIXN_KEY" -H "Content-Type: application/json" \
-d '{"locations":[{"lat":30.27,"lon":-97.74,"label":"Austin office"}],"window":"24h"}'Response shapes come from the API's own x402 manifest and docs: /v1/portfolio/risk returns results with lat, lon, county, grade per location. /v1/weather/batch returns results with current and alerts. Paid calls were not run for these docs, so verify with one location first. Bigger lists: split into chunks of 500.
Errors and limits
| Code | Meaning | What to do |
|---|---|---|
| 400 | A required parameter is missing or does not fit the dataset. | Read the detail text. It names what is missing. |
| 402 | Payment required: a paid pull with no valid key or balance, or an unpaid x402 route. | Add a Bearer key, top up, or pay with x402. The body states the price in accepts[0].amount. |
| 422 | A parameter has the wrong type, such as text where a number belongs. | Fix the value named in loc. |
| 429 | Too many free previews (60 per minute per IP). | Wait a minute. Space out calls, or use a key. |
402 payment required
This is what a paid route returns when there is no valid key or payment. It tells you the price. Nothing is charged.
{
"x402Version": 2,
"error": "Payment required",
"resource": { "url": "https://data.truefixr.com/v1/weather/batch", "description": "...", "mimeType": "application/json" },
"accepts": [{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x8335...",
"amount": "200",
"payTo": "0xFf23cfFf46535E076e88835CD0Bbad8D1033E255",
"maxTimeoutSeconds": 300,
"extra": { "name": "USD Coin", "version": "2" }
}],
"extensions": { "bazaar": { /* ... */ } }
}The price of the call is accepts[0].amount in atomic USDC (6 decimals), so 200 means $0.0002 (price in USD = amount / 1,000,000). The same object is also sent in the PAYMENT-REQUIRED response header as base64 JSON. The old for_ai_agents and price_usd fields are gone. Handle 402 by stopping and asking the user to top up, never by retrying in a loop.
400 and 422
// GET /v1/data?dataset=weather
{ "detail": "dataset=weather needs address, or lat+lon" }
// lat=abc
{ "detail": [ { "type": "float_parsing", "loc": ["query", "lat"], "msg": "Input should be a valid number, unable to parse string as a number" } ] }Practical limits
- Free previews: 60 requests per minute per IP (429 beyond that).
- Batch routes: 500 locations per call.
- Paid pulls: 2,000 records by default, up to 5,000 with
limit. There is no cursor in the API. Split big jobs by county, peril or days. - History radius: 1 to 25 miles.
- Observed: some default HTTP clients (for example Python's built-in
urllibwith its stock User-Agent) were blocked with a 403.requests,fetchand curl worked. If you hit a 403, set your ownUser-Agentheader.
Pricing
Prepaid balance, pay as you go. Minimum purchase is $25 (presets 25, 50, 100, 250, 500 or a custom amount). No subscription, no contract. Calls come out of your balance. Free previews cost nothing and show the price first.
| What you get | Price | Free preview |
|---|---|---|
| Past Storm Leads by Address (reported and radar-detected storms matched to addresses) | $0.05 per address | Counts, storm types, repeat-hit addresses, exact cost |
| Storm History by Address, 2003 to present | $0.05 per line, $10 minimum per report | Line count by peril and exact price; date-of-loss yes or no |
| ML Storm Forecast by Address (10 perils, 24 hours to 10 days) | $0.05 per address | County grade (teaser), storm types, per-peril counts, exact cost |
| Hazard score | $0.50 per query | Event counts per peril |
| County forecast status, batch (up to 500 locations) | $0.05 per location | No preview on the batch route |
| Model-Based Weather by Address, full data (details=true) | $0.0002 per call | Free lean response |
| Model-Based Hourly Forecast by Address (hours_ahead 0 to 48) | $0.0002 per call | Free lean response |
| Facilities, at-risk records, wildfire counties | $0.05 per record | Counts only |
| Daily county digest, coverage, the menu | Free | Always free |
Optional auto top-up (off unless you tick it): charges the saved card the same amount when your balance drops below $5, at most once every 20 hours. See Pricing and Buy API key.
Prices are the live ones from the menu on /v1/data. A paid history report is $10 minimum however few lines it has.
MCP setup
MCP lets AI assistants such as Claude and Cursor call outside tools. Point the client at one URL and the assistant can look up storm data. Free previews work without a key.
Server URL: https://mcp.atlasunited.io/mcp. It was checked live with a tools/list call and exposes six tools: get_weather_data, get_storm_history, get_risk_forecast, get_property_storm_history_report, get_current_weather and get_address_report.
Claude Desktop
Easiest: in Settings, add a custom connector with the URL above. Or edit claude_desktop_config.json (the mcp-remote bridge is a common pattern for remote servers):
{
"mcpServers": {
"getfixn-storm-data": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.atlasunited.io/mcp"]
}
}
}Cursor
Add this to ~/.cursor/mcp.json (or the project's .cursor/mcp.json):
{
"mcpServers": {
"getfixn-storm-data": {
"url": "https://mcp.atlasunited.io/mcp"
}
}
}Check it by hand
curl -s -X POST https://mcp.atlasunited.io/mcp \
-H "content-type: application/json" \
-H "accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'The server URL and tool list are verified. The client config snippets follow each client's standard pattern for remote MCP servers and were not run inside those apps for this page. If a client changes its format, use its own docs for the URL field.
x402: pay per call, no account
x402 lets a bot or AI agent pay for a call in USDC on Base with no signup and no key. The server answers 402 with a price, the agent signs a payment from its own wallet, retries, and gets the data. Settlement is on chain. Per the API's notes, the first payment settles immediately and later small calls accrue to a $1.00 tab.
curl -i -X POST https://data.truefixr.com/v1/weather/batch \
-H "content-type: application/json" \
-d '{"locations":[{"lat":32.78,"lon":-96.80}]}'- Discover. Read /.well-known/x402.json: payable routes, network
eip155:8453, asset USDC, pay-to address. - Ask. Call a paid route. You get HTTP 402 and a base64
payment-requiredheader with the exact amount. - Pay. Sign an x402
exactpayment from your wallet and retry the same request with it. - Receive. HTTP 200 and the data.
Payable routes listed in the manifest: GET /v1/data?dataset=weather&details=true, POST /v1/weather/batch, POST /v1/portfolio/risk. A standard x402 client does steps 2 to 4 for you. Python (needs pip install "x402[httpx,evm]" eth-account):
import asyncio, os
from eth_account import Account
from x402 import x402Client
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact import register_exact_evm_client
URL = "https://data.truefixr.com/v1/weather/batch"
BODY = {"locations": [{"lat": 32.78, "lon": -96.80}]}
async def main():
acct = Account.from_key(os.environ["EVM_PRIVATE_KEY"]) # a small, separate wallet
client = x402Client()
register_exact_evm_client(client, EthAccountSigner(acct))
async with x402HttpxClient(client) as http:
r = await http.post(URL, json=BODY) # 402, pay, retry: all inside
await r.aread()
print(r.status_code, r.text[:300])
asyncio.run(main())GetFixn sells data, not trading advice. Nothing here is investment advice. Forecasts can be wrong. You are responsible for your own strategies and for following the rules of any exchange or market you use.
Prediction-market bots and paying agents
Two common setups. Both only fetch data. Neither places an order.
- Prediction-market bot (Kalshi-style weather contracts). Fetch live weather,
hours_aheadforecasts and county forecast grades for the cities you trade, write them to a file and let your own model read it. Working code in four languages: recipe 12. The free tier covers it. - Agent with a wallet. Skip the key and pay per call in USDC on Base with x402. See x402 below and recipe 13.
GetFixn sells data, not trading advice. Nothing here is investment advice. Forecasts can be wrong. You are responsible for your own strategies and for following the rules of any exchange or market you use. No exchange endorses or partners with GetFixn. Heavy or commercial volume? Email admin@truefixr.com.
Caching and good habits
- Preview first. Every paid pull has a free preview with the exact price. Read it in code and stop if it is higher than you expect.
- Cap spend with limit.
limit=25on a paid pull is a hard ceiling on records. - Cache by full URL. Forecasts refresh 4 times a day, live weather hourly. Minutes for weather, an hour or more for forecasts, a day for history.
- Throttle loops. One call per second keeps free previews under 60 a minute.
- Retry politely. Back off on 429 and 5xx. Never retry a 402.
- Label it honestly. In your own UI call it "reported and radar-detected storms" and "forecast risk, what could happen", never as damage assessments.
Working code for each of these: errors and spend caps, caching, rate limiting.
Changelog
- GetFixn launched. Buy a key from $50, examples, starter kit and docs for builders.
Storm data means reported and radar-detected storms matched to street addresses, not an inspection or damage assessment. Forecasts show what could happen, not what will, and can be wrong. Not affiliated with NOAA or the National Weather Service. GetFixn sells data, not trading advice. Nothing here is investment advice.