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
}
]
}