> ## Documentation index
> Fetch the complete documentation index at: https://docs.predictefy.com/llms.txt
> Use it to discover every available page before exploring further.

# Alert on scored trades

> Poll the smart-money feed with keyset pagination, read the score honestly, and handle the venues that have no rows.

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](/reference/trader-intelligence/) is the reference. This page builds a
watcher.

## Poll

```sh
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:

| Parameter  | Values                                            |
| ---------- | ------------------------------------------------- |
| `venue`    | One Trader Intelligence venue                     |
| `minScore` | 0–100                                             |
| `market`   | Exact market id                                   |
| `wallet`   | Exact venue-scoped wallet                         |
| `category` | `bot`, `whale`, `smart`, `fresh`, `fish`          |
| `window`   | `day`, `week`, `month`, `all` (default `all`)     |
| `limit`    | 1–100                                             |
| `cursor`   | Opaque `(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`.

## Watch without re-alerting

The cursor is a keyset over `(ts, tradeId)`, so it is stable for a watcher: hold the newest
cursor and page forward from it.

```js
let cursor = null;

async function poll() {
  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;
  }

  for (const trade of body.data) alert(trade);
  cursor = body.page?.hasMore ? body.page.nextCursor : cursor;
}
```

Keep the cursor across polls rather than re-querying a time window. Two identical
window-based polls overlap, and a watcher that alerts on the overlap sends the same trade twice.

## Reading the score honestly

- **`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.

## The errors are answers

| Response                     | Meaning                                                |
| ---------------------------- | ------------------------------------------------------ |
| `400 TRADERS_UNSUPPORTED`    | That venue does not support that verb. Not retryable.  |
| `404 TRADER_NOT_FOUND`       | Unknown 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](/guides/honest-data/).

## Through an agent instead

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](/guides/mcp/).

## Related

- [Trader Intelligence](/reference/trader-intelligence/) — every route, parameter and venue capability
- [MCP server](/guides/mcp/) — the same data as agent tools
- [Capability-honest data](/guides/honest-data/) — why an unsupported verb is an answer
