# Trends

A trend is a story: the articles that many sources publish about the same event, grouped by EarlyWave as they arrive. Trends are built from every source EarlyWave reads, so every key sees the same trends, whatever its account follows.

Four operations cover them:

| REST | MCP tool | Returns |
|---|---|---|
| `GET /trends` | `list_trends` | Trends, filtered and sorted. |
| `GET /trends/{trend_id}` | `get_trend` | One trend with its summary, entities, keywords and 10 latest articles. |
| `GET /trends/{trend_id}/articles` | `get_trend_articles` | Every article of a trend, with its source. |
| `GET /trends/{trend_id}/coverage` | `get_trend_coverage` | Where a trend is covered: countries, languages, hour by hour. |

## List trends

```bash
curl "https://api.earlywave.ai/api/v1/trends?country=FR&since_hours=24&limit=5" \
  -H "Authorization: Bearer $EARLYWAVE_API_KEY"
```

The list holds active stories only. As on the Trends page, stories EarlyWave judged low quality and recurring formats (horoscopes, exchange rates, daily deals, lottery results) are left out.

### Filters

All filters are optional and combine with AND. Lists of values are comma-separated and match any of them.

| Parameter | Example | Keeps the trends… |
|---|---|---|
| `country` | `FR` | about this country (`subject_countries` contains it). |
| `publisher_country` | `DE` | covered by at least 2 sources from this country (`publisher_countries`). |
| `category` | `politics,economy` | in one of these categories. |
| `stage` | `breakout` | at one of these stages: `emerging`, `accelerating`, `breakout`. |
| `reach` | `international,global` | with one of these reaches: `local`, `national`, `international`, `global`. |
| `since_hours` | `24` | that started within this many hours (1–720). |
| `query` | `strike` | whose title contains this text (case-insensitive). |

Categories: `ai`, `tech`, `business`, `economy`, `crypto`, `cyber`, `geopolitics`, `politics`, `energy`, `climate`, `health`, `science`, `space`, `society`, `sports`, `cinema`, `people`, `music`, `world`.

Countries are ISO 3166-1 alpha-2 codes. A three-letter code or an unknown category answers `400` with the allowed values in the message.

### Sorting

| `sort` | Order |
|---|---|
| `signal` (default) | Strongest signal first (`signal_score`). |
| `recent` | Latest activity first (`last_activity_at`). |
| `sources` | Most distinct sources first (`source_count`). |

### The fields of a trend

```json
{
  "id": 48213,
  "title": "Rail strike disrupts travel across France",
  "url": "https://www.earlywave.ai/trends/trend/48213",
  "status": "active",
  "stage": "accelerating",
  "category": "society",
  "reach": "national",
  "subject_countries": ["FR"],
  "publisher_countries": ["FR", "BE", "CH"],
  "item_count": 142,
  "source_count": 61,
  "signal_score": 74.2,
  "velocity_1h": 9,
  "velocity_24h": 118,
  "started_at": "2026-10-18T05:42:00.000Z",
  "earliest_item_at": "2026-10-18T05:42:00.000Z",
  "first_seen_at": "2026-10-18T06:10:12.000Z",
  "last_activity_at": "2026-10-19T08:55:31.000Z"
}
```

| Field | Meaning |
|---|---|
| `url` | The trend's page on earlywave.ai, to link people to. |
| `status` | `active` in lists. `get_trend` can also return older stories. |
| `stage` | The story's momentum: `emerging`, `accelerating`, `breakout`. |
| `reach` | How far the coverage spreads, from the publishers' countries and languages: `local`, `national`, `international`, `global`. `null` until computed. |
| `subject_countries` | Countries the story is about. Empty for a story about no country in particular. |
| `publisher_countries` | Countries with at least 2 sources covering the story, most sources first. |
| `item_count` / `source_count` | Articles, and distinct sources (sites) that published them. |
| `signal_score` | EarlyWave's composite score, 0–100. |
| `velocity_1h` / `velocity_24h` | Articles in the last hour / 24 hours. |
| `started_at` | When the story started: its earliest trusted article. Use this one. |
| `first_seen_at` | When EarlyWave grouped the articles into a story, usually a little later. |
| `last_activity_at` | The latest article. |

`subject_countries` and `publisher_countries` answer different questions. A story about France covered by German media has `subject_countries: ["FR"]` and `"DE"` in `publisher_countries`: `country=FR` and `publisher_country=DE` both find it.

## Get one trend

```bash
curl "https://api.earlywave.ai/api/v1/trends/48213" \
  -H "Authorization: Bearer $EARLYWAVE_API_KEY"
```

The answer has every field of the list, plus:

```json
{
  "summary": "Rail unions began a 48-hour strike over pay. Two trains in three were cancelled on Monday morning.",
  "regions": ["FR", "BE"],
  "publisher_languages": ["fr", "en"],
  "top_entities": [{ "name": "SNCF", "type": "ORGANIZATION" }],
  "top_keywords": [{ "term": "rail strike", "aliases": ["grève"], "kind": "concept" }],
  "sources": [
    {
      "id": 9917305,
      "title": "Rail strike: two trains in three cancelled on Monday",
      "url": "https://news.example.fr/rail-strike-monday",
      "published": "2026-10-19T08:41:00.000Z"
    }
  ]
}
```

- `summary` is written by EarlyWave from the articles; `null` until then.
- `publisher_languages` lists the languages with at least 2 sources. `regions` is an older list of country codes; prefer `subject_countries` and `publisher_countries`.
- `top_entities` holds up to 5 `{ "name", "type" }` (`PERSON`, `ORGANIZATION`, `LOCATION`, `EVENT`, `PRODUCT`); `top_keywords` holds `{ "term", "aliases", "kind" }`. Their shape is typed loosely in the schema: read them defensively.
- `sources` holds the 10 most recently added articles. For all of them, use the next operation.

An unknown ID answers `404` with code `trend_not_found`.

## List a trend's articles

```bash
curl "https://api.earlywave.ai/api/v1/trends/48213/articles?sort=oldest&limit=1" \
  -H "Authorization: Bearer $EARLYWAVE_API_KEY"
```

```json
{
  "trend_id": 48213,
  "articles": [
    {
      "id": 9911842,
      "title": "Rail unions call a 48-hour strike from Saturday",
      "url": "https://news.example.fr/rail-unions-strike",
      "preview": "The four main rail unions called a strike over the pay offer made on Thursday…",
      "image_url": null,
      "author": null,
      "published": "2026-10-18T05:42:00.000Z",
      "feed_id": 1207,
      "language": "en",
      "source": {
        "feed_id": 1207,
        "title": "Example News",
        "website_url": "https://news.example.fr",
        "country": "FR"
      }
    }
  ],
  "total": 142,
  "limit": 1,
  "offset": 0,
  "has_more": true
}
```

`sort=latest` (default) gives the newest first, `sort=oldest` the first coverage first: with `limit=1`, who broke the story. `source.country` is the publisher's country.

## Where a trend is covered

```bash
curl "https://api.earlywave.ai/api/v1/trends/48213/coverage" \
  -H "Authorization: Bearer $EARLYWAVE_API_KEY"
```

```json
{
  "trend_id": 48213,
  "total_articles": 142,
  "total_sources": 61,
  "first_article_at": "2026-10-18T05:42:00.000Z",
  "peak_at": "2026-10-19T07:00:00.000Z",
  "countries": [
    { "country": "FR", "sources": 52, "articles": 126, "first_article_at": "2026-10-18T05:42:00.000Z", "peak_hour": "2026-10-19T07:00:00.000Z" },
    { "country": "BE", "sources": 5, "articles": 9, "first_article_at": "2026-10-18T09:15:00.000Z", "peak_hour": "2026-10-19T08:00:00.000Z" },
    { "country": "CH", "sources": 4, "articles": 7, "first_article_at": "2026-10-18T11:02:00.000Z", "peak_hour": "2026-10-19T08:00:00.000Z" }
  ],
  "languages": [
    { "language": "fr", "sources": 57, "articles": 134 },
    { "language": "en", "sources": 4, "articles": 8 }
  ],
  "series": {
    "start": "2026-10-12T10:00:00.000Z",
    "step_minutes": 60,
    "articles": [0, 0, 0, "…", 14, 9],
    "sources": [0, 0, 0, "…", 11, 7],
    "new_sources": [0, 0, 0, "…", 3, 1]
  }
}
```

This is the same data as the "Where it is covered" card of a trend page.

- `countries` lists every publisher country, most sources first, with the first article and the busiest hour in each. A source is a distinct site.
- `series` covers the last 7 days in 168 hourly buckets starting at `start`. `articles` counts articles per hour, `sources` the distinct sources publishing that hour, `new_sources` those publishing on the story for the first time. (The arrays above are shortened; the real ones hold 168 numbers.)

## Recipes

| Question | Request |
|---|---|
| What is France talking about today? | `GET /trends?country=FR&since_hours=24&sort=sources` |
| Which stories about France are covered abroad? | `GET /trends?country=FR&reach=international,global` |
| What do German media cover most right now? | `GET /trends?publisher_country=DE` |
| Which tech stories are breaking out? | `GET /trends?category=tech,ai&stage=breakout` |
| Who broke this story? | `GET /trends/{trend_id}/articles?sort=oldest&limit=1` |
| Has it crossed borders, and when? | `GET /trends/{trend_id}/coverage`, then `countries[].first_article_at` |
| What is new in the last hour? | `GET /trends?since_hours=1&sort=recent` |

Polling for new stories? Once every few minutes is plenty, and stays far below the [rate limit](https://www.earlywave.ai/developers/docs/errors-and-limits#rate-limit).

---
Source: https://www.earlywave.ai/developers/docs/trends · All docs: https://www.earlywave.ai/llms.txt
