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

# Demand & Intent — Game endpoints reference

> Game demand leaderboards, individual game profiles, trending titles, watched games, and per-game condition breakdowns. Scope: demand-intent.read.

The game demand endpoints let you see which retro game titles buyers are actively seeking — measured by purchase-intent clicks (redirects to eBay listings), watchlist alerts, and search activity. Use them to answer questions like "what should I stock right now?", "is interest in this title accelerating?", and "should I sell this copy loose or complete in box?". All endpoints documented on this page require the `demand-intent.read` scope and a valid `Authorization: Bearer <token>` header.

## Common query parameters

All list endpoints on this page share the following query parameters.

<ParamField query="period" type="string" default="7d">
  The time window to aggregate over. One of `day`, `7d`, or `30d`.
</ParamField>

<ParamField query="console_id" type="integer">
  Restrict results to games belonging to this console. Omit to return results across all consoles.
</ParamField>

<ParamField query="date" type="string">
  Override the target date. Defaults to the latest computed date for the selected period. Format: `YYYY-MM-DD`.
</ParamField>

<ParamField query="limit" type="integer" default="25">
  Page size. Capped by your plan's `max_page_size`.
</ParamField>

<ParamField query="page" type="integer" default="1">
  Page number (page-mode pagination).
</ParamField>

<ParamField query="cursor" type="string">
  Cursor token for cursor-mode pagination. Pass `paginate=cursor` to opt in.
</ParamField>

<ParamField query="paginate" type="string" default="page">
  Pagination mode. Set to `cursor` to use cursor-based pagination.
</ParamField>

## Derived fields

Several fields in the response are computed from the raw demand data rather than stored directly. Understanding how they are derived helps you interpret what they signal.

### `momentum`

```
momentum = (redirects_7d / 7) ÷ (redirects_30d / 30)
```

Momentum measures whether buyer interest is accelerating or fading by comparing the recent 7-day daily pace against the longer 30-day baseline. A value above 1.0 means the game is getting more attention recently than its baseline average.

| Label     | Condition             |
| --------- | --------------------- |
| `rising`  | momentum 1.2 or above |
| `steady`  | between 0.8 and 1.2   |
| `cooling` | below 0.8             |

When a game has no 30-day baseline (it is newly tracked, or had no activity in the prior 30 days), both `value` and `label` are returned as `null` / `"unknown"`.

### `demand_score`

A single 0–100 index blending intent, reach, and watch demand into one comparable number. Each component is normalised against the highest value in the current period and console scope, so the top-ranked title always scores 100 and every other title is scored relative to it.

The three signals blended are:

* **Intent** — redirect volume (purchase-intent clicks).
* **Reach** — distinct users who generated those clicks.
* **Watch demand** — watchlist alert count.

### `mobile_share`

The fraction of demand activity that originated from a mobile device, expressed as a value between `0.0` (no mobile activity) and `1.0` (all mobile). Useful for understanding your buyers' browsing context.

***

## GET /api/v1/demand-intent/games

Returns a ranked leaderboard of games by demand for the selected period. Use this endpoint to answer "what should I source and stock right now?"

```bash theme={null}
curl -s "https://api.8bitedge.com/api/v1/demand-intent/games" \
  -H "Authorization: Bearer $TOKEN" | jq
```

### Query parameters

In addition to the [common parameters](#common-query-parameters):

<ParamField query="sort" type="string" default="intent">
  Sort order for the leaderboard. One of:

  * `intent` — by redirect volume (default)
  * `watches` — by `watch_count` descending (latent demand)
  * `momentum` — by the momentum ratio descending (fastest-rising first)
</ParamField>

### Response

Returns a paginated array of leaderboard rows. The `meta` object includes the resolved `period`, `period_date`, and `sort`.

<ResponseField name="data" type="array">
  Array of leaderboard rows, each representing one game ranked by the selected sort.

  <ResponseField name="rank" type="integer">
    The game's rank within the current period and sort. Precomputed from the demand metrics tables.
  </ResponseField>

  <ResponseField name="game" type="object">
    Game identity fields.

    <ResponseField name="id" type="integer">Unique game ID.</ResponseField>
    <ResponseField name="name" type="string">Display name of the game.</ResponseField>
    <ResponseField name="slug" type="string">URL slug for the game.</ResponseField>
    <ResponseField name="console_id" type="integer">ID of the console this game belongs to.</ResponseField>
    <ResponseField name="console_name" type="string">Display name of the console.</ResponseField>
  </ResponseField>

  <ResponseField name="intent" type="object">
    Purchase-intent signals derived from redirect clicks to eBay listings.

    <ResponseField name="redirects" type="integer">Number of purchase-intent clicks in the period.</ResponseField>
    <ResponseField name="distinct_users" type="integer">Number of unique users who clicked through.</ResponseField>
    <ResponseField name="mobile_share" type="float">Fraction of clicks from mobile devices (0.0–1.0).</ResponseField>
  </ResponseField>

  <ResponseField name="watch" type="object">
    Watchlist / notification alert signals (latent demand).

    <ResponseField name="watch_count" type="integer">Number of active watchlist alerts for this game in the period.</ResponseField>
  </ResponseField>

  <ResponseField name="momentum" type="object">
    Acceleration of interest relative to the 30-day baseline.

    <ResponseField name="value" type="float">Computed ratio. `null` when no 30-day baseline exists.</ResponseField>
    <ResponseField name="label" type="string">`rising`, `steady`, `cooling`, or `unknown`.</ResponseField>
  </ResponseField>

  <ResponseField name="pricing" type="object">
    Current market prices from the catalog.

    <ResponseField name="loose" type="string">Loose (cartridge/disc only) price as a decimal string.</ResponseField>
    <ResponseField name="complete" type="string">Complete-in-box price as a decimal string.</ResponseField>
    <ResponseField name="new" type="string">Sealed/new price as a decimal string.</ResponseField>
  </ResponseField>

  <ResponseField name="demand_score" type="integer">
    Composite 0–100 demand index. The highest-ranked title in the result set always scores 100.
  </ResponseField>
</ResponseField>

<ResponseField name="meta" type="object">
  <ResponseField name="period" type="string">The resolved period (`day`, `7d`, or `30d`).</ResponseField>
  <ResponseField name="period_date" type="string">The date the data was computed for (YYYY-MM-DD).</ResponseField>
  <ResponseField name="sort" type="string">The active sort (`intent`, `watches`, or `momentum`).</ResponseField>
  <ResponseField name="pagination" type="object">Standard pagination metadata (see [Pagination](/concepts/pagination)).</ResponseField>
</ResponseField>

**Example response:**

```json theme={null}
{
  "data": [
    {
      "rank": 1,
      "game": {
        "id": 412,
        "name": "Chrono Trigger",
        "slug": "chrono-trigger",
        "console_id": 19,
        "console_name": "Nintendo SNES"
      },
      "intent": { "redirects": 980, "distinct_users": 712, "mobile_share": 0.41 },
      "watch": { "watch_count": 64 },
      "momentum": { "value": 1.4, "label": "rising" },
      "pricing": { "loose": "40.00", "complete": "95.50", "new": "300.00" },
      "demand_score": 100
    }
  ],
  "meta": {
    "period": "7d",
    "period_date": "2026-06-16",
    "sort": "intent",
    "pagination": { "mode": "page", "page": 1, "per_page": 25, "total": 842, "last_page": 34 }
  },
  "links": { "next": "https://api.8bitedge.com/api/v1/demand-intent/games?page=2", "prev": null }
}
```

***

## GET /api/v1/demand-intent/games/{game_id}

Returns a full demand profile for one game, with metrics shown side-by-side for all three periods (`day`, `7d`, and `30d`). Use this to understand how a specific title is performing across different time horizons.

```bash theme={null}
curl -s "https://api.8bitedge.com/api/v1/demand-intent/games/412" \
  -H "Authorization: Bearer $TOKEN" | jq
```

### Path parameters

<ParamField path="game_id" type="integer" required>
  The numeric ID of the game. You can resolve IDs from the [Games catalog endpoints](/api/games).
</ParamField>

### Response

<ResponseField name="data" type="object">
  <ResponseField name="game" type="object">
    <ResponseField name="id" type="integer">Game ID.</ResponseField>
    <ResponseField name="name" type="string">Display name.</ResponseField>
    <ResponseField name="console_name" type="string">Display name of the console.</ResponseField>
  </ResponseField>

  <ResponseField name="pricing" type="object">
    Current market prices.

    <ResponseField name="loose" type="string">Loose price (decimal string).</ResponseField>
    <ResponseField name="complete" type="string">Complete-in-box price (decimal string).</ResponseField>
    <ResponseField name="new" type="string">Sealed/new price (decimal string).</ResponseField>
  </ResponseField>

  <ResponseField name="periods" type="object">
    Demand metrics for each time window.

    <ResponseField name="day" type="object">
      <ResponseField name="redirects" type="integer">Purchase-intent clicks in the last day.</ResponseField>
      <ResponseField name="distinct_users" type="integer">Unique users in the last day.</ResponseField>
      <ResponseField name="watch_count" type="integer">Active watchlist alerts in the last day.</ResponseField>
      <ResponseField name="rank" type="integer">Leaderboard rank for the day period.</ResponseField>
    </ResponseField>

    <ResponseField name="7d" type="object">
      <ResponseField name="redirects" type="integer">Purchase-intent clicks in the last 7 days.</ResponseField>
      <ResponseField name="distinct_users" type="integer">Unique users in the last 7 days.</ResponseField>
      <ResponseField name="watch_count" type="integer">Active watchlist alerts in the last 7 days.</ResponseField>
      <ResponseField name="rank" type="integer">Leaderboard rank for the 7-day period.</ResponseField>
    </ResponseField>

    <ResponseField name="30d" type="object">
      <ResponseField name="redirects" type="integer">Purchase-intent clicks in the last 30 days.</ResponseField>
      <ResponseField name="distinct_users" type="integer">Unique users in the last 30 days.</ResponseField>
      <ResponseField name="watch_count" type="integer">Active watchlist alerts in the last 30 days.</ResponseField>
      <ResponseField name="rank" type="integer">Leaderboard rank for the 30-day period.</ResponseField>
    </ResponseField>
  </ResponseField>

  <ResponseField name="momentum" type="object">
    <ResponseField name="value" type="float">Momentum ratio (7-day pace vs. 30-day baseline). `null` if no baseline.</ResponseField>
    <ResponseField name="label" type="string">`rising`, `steady`, `cooling`, or `unknown`.</ResponseField>
  </ResponseField>
</ResponseField>

**Example response:**

```json theme={null}
{
  "data": {
    "game": { "id": 412, "name": "Chrono Trigger", "console_name": "Nintendo SNES" },
    "pricing": { "loose": "40.00", "complete": "95.50", "new": "300.00" },
    "periods": {
      "day":  { "redirects": 140,  "distinct_users": 121,  "watch_count": 9,   "rank": 2 },
      "7d":   { "redirects": 980,  "distinct_users": 712,  "watch_count": 64,  "rank": 1 },
      "30d":  { "redirects": 3120, "distinct_users": 2380, "watch_count": 210, "rank": 1 }
    },
    "momentum": { "value": 1.4, "label": "rising" }
  }
}
```

<Note>
  Returns `404 not_found` if the `game_id` does not correspond to an enabled game in the catalog.
</Note>

***

## GET /api/v1/demand-intent/games/{game_id}/conditions

Returns a condition breakdown for one game, showing whether buyers most want it **loose** (cartridge/disc only), **CIB** (complete in box), **new** (sealed), or **any** (no condition preference). This is sourced from saved notification alerts — real buyer intent with a specific condition attached — making it a reliable signal for how to list your copy.

```bash theme={null}
curl -s "https://api.8bitedge.com/api/v1/demand-intent/games/412/conditions?period=7d" \
  -H "Authorization: Bearer $TOKEN" | jq
```

### Path parameters

<ParamField path="game_id" type="integer" required>
  The numeric ID of the game.
</ParamField>

### Query parameters

<ParamField query="period" type="string" default="7d">
  The time window to aggregate over. One of `day`, `7d`, or `30d`.
</ParamField>

### Response

<ResponseField name="data" type="object">
  <ResponseField name="game" type="object">
    <ResponseField name="id" type="integer">Game ID.</ResponseField>
    <ResponseField name="name" type="string">Display name.</ResponseField>
    <ResponseField name="slug" type="string">URL slug.</ResponseField>
    <ResponseField name="console_id" type="integer">Console ID.</ResponseField>
    <ResponseField name="console_name" type="string">Console display name.</ResponseField>
  </ResponseField>

  <ResponseField name="pricing" type="object">
    <ResponseField name="loose" type="string">Loose price (decimal string).</ResponseField>
    <ResponseField name="complete" type="string">Complete-in-box price (decimal string).</ResponseField>
    <ResponseField name="new" type="string">Sealed/new price (decimal string).</ResponseField>
  </ResponseField>

  <ResponseField name="conditions" type="array">
    All four condition rows, sorted by rank. Rows sum to approximately 1.0 on `condition_share`.

    <ResponseField name="rank" type="integer">Rank within this game's conditions for the period.</ResponseField>
    <ResponseField name="condition" type="string">One of `loose`, `cib`, `new`, or `any`.</ResponseField>
    <ResponseField name="watch_count" type="integer">Number of active watchlist alerts for this game/condition pair.</ResponseField>
    <ResponseField name="update_count" type="integer">Number of price-drop notification triggers for this game/condition pair.</ResponseField>
    <ResponseField name="condition_share" type="float">This condition's share of all alerts across the game's four conditions (0.0–1.0). All four rows sum to \~1.0.</ResponseField>
    <ResponseField name="distinct_users" type="integer">Unique users behind these alerts.</ResponseField>
    <ResponseField name="mobile_share" type="float">Fraction of alert activity from mobile devices (0.0–1.0).</ResponseField>
  </ResponseField>
</ResponseField>

<Note>
  All four conditions are always returned. A condition with no alerts in the selected period appears as a zeroed row (`watch_count: 0`, `condition_share: 0.0`) ranked after the conditions that had activity. Returns `404 not_found` if the `game_id` is unknown or disabled.
</Note>

***

## GET /api/v1/demand-intent/trending

Returns games ranked by momentum — the fastest-rising titles whose recent daily activity most exceeds their 30-day baseline. Use this to get ahead of demand before prices move. The sort is fixed to `momentum` and cannot be overridden.

```bash theme={null}
curl -s "https://api.8bitedge.com/api/v1/demand-intent/trending?period=7d" \
  -H "Authorization: Bearer $TOKEN" | jq
```

### Query parameters

<ParamField query="period" type="string" default="7d">
  The time window to aggregate over. One of `day`, `7d`, or `30d`.
</ParamField>

<ParamField query="console_id" type="integer">
  Filter results to a single console.
</ParamField>

<ParamField query="date" type="string">
  Override the target date (defaults to latest computed).
</ParamField>

<ParamField query="limit" type="integer" default="25">
  Page size.
</ParamField>

<ParamField query="page" type="integer" default="1">
  Page number.
</ParamField>

<ParamField query="cursor" type="string">
  Cursor token for cursor-mode pagination.
</ParamField>

<ParamField query="paginate" type="string" default="page">
  Set to `cursor` for cursor-based pagination.
</ParamField>

### Response

Returns a paginated array of leaderboard rows in the same shape as `GET /api/v1/demand-intent/games`. The `meta.sort` field is always `"momentum"`.

<Tip>
  Games with no 30-day baseline are excluded from this endpoint — momentum is undefined without a prior period to compare against. If you need to include brand-new titles, use the main leaderboard with `sort=intent`.
</Tip>

***

## GET /api/v1/demand-intent/watched

Returns the most-watched games — titles with the highest number of active watchlist alerts, representing buyers who are waiting for the right price before purchasing. This surfaces latent demand that redirect intent alone may not capture: a game with modest click-through but many alert saves signals a price-sensitive buyer pool ready to act.

```bash theme={null}
curl -s "https://api.8bitedge.com/api/v1/demand-intent/watched?period=7d" \
  -H "Authorization: Bearer $TOKEN" | jq
```

### Query parameters

<ParamField query="period" type="string" default="7d">
  The time window to aggregate over. One of `day`, `7d`, or `30d`.
</ParamField>

<ParamField query="console_id" type="integer">
  Filter results to a single console.
</ParamField>

<ParamField query="date" type="string">
  Override the target date (defaults to latest computed).
</ParamField>

<ParamField query="limit" type="integer" default="25">
  Page size.
</ParamField>

<ParamField query="page" type="integer" default="1">
  Page number.
</ParamField>

<ParamField query="cursor" type="string">
  Cursor token for cursor-mode pagination.
</ParamField>

<ParamField query="paginate" type="string" default="page">
  Set to `cursor` for cursor-based pagination.
</ParamField>

### Response

Returns a paginated array of leaderboard rows in the same shape as `GET /api/v1/demand-intent/games`. The sort is fixed to `watch_count` descending. Redirect intent (`intent.redirects`) is left-joined from the intent table and may be `0` for titles that have watchlist saves but no purchase-intent clicks in the period.

<Note>
  Because this endpoint is built from the watch table rather than the intent table, you may see titles that do not appear on the main leaderboard at all — games people are waiting on but not yet actively clicking to buy.
</Note>
