Skip to content

GuidesCookbook

The smart-money feed is a scored-trade feed. It ranks trades that have already happened; it is informational and is not a recommendation, and treating a score as a signal to copy is a misreading of what it measures.

Trader Intelligence is the reference. This page builds a watcher.

Terminal window
curl -s "$PREDICTEFY_API_URL/v1/traders/smart-money?minScore=80&window=day&limit=100" \
-H "Authorization: Bearer pk_live_YOUR_KEY"

Every parameter is optional:

ParameterValues
venueOne Trader Intelligence venue
minScore0–100
marketExact market id
walletExact venue-scoped wallet
categorybot, whale, smart, fresh, fish
windowday, week, month, all (default all)
limit1–100
cursorOpaque (ts, tradeId) keyset cursor

Rows add tradeScore, tradeFactors, scoreVersion, walletScoreAtTrade and categoryAtTrade to the normal trader-trade fields. Under score version t1 the factors are walletScore, size, entry and timing.

The feed is newest-first. Its cursor walks backward to rows older than the last row on the current page; it is not a forward watcher checkpoint. Start every poll without a cursor, then use the top-level nextCursor only to walk older pages until you reach the newest trade saved from the previous poll.

let initialized = false;
let newestSeen = null;
function tradeKey(trade) {
return `${trade.venue}:${trade.ts}:${trade.tradeId}`;
}
async function poll() {
let cursor = null;
let newestInPoll = null;
let reachedPrevious = false;
const fresh = [];
do {
const url = new URL('/v1/traders/smart-money', BASE);
url.searchParams.set('minScore', '80');
url.searchParams.set('window', 'day');
url.searchParams.set('limit', '100');
if (cursor) url.searchParams.set('cursor', cursor);
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.PREDICTEFY_API_KEY}` },
});
const body = await res.json();
if (!body.success) {
// TRADERS_UNSUPPORTED is a 400 and is not retryable — it is an answer.
if (!body.error.retryable) throw new Error(`${body.error.code}: ${body.error.message}`);
return;
}
if (newestInPoll === null && body.data[0]) newestInPoll = tradeKey(body.data[0]);
for (const trade of body.data) {
if (tradeKey(trade) === newestSeen) {
reachedPrevious = true;
break;
}
fresh.push(trade);
}
cursor = reachedPrevious ? null : (body.nextCursor ?? null);
} while (initialized && cursor);
// The first poll establishes a baseline instead of alerting the existing feed.
if (!initialized) {
initialized = true;
newestSeen = newestInPoll;
return;
}
for (const trade of fresh.reverse()) alert(trade);
if (newestInPoll !== null) newestSeen = newestInPoll;
}

Persist newestSeen across process restarts and keep the filter set unchanged. Reusing a backward cursor on the next poll skips trades that arrived after that cursor was minted; restarting from the newest page and stopping at the saved trade avoids both misses and duplicate alerts.

  • window=all means all collected feed data. No historical backfill is included — the feed starts when collection started, so an empty early window is a collection boundary, not a quiet market.
  • walletScoreAtTrade and categoryAtTrade are the values as they were at the time of the trade, not the wallet’s current standing. Rendering a current score next to a historical trade attributes information to the trader that they did not have.
  • scoreVersion matters. Factors differ between versions, so scores are not comparable across them. Store the version with anything you persist.
  • A listed capability is not a claim that rows exist. Scored-trade coverage requires activity from that venue; a supported venue can legitimately return nothing.
ResponseMeaning
400 TRADERS_UNSUPPORTEDThat venue does not support that verb. Not retryable.
404 TRADER_NOT_FOUNDUnknown wallet.
404 on any /v1/traders/*Trader Intelligence is unavailable.

TRADERS_UNSUPPORTED names the verb and the venue — for example, market holders being unsupported on a given venue. Do not fall back to another venue’s data to fill the gap; the honest render is that this venue does not expose it. See Capability-honest data.

The same surface is available as MCP tools — get_smart_money, get_market_traders, get_market_holders, get_leaderboard, get_wallet_profile — each capped at 100 rows, with get_wallet_profile under a 50 KB response budget. See MCP server.