Demand

GET /api/v1/demand/ Auth required

Search-demand cut

Single parametrized endpoint over the market-demand cut (slot × country search-volume aggregate). The volume_12m figure is a SUM over a rolling 12-month window shared by every row in the response (not the latest month) — see meta.window and meta.coverage.pairs_at_frontier_pct for how complete the current month's collection is. coverage=our own catalogue, not the wider market (meta.coverage.basis). The response schema is a oneOf over four envelopes, one per axis family, and meta.by tells you which one you received: by='slot' carries per-market detail, by='slot_global' aggregates a slot across markets, by='country' is one market per row, and the remaining axes share a keyed shape. See the examples for each.

Parameters

Name In Type Required Description Example
by query string optional Cut axis; the shape of each result item is decided by this parameter alone. 'slot' (default) is one slot in ONE market and requires ?country=; 'slot_global' is one slot aggregated across every tracked market and does not require one; passing ?country= there simply narrows the aggregate. 'country' is one market; 'provider', 'theme', 'feature', 'mechanic' and 'game_category' share one shape keyed by the axis value. Any other value → 400. 'theme'/'feature' are overlapping axes (a slot with multiple themes counts in each) — see response meta.overlapping. Allowed: country · feature · game_category · mechanic · provider · slot · slot_global · theme
country query string optional 2-letter ISO country code (case-insensitive, normalized to upper-case). REQUIRED when by='slot', because that axis reports one slot in one market and its per-market fields are undefined without one — use by='slot_global' for a worldwide ranking instead. Optional for every other axis, where omitting it aggregates across all tracked markets. Invalid format → 400.
coverage query boolean optional false suppresses meta.coverage entirely — the coverage aggregates are not computed at all, rather than computed and discarded. Omitted or true follows the default rule: meta.coverage is populated on the first page of a cursor traversal (previous == null) and null on subsequent pages. Any other value returns 400.
cursor query string optional Opaque pagination cursor from a previous response's next/previous link.
feature query string optional Feature slug (exact match). Non-existent slug → empty results, not 400.
game_category query string optional Game category filter (catalogue). One of: unknown, video_slot, crash, instant_win, scratch, live, table, other. Not to be confused with ?by=game_category (cut axis) — both can be combined. Allowed: crash · instant_win · live · other · scratch · table · unknown · video_slot
has_bonus_buy query string optional 'true' or 'false'. Any other value returns 400.
jackpot_type query string optional Jackpot type (none/fixed/progressive/pooled/unknown) Allowed: fixed · none · pooled · progressive · unknown
max_win_max query integer optional max_win <= this value (multiplier of stake, positive integer). Also filters GET /api/v1/demand/ — same catalogue filter.
max_win_min query integer optional max_win >= this value (multiplier of stake, positive integer). Also filters GET /api/v1/demand/ — same catalogue filter.
mechanic query string optional Bet mechanic (catalogue filter). One of: lines, ways, cluster, megaways, scatter_pays. Not to be confused with ?by=mechanic (cut axis) — both can be combined. Allowed: cluster · lines · megaways · scatter_pays · variable_ways · ways
ordering query string optional Whitelist: '-volume_12m' (default, highest demand first) or 'volume_12m' (lowest first). Any other value → 400. Allowed: -volume_12m · volume_12m
page_size query integer optional Number of results per page. Default 20, maximum 100 — same limits as the rest of the public API. An operator-configured limit may lower the maximum.
provider query string optional Provider slug (exact match). Non-existent slug → empty results, not 400. Not to be confused with ?by=provider (cut axis) — both can be combined.
released_after query string(date) optional ISO date (YYYY-MM-DD). release_date >= this value. Slots with release_date IS NULL are excluded. 400 on invalid format.
released_before query string(date) optional ISO date (YYYY-MM-DD). release_date <= this value — INCLUSIVE, the named day is part of the range. Note that ?published_before, ?posted_before and ?established_before on other endpoints are EXCLUSIVE. Slots with release_date IS NULL are excluded. 400 on invalid format.
rtp_max query number(double) optional rtp_default <= this value (percent, decimal, e.g. 96.5). Also filters GET /api/v1/demand/ — same catalogue filter.
rtp_min query number(double) optional rtp_default >= this value (percent, decimal, e.g. 96.5). Also filters GET /api/v1/demand/ — same catalogue filter.
search query string optional Case-insensitive substring search over slot name + aliases. Empty/whitespace-only value is a no-op (does not narrow results). Soft-clipped to 100 characters (not a 400).
series query string optional Series slug (exact match). A slot belongs to at most one series.
theme query string optional Theme slug (exact match). Non-existent slug → empty results, not 400.
volatility query string optional Volatility (low/med_low/medium/med_high/high/very_high) Allowed: high · low · med_high · med_low · medium · very_high
curl \
  -H "Authorization: Token <YOUR_TOKEN>" \
  "https://i-gaming.tools/api/v1/demand/"
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://i-gaming.tools/api/v1/demand/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Token <YOUR_TOKEN>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
const response = await fetch("https://i-gaming.tools/api/v1/demand/", {
  method: "GET",
  headers: {
  "Authorization": "Token <YOUR_TOKEN>"
}
});
const data = await response.json();
console.log(data);
import requests

headers = {
    "Authorization": "Token <YOUR_TOKEN>"
}
response = requests.get("https://i-gaming.tools/api/v1/demand/", headers=headers)

print(response.json())
Example response
{
  "meta": {
    "by": "slot",
    "country": "BR",
    "window": {
      "start": "2025-07",
      "end": "2026-06"
    },
    "window_mixed": false,
    "metric": "volume_12m",
    "total_volume_12m": 4820100,
    "overlapping": false,
    "coverage": {
      "basis": "our_catalogue",
      "markets_tracked": 81,
      "slots_total": 509,
      "providers": [
        {
          "slug": "pragmatic-play",
          "name": "Pragmatic Play",
          "slots": 509
        }
      ],
      "pairs_at_frontier_pct": 70,
      "computed_at": "2026-07-29T03:30:00Z"
    }
  },
  "next": null,
  "previous": null,
  "results": [
    {
      "slot": {
        "slug": "example-slot-title",
        "name": "Example Slot Title",
        "provider": {
          "slug": "pragmatic-play",
          "name": "Pragmatic Play"
        },
        "demo_url": "https://demo.i-gaming.tools/iframe/example-slot-title/"
      },
      "volume_12m": 12000,
      "months_covered": 12,
      "last_seen": {
        "month": "2026-06",
        "volume": 1100
      },
      "prev_volume": 950
    }
  ]
}