Build a DEX screener

Rank live pairs by the metric you care about, then keep the list fresh.

A screener is one call. The work is in choosing the filter.

curl -G 'https://api.preview.avee.tech/api/v1/pairs' \
  -d chains=hyperliquid,ton \
  -d min_liquidity_usd=25000 \
  -d min_score=60 \
  -d only_trustable=true \
  -d sort=volume -d timeframe=1h -d order=desc \
  -d limit=50

Every filter is an AND. sort=volume with timeframe=1h ranks by the last hour; sort=trending and sort=hottest are composite boards that define their own windows and ignore timeframe.

Filter for reality, not for noise

Three filters remove most of what wastes a trader's attention:

FilterWhy
min_liquidity_usdA pair with $200 of liquidity has a price, but not one you can trade.
only_trustable=trueDrops pairs where the pair or either token carries a terminal scam status.
max_deployed_pairsA deployer with four hundred launches is a factory, not a project.
min_scoreThe trust score, 0–100. Sixty removes most of the tail without hiding new pairs.
min_age_seconds / max_age_secondsPair age. max_age_seconds=3600 is "new pairs, last hour".

only_trustable is the cheap version of a rug filter. For the full picture, read trust signals.

Keep it fresh without re-reading it

The list changes every couple of seconds; unchanged answers do not need to travel. Send the ETag back:

let etag: string | undefined;

async function poll() {
  const res = await fetch(url, {
    headers: {
      ...(etag ? {'If-None-Match': etag} : {}),
    },
  });

  if (res.status === 304) return null;

  etag = res.headers.get('etag') ?? undefined;
  return res.json();
}

A 304 has no body. See Authentication and limits for what each call spends.

Omitting chains

Leave chains out and the screener covers every chain that is live right now — including one launched after you deployed. That is usually what you want; naming chains explicitly is for when your product is deliberately scoped to a venue.

Then

On this page