RESEARCH DATA & API

Truth Observatory collects public scientific data streams, stores them unchanged with a hash of every record, and serves measured series back out for analysis. This page explains how to get the data, what each field means, what the data cannot tell you, and how to verify and cite it.

Last updated: October 21, 2026 · API version 1

1. WHO CAN ACCESS WHAT

The measured series, discrete events, anchor receipts and feed status are free and need no account or key. The raw per-feed archives and the correlation output need a subscription, because they are what pays for collection and storage.

DATAACCESSENDPOINT
Measured time series (Kp, Dst, solar wind, magnetometers, grid demand, …)FREE/api/signals/<id>
Discrete events (earthquakes, flares, wildfire starts, volcano alerts)FREE/api/signals/events/<kind>
Feed status and collection healthFREE/api/feeds
Hourly hash anchor receiptsFREE/api/anchors
5G coverage (carrier-reported, FCC)FREE/api/coverage
Sealed daily raw archives (every record each collector wrote)SUBSCRIBER/api/archive/<feed>/<day>
Recent raw records per feedSUBSCRIBER/api/feed/<feed>
Cross-feed correlationsSUBSCRIBER/api/correlations

Working on a funded or academic project that needs bulk raw archives? Email team@dwsc.io with a short description.

2. QUICK START

BROWSER OR SPREADSHEET

Paste a URL with format=csv to download a table. For example, the last 30 days of the planetary Kp index:

https://observatory.tlid.io/api/signals/kp?from=2026-09-21&format=csv

PYTHON (PANDAS)

import pandas as pd

base = "https://observatory.tlid.io/api/signals"
kp = pd.read_csv(f"{base}/kp?from=2025-01-01&to=2025-12-31&format=csv", parse_dates=["key"])

# Events are paged: follow `next` until it is null
import requests
url, quakes = f"{base}/events/quake?from=2025-01-01&minmag=5", []
while url:
    page = requests.get(url if url.startswith("http") else "https://observatory.tlid.io" + url).json()
    quakes += page["events"]
    url = page["next"]

R

kp <- read.csv("https://observatory.tlid.io/api/signals/kp?from=2025-01-01&format=csv")

CURL

curl -s "https://observatory.tlid.io/api/signals" | jq '.series | keys'

3. ENDPOINTS

All times are UTC, ISO 8601. All responses are JSON unless format=csv is given. CORS is open, so the API can be called from notebooks and browser tools.

GET /api/signals

The catalog: every series and event kind with its unit, time resolution, source, start year and the date range actually held (coverage.first / coverage.last). Also lists knownLinks, the pairs of series with an established physical link.

GET /api/signals/<id>

PARAMETERDEFAULTMEANING
from7 days before toStart, ISO date or datetime (inclusive)
tonowEnd, ISO date or datetime (inclusive)
formatjsoncsv for a table with header key,mean,min,max,n

Each row is [key, mean, min, max, n]. key is the start of the time bin (YYYY-MM-DDTHH for hourly and 3-hourly series, YYYY-MM-DD for daily). n is how many source readings fell in that bin. The catalog field stat says which of mean, min or max is the standard summary for that quantity (for example min for Dst, because storms make it more negative).

GET /api/signals/events/<kind>

PARAMETERDEFAULTMEANING
from, tolast 30 daysTime window (max 732 days per request)
minmagnoneMinimum magnitude, where the event has one
limit20000Page size, 1 to 20000
offset0Index of the first event to return
formatjsoncsv for a table (one column per field; id and t first)

GET /api/feeds

Status of every collector. See feed status for what each value means.

GET /api/anchors?limit=48

The most recent hourly hash receipts (up to 500). See verify.

GET /api/coverage?carrier=&tier=&bbox=&zoom=

Carrier-reported 5G coverage as H3 hexagons with the share of each hexagon claimed. carrier is tmobile, att or verizon; tier is 7 (7/1 Mbps) or 35 (35/3 Mbps); bbox is south,west,north,east. Larger views return coarser hexagons; the response says which H3 resolution (res) was used.

4. SERIES CATALOG (LIVE)

Loaded from /api/signals when you open this page. The held column is what the archive contains right now, not just the source's start year.

Loading catalog…

5. LIMITS AND HONESTY FLAGS

No response is ever shortened without telling you.

6. WHAT FEED STATUS MEANS

STATUSMEANING
live with sources: "ok"The collector ran on schedule and its recent pulls returned data.
live with sources: "partial"The collector is running and some upstream sources answered, but at least one recent pull failed. Data is real but may be incomplete.
failingThe collector is running, but every recent pull from the upstream source failed (for example HTTP 403/404, or a facility that has closed). lastGood says when real data last arrived.
staleThe collector has written nothing for more than 3 times its normal interval.
offlineNo records at all.

Each record a collector writes is either an observation or a DATA-GAP entry with the reason the source failed. Gap entries are kept and hashed like everything else, so the record of outages is as verifiable as the data.

7. METHODS AND LIMITATIONS

COLLECTION

Each stream is fetched from its official public source on a fixed schedule (from 5 minutes to daily, depending on how often the source updates). Responses are recorded as received with a retrieval timestamp. Measured series are extracted into hourly, 3-hourly or daily bins keeping mean, min, max and reading count. History before live collection began comes from the long-term archives named in the catalog (GFZ Potsdam, NASA OMNI, USGS ComCat).

DERIVED NUMBERS — READ BEFORE USING

WHAT IS NOT BUILT

There is no anomaly catalog and no editorial interpretation layer. The Observatory records and serves data; it does not claim causes.

8. VERIFY THE DATA

Every record each collector writes is hashed. Once an hour the new records are folded into a Merkle root, and the top root is written to the TrustLayer chain. Anyone can check that an archive file has not changed since that hour.

  1. Download a feed's sealed archive for a day: /api/archive/<feed>/<YYYY-MM-DD> (subscriber). Split it into lines, without the trailing newline.
  2. Get the receipts from /api/anchors?limit=500. They come in pairs per UTC hour: an ANCHOR record with the roots, and an ANCHOR-RESULT record with the chain txHash for the same root.
  3. In the ANCHOR record, feeds.<stem> gives day, lineFrom, lineTo (0-based, inclusive) and that feed's root. Take those lines, compute leaf = sha256(line) on the exact UTF-8 bytes, and fold pairwise with parent = sha256(leftHex + rightHex), concatenating the lowercase hex strings. An odd node is paired with itself. The result must equal the feed's root.
  4. Top root: compute sha256("<stem>:<feedRoot>") for every feed in the record, sort those hashes, and fold them the same way. The result must equal the record's root.
  5. Look up the matching ANCHOR-RESULT's txHash at https://chain.tlid.io/api/hash/<txHash>. Its dataHash must equal that root.
# obs-merkle-v1 in Python
import hashlib
h = lambda s: hashlib.sha256(s.encode()).hexdigest()
def root(leaves):
    if not leaves: return ""
    while len(leaves) > 1:
        leaves = [h(leaves[i] + (leaves[i+1] if i+1 < len(leaves) else leaves[i]))
                  for i in range(0, len(leaves), 2)]
    return leaves[0]
feed_root = root([h(line) for line in lines_in_range])

Receipts name feeds by their manifest stem, which can differ from the feed id used in the archive URL (for example the geomag feed is geomagnetic and earthquake is seismic in receipts). Each feed's stem is listed in /api/feeds as stem. The measured series in /api/signals are derived from those records; verifying a series value means checking the archive records it came from.

9. HOW TO CITE

Please cite both the Observatory and the original source of the data you used (listed per series in the catalog). Include the date you downloaded the data, because live series keep growing.

DarkWave Studios LLC (2026). Truth Observatory: archived public geophysical, space-weather and infrastructure data streams [Data set]. https://observatory.tlid.io. Accessed YYYY-MM-DD.
@misc{truth_observatory_2026,
  author       = {{DarkWave Studios LLC}},
  title        = {Truth Observatory: archived public geophysical, space-weather and infrastructure data streams},
  year         = {2026},
  howpublished = {\url{https://observatory.tlid.io}},
  note         = {Data set. Accessed YYYY-MM-DD}
}

Upstream sources ask for these citations:

10. LICENSE

The Observatory's own compilation (the binned series, catalog, status records and anchor receipts) is released under Creative Commons Attribution 4.0 (CC BY 4.0). You may use, share and adapt it, including commercially, if you credit Truth Observatory as shown above.

The underlying measurements keep their original terms, which take precedence:

SOURCETERMS
NOAA, NWS, SWPC, USGS, NASA, NIFC, EIA, FCCUS government works, public domain in the United States
GFZ Potsdam (Kp, F10.7)CC BY 4.0
SILSO sunspot numberCC BY-NC 4.0 (non-commercial)
OpenCelliD cell sitesCC BY-SA 4.0
Blitzortung.org lightningNon-commercial use only; not redistributed through this API
OpenSky Network aircraftResearch and non-commercial use; not redistributed through this API

Data is provided as is, without warranty. It is not a substitute for official warnings. For life-safety decisions use the National Weather Service and local authorities. See also the terms of service.

11. CHANGES AND DATA-QUALITY NOTES

Found a problem in the data? Email team@dwsc.io with the series, time range and what you expected. Corrections are logged here.