Developers · API v1.0

Trends data,as JSON.

Every number on this site comes from these endpoints. Free, keyless and read-only, with CORS open for GET. Machine-readable spec: /openapi.json.

Envelope

Every GET returns the same envelope. Older fields stay at the top level so existing clients keep working; new clients should read data.

okbooleantrue on success, false on error
versionstringAPI version, currently "1.0". On /api/radar the scoring model version is in model_version.
generated_atstring (ISO 8601 UTC)when this response was generated
dataobject | nullthe full payload. The same fields are also repeated at the top level for backward compatibility.
errorstringhuman-readable error message (errors only)
error_codestringunsupported_geo, bad_phase, missing_term, method_not_allowed, warming_up, upstream_unavailable (errors only)

Errors, caching and limits

  • Errors use HTTP 400 (bad parameter), 405 (wrong method) or 503 (warming up, or a source failed), with ok:false, error and error_code.
  • Responses are cached at the edge (see each endpoint). Data refreshes about every 30 minutes, so polling more than every 5 minutes returns the same data.
  • CORS: Access-Control-Allow-Origin: * on GET and OPTIONS.
  • Times are ISO 8601 in UTC; history arrays use epoch milliseconds.
  • Fields are only ever added, never renamed or removed, within API version 1.x.
  • Please credit “NYPTID Trends” with a link to trends.nyptid.com. Trend data originates from Google Trends' public feed; we are not affiliated with Google.
GET

/api/radar

Trend Radar: scored candidates, calls ledger, control picks and record. Cache: 5 min CDN.

curl "https://trends.nyptid.com/api/radar"

Parameters

No parameters.

Fields

model_versionscoring model, e.g. "radar-1.2 (...)"
cycles, since, geosTracked, termsLive, noSignal, warmingmodel state; warming is true below 6 snapshots
weightsfeature weights, sum 1
candidates[]{k, term, score 0-100, confidence low|medium|high, measured 0-1, features{name: 0-1}, unknown[], why[], geos[], maxLabel, firstSeen, observations, news}
calls[], model_calls[], control_picks[]{id, model, term, made_at, score, confidence, geos, why, group model|control, status pending|hit|miss, graded_at, outcome}
record{model:{calls, hit, miss, pending, hitRate}, control:{...}}
ledgersame as record (legacy name)
healthsource status, same as /api/sources?health=1
GET

/api/sources

Every source we have for one term, or the health of every source. Cache: 5 min CDN (health 2 min).

curl "https://trends.nyptid.com/api/sources?term=roma"
curl "https://trends.nyptid.com/api/sources?health=1"

Parameters

termthe trend text or its key
health1: return live status of every source instead

Fields

foundfalse if we have no lookups for this term yet
summarycounts, as on trend items
outlets{platform: [outlet names]}
groups{platform: {outlet: [{title, url, at, geo, author, engagement, views}]}}
wikiWikipedia article daily pageviews and spike ratio
gdelt[[hour_ms, articles]] GDELT volume, 3 days
social, socialTimeline, socialVelocitySocial Fetch per-platform results, history and pace
timeline[[ms, articles, outlets]] per snapshot
health{source: {ok true|false|null, note, error}}. socialFetch also has state (live, "paused: daily cap", "paused: low balance"), cap, usedToday, balance and platforms{}
GET

/api/evergreen

Terms that persist across many snapshots, days and countries. Cache: 10 min CDN.

curl "https://trends.nyptid.com/api/evergreen"

Parameters

No parameters.

Fields

criteriathe exact rules used
historyDays, enoughHistory, notehonest status while history is shorter than 7 days
evergreen[]{key, title, firstSeen, lastSeen, spanDays, daysSeen, snapshotsSeen, countriesEver, maxCountriesAtOnce, liveNow, countries[]}
emerging[]same shape: terms seen on 2+ days in 2+ countries
termsTrackedhow many terms are in history