> ## Documentation Index
> Fetch the complete documentation index at: https://docs.exorde.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Trending

> Top terms driving conversation on a topic or watchlist, ranked by rolling z-score with a 24-hour delta. The state of the conversation in one call.

The `trending` endpoint returns the **top terms** driving conversation on a topic or watchlist right now, ranked by a rolling z-score against a 14-day baseline. It is the fastest way to answer "what is everyone actually talking about" in one call, and it is available on every tier — including the free Watch trial.

Trending answers a different question from [Alerts](/alerts) and [Narrative](/narrative):

| Surface                 | Question                                   | Shape                                       |
| ----------------------- | ------------------------------------------ | ------------------------------------------- |
| **Trending**            | "Which words are spiking?"                 | Ranked list of terms with z-scores          |
| [Narrative](/narrative) | "What is the story those words form?"      | Editorial summary + sub-narrative weights   |
| [Alerts](/alerts)       | "What just happened that needs attention?" | Discrete events with severity, spread, IOCs |

Use trending as the **state** view — a tile on a dashboard, a feed in a wallboard, a row in an exec digest. Use alerts when you need a push-shaped, machine-routable event.

***

## The endpoints

| Endpoint                           | Tier   | Returns                                      |
| ---------------------------------- | ------ | -------------------------------------------- |
| `GET /v1/topics/{topic}/trending`  | Watch+ | Top terms on a curated topic                 |
| `GET /v1/watchlists/{id}/trending` | See+   | Top terms inside your watchlist's term scope |

Both return the **same JSON shape**. Code written for one works on the other — the only difference is the scope identifier in the response (`topic` vs. `watchlist_id`).

***

## The response envelope

```json theme={null}
{
  "topic": "global",
  "snapshot_id": "2026-05-19T13:00:00Z",
  "terms": [
    { "term": "Iran",       "score": 847.2, "rank": 1, "delta_24h": 6.6,  "post_count": 12480 },
    { "term": "Eurovision", "score": 412.0, "rank": 2, "delta_24h": 1.8,  "post_count":  6210 },
    { "term": "ECB",        "score": 289.4, "rank": 3, "delta_24h": 0.9,  "post_count":  4055 },
    { "term": "Bitcoin",    "score": 211.7, "rank": 4, "delta_24h": -0.3, "post_count":  3142 }
  ],
  "count": 50,
  "data_freshness": { "snapshot_age_seconds": 312, "level": "ok" },
  "query_window": { "hours": 24, "effective_hours": 24 }
}
```

### Field guide

| Field                                 | Type         | Meaning                                                                  |
| ------------------------------------- | ------------ | ------------------------------------------------------------------------ |
| `topic` / `watchlist_id`              | string       | Scope identifier — exactly one is present                                |
| `snapshot_id`                         | ISO-8601 UTC | Pipeline run that produced this response. Pin to it for reproducibility. |
| `terms[]`                             | array        | Ranked term list, length capped per tier (see below)                     |
| `terms[].term`                        | string       | Surface form, lowercased, deduped against synonyms                       |
| `terms[].score`                       | float        | Rolling z-score against 14-day baseline. Higher = more anomalous         |
| `terms[].rank`                        | int          | 1-indexed position in this snapshot                                      |
| `terms[].delta_24h`                   | float        | Score change vs. same window 24h ago. Positive = accelerating            |
| `terms[].post_count`                  | int          | Raw posts mentioning the term in the window                              |
| `count`                               | int          | Total terms returned (≤ tier cap)                                        |
| `data_freshness.snapshot_age_seconds` | int          | Seconds since pipeline produced this snapshot                            |
| `data_freshness.level`                | enum         | `ok`, `degraded`, `stale` — UI traffic light                             |
| `query_window.hours`                  | int          | What you asked for                                                       |
| `query_window.effective_hours`        | int          | What you got after tier clamping                                         |

`score` is **not** comparable across topics — `global` and `cyber` have different baselines. `delta_24h` is comparable across snapshots within the same topic.

***

## Query parameters

| Param           | Default | Watch cap | See cap | Know cap | Notes                                                                                               |
| --------------- | ------- | --------- | ------- | -------- | --------------------------------------------------------------------------------------------------- |
| `hours`         | 24      | 24        | 72      | 168      | Rolling window length. Above-cap requests are silently clamped — see `query_window.effective_hours` |
| `limit`         | 50      | 20        | 100     | 500      | Hard ceiling on returned terms                                                                      |
| `min_score`     | —       | —         | —       | —        | Filter out terms below this z-score                                                                 |
| `exclude_terms` | —       | —         | —       | —        | Comma-separated list to suppress (e.g. brand stopwords)                                             |

A request for `limit=10000&hours=720` on a Watch key returns at most 20 terms over 24h, with `query_window.effective_hours: 24` so your UI knows what it actually got.

***

## Calling it

<CodeGroup>
  ```bash curl theme={null}
  curl "https://intel-v1.exorde.io/v1/topics/global/trending?limit=10" \
    -H "X-API-Key: $EXORDE_API_KEY"
  ```

  ```python Python theme={null}
  import os, httpx

  r = httpx.get(
      "https://intel-v1.exorde.io/v1/topics/global/trending",
      params={"limit": 10},
      headers={"X-API-Key": os.environ["EXORDE_API_KEY"]},
      timeout=10,
  ).json()

  print(f"snapshot {r['snapshot_id']}  age={r['data_freshness']['snapshot_age_seconds']}s")
  for t in r["terms"]:
      print(f"{t['rank']:>2}. {t['term']:<25} z={t['score']:>7.1f}  Δ24h={t['delta_24h']:+.1f}")
  ```

  ```javascript Node theme={null}
  const r = await fetch(
    "https://intel-v1.exorde.io/v1/topics/global/trending?limit=10",
    { headers: { "X-API-Key": process.env.EXORDE_API_KEY } }
  ).then(r => r.json());

  r.terms.forEach(t =>
    console.log(`${t.rank}. ${t.term}  z=${t.score.toFixed(1)}  Δ24h=${t.delta_24h}`)
  );
  ```

  ```powershell PowerShell theme={null}
  $r = Invoke-RestMethod `
    -Uri "https://intel-v1.exorde.io/v1/topics/global/trending?limit=10" `
    -Headers @{ "X-API-Key" = $env:EXORDE_API_KEY }

  $r.terms | Select-Object rank, term, score, delta_24h | Format-Table
  ```
</CodeGroup>

***

## Reading the score

`score` is a **rolling z-score** — how many standard deviations above the 14-day baseline this term's volume sits. Rough guidance:

| Score range | Interpretation                                                   |
| ----------- | ---------------------------------------------------------------- |
| `< 50`      | Background noise on a high-volume topic                          |
| `50 – 200`  | Normal trending — recurring storyline, scheduled event           |
| `200 – 500` | Genuinely elevated — a real story is forming                     |
| `> 500`     | Loud — the term is dominating the snapshot                       |
| `> 1000`    | Rare. Usually maps to a major breaking story or coordinated push |

Combine `score` with `delta_24h` to distinguish **accelerating** from **decaying** stories:

* High `score` + high `delta_24h` → story breaking now
* High `score` + low or negative `delta_24h` → story peaked, decaying
* Low `score` + high `delta_24h` → emerging, worth watching

***

## Trending on a watchlist

Same shape, scoped to your watchlist's terms. Useful when the top terms inside your brand or threat scope diverge from the topic baseline.

```bash theme={null}
curl https://intel-v1.exorde.io/v1/watchlists/wl_01HXYZ.../trending \
  -H "X-API-Key: $EXORDE_API_KEY"
```

```json theme={null}
{
  "watchlist_id": "wl_01HXYZ7DKMSV2X9WJEQ5RQ4N3F",
  "name": "acme-monitoring",
  "snapshot_id": "2026-05-19T13:00:00Z",
  "terms": [
    { "term": "acme",     "score": 142.3, "rank": 1, "delta_24h":  0.4, "post_count": 1820 },
    { "term": "ceo",      "score":  87.1, "rank": 2, "delta_24h":  1.2, "post_count":  920 },
    { "term": "earnings", "score":  61.8, "rank": 3, "delta_24h":  3.7, "post_count":  610 }
  ],
  "data_freshness": { "snapshot_age_seconds": 312, "level": "ok" }
}
```

`earnings` accelerating fast (`delta_24h: 3.7`) on a brand watchlist is the kind of signal a comms team wants to see before the quarterly press cycle. See [Topics and watchlists](/topics-and-watchlists#custom-watchlists) for watchlist setup.

***

## Cadence and freshness

Snapshots refresh every few minutes. Polling faster than the snapshot cadence returns the same payload — burns RPM for nothing.

| Use case            | Tier  | Cadence     | Daily call cost |
| ------------------- | ----- | ----------- | --------------- |
| Dashboard tile      | Watch | every 5 min | \~290 / day     |
| Live wallboard      | See   | every 60s   | \~1,440 / day   |
| Real-time exec view | Know  | every 15s   | \~5,760 / day   |

Below 15-second freshness on trending you're chasing snapshot publication latency, not the data — there's nothing newer to fetch. For sub-second event delivery, use [Alerts via webhook](/alerts#webhook-delivery-see-and-know).

Always read `X-RateLimit-Remaining` and back off when it drops below 20% of `X-RateLimit-Limit`. Full pattern: [Rate limits](/rate-limits).

***

## Common patterns

### Filter out predictable churn

Some terms appear permanently elevated on certain topics (`bitcoin` on finance, `russia` on disinfo). Mute them client-side or with `exclude_terms`:

```python theme={null}
EXCLUDE = {"bitcoin", "ethereum", "russia"}
fresh = [t for t in r["terms"] if t["term"].lower() not in EXCLUDE]
```

### Track new entrants

Compare consecutive snapshots and surface terms that just appeared in the top N:

```python theme={null}
prev_terms = {t["term"] for t in prev_snapshot["terms"][:25]}
new_entrants = [t for t in current["terms"][:25] if t["term"] not in prev_terms]
```

A term that wasn't in the top 25 an hour ago and now sits at rank 7 is usually worth a look.

### Cross-topic comparison

Pull trending on `global`, `cyber`, `finance`, `disinfo` in parallel for a one-page situational view. Score is not comparable across topics, but presence and rank are. See [Use cases recipe 5](/use-cases#5-executive-dashboard-single-pane-situational-awareness).

***

## Snapshots and reproducibility

Every response carries `snapshot_id`. Pin to a snapshot when you need to reproduce an analysis or align trending with a specific narrative or alert state. Snapshots are retained for the same window your tier allows on history depth (see [Tiers — history depth caps](/tiers#history-depth-caps)).

```bash theme={null}
# Pin a query to the snapshot the alert was emitted under
curl "https://intel-v1.exorde.io/v1/topics/global/trending?snapshot_id=2026-05-19T13:00:00Z" \
  -H "X-API-Key: $EXORDE_API_KEY"
```

A `410 snapshot_expired` envelope means the snapshot rolled out of retention — refetch with `latest`. See [Errors](/errors#resource-errors).

***

## Operational guidance

* **Don't compare `score` across topics.** Different baselines, different volume regimes. `rank` and `delta_24h` are the cross-topic-safe fields.
* **Cache by `snapshot_id`.** Same `snapshot_id` = same payload. Re-fetch only when you suspect a new snapshot exists (every few minutes).
* **Pair trending with [narrative](/narrative)** on dashboards: the term list is the spike, the narrative is the story. One without the other under-delivers.
* **For watchlists, expect lower scores.** A watchlist filters the universe — the top term in your brand scope may have a `score` of 80 while `global` has terms above 800. The math is the same; the volume is smaller.
* **Trending counts against RPM** like any other call. Don't poll under the snapshot cadence.

***

## What's not trending

| You want                         | Use this                                                                                |
| -------------------------------- | --------------------------------------------------------------------------------------- |
| "Volume of X over the last week" | [`/v1/topics/{t}/volume`](/topics-and-watchlists#analytics-endpoints-on-curated-topics) |
| "Volume broken down by keyword"  | `/v1/topics/{t}/volume/keywords`                                                        |
| "Find posts mentioning X"        | `/v1/topics/{t}/search` (See+)                                                          |
| "Which entities co-occur"        | `/v1/topics/{t}/entities/cooccurrence` (See+)                                           |
| "Push me when something spikes"  | [Alerts via webhook](/alerts#webhook-delivery-see-and-know)                             |

Trending is the **ranked-state** view. Everything else is volume, content, or events.

<Note>Last reviewed: 2026-05-19. API version 1.2.8.</Note>
