curl "https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades?limit=50" \
-H "Authorization: Bearer $API_KEY"
curl "https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades?flags=bundler,insider" \
-H "Authorization: Bearer $API_KEY"
const url = new URL(
"https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades",
);
url.searchParams.set("limit", "50");
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.API_KEY}` },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const { trades, nextCursor, hasMore } = await response.json();
{
"trades": [
{
"id": "4xQmVb8e2kT1nR7pZcW3sLdHfA9jEuY6gVnX1oB5iC0wQ2rT8yU3iO7pA1sD4fG6h:2",
"chain": "solana",
"token": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"name": "Bonk",
"symbol": "Bonk",
"trader": "7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5",
"transactionHash": "4xQmVb8e2kT1nR7pZcW3sLdHfA9jEuY6gVnX1oB5iC0wQ2rT8yU3iO7pA1sD4fG6h",
"side": "buy",
"amount": "12500000",
"price": { "native": "0.000000121", "usd": "0.0000216" },
"volume": { "native": "1.51", "usd": "270.12" },
"marketCap": { "native": "10741962.1", "usd": "1917440000" },
"timestamp": 1789632015120
}
],
"nextCursor": "eyJ0cyI6MTc4OTYzMjAxNTEyMCwiaWQiOiI0eFFtVmI4ZTJrVDFuUjdwWmNXM3NMZEhmQTlq",
"hasMore": true
}
{
"trades": [],
"nextCursor": null,
"hasMore": false
}
REST
Token trades
Page through one token’s executed trades, newest first, narrowed by trader or wallet classification.
GET
/
v1
/
tokens
/
{chain}
/
{address}
/
trades
curl "https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades?limit=50" \
-H "Authorization: Bearer $API_KEY"
curl "https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades?flags=bundler,insider" \
-H "Authorization: Bearer $API_KEY"
const url = new URL(
"https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades",
);
url.searchParams.set("limit", "50");
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.API_KEY}` },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const { trades, nextCursor, hasMore } = await response.json();
{
"trades": [
{
"id": "4xQmVb8e2kT1nR7pZcW3sLdHfA9jEuY6gVnX1oB5iC0wQ2rT8yU3iO7pA1sD4fG6h:2",
"chain": "solana",
"token": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"name": "Bonk",
"symbol": "Bonk",
"trader": "7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5",
"transactionHash": "4xQmVb8e2kT1nR7pZcW3sLdHfA9jEuY6gVnX1oB5iC0wQ2rT8yU3iO7pA1sD4fG6h",
"side": "buy",
"amount": "12500000",
"price": { "native": "0.000000121", "usd": "0.0000216" },
"volume": { "native": "1.51", "usd": "270.12" },
"marketCap": { "native": "10741962.1", "usd": "1917440000" },
"timestamp": 1789632015120
}
],
"nextCursor": "eyJ0cyI6MTc4OTYzMjAxNTEyMCwiaWQiOiI0eFFtVmI4ZTJrVDFuUjdwWmNXM3NMZEhmQTlq",
"hasMore": true
}
{
"trades": [],
"nextCursor": null,
"hasMore": false
}
Recent trades on one token, newest first.
Filters
flags takes a comma-separated list of wallet classifications, such as bundler,insider. A trade is kept when its trader carries at least one of them, and fomo keeps trades routed through the fomo.family terminal. The same classifications filter the spot.trades stream, where fomo also keeps trades by wallets flagged fomo with no known terminal.
trader takes one wallet address, and keeps only that wallet’s trades.
Response
A page carriestrades, nextCursor and hasMore. nextCursor is the cursor for the next page, or null on the last one, and hasMore is true while another page waits. An unknown token answers an empty page, not a 404.
Paging
- Treat the cursor as opaque. Do not build, change or store meaning in it. Send back exactly what you received, and never build one yourself.
- Pages do not shift. The cursor marks a position in the list, not an offset. Trades that arrive while you page neither duplicate nor skip results.
- A bad cursor is refused. A cursor the API cannot read returns
400 VALIDATION_ERRORon thecursorfield. It never silently restarts from the first page.
import os
import requests
url = "https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
params = {"limit": 100}
while True:
response = requests.get(url, headers=headers, params=params, timeout=10)
response.raise_for_status()
page = response.json()
for trade in page["trades"]:
print(trade["id"], trade["side"], trade["volume"]["usd"])
if not page["hasMore"]:
break
params["cursor"] = page["nextCursor"]
const url = "https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades";
const headers = { Authorization: `Bearer ${process.env.API_KEY}` };
let cursor: string | null = null;
do {
const params = new URLSearchParams({ limit: "100" });
if (cursor) params.set("cursor", cursor);
const response = await fetch(`${url}?${params}`, { headers });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const page = await response.json();
for (const trade of page.trades) console.log(trade.id, trade.side, trade.volume.usd);
cursor = page.hasMore ? page.nextCursor : null;
} while (cursor);
Errors
| Code | When |
|---|---|
UNSUPPORTED_CHAIN | chain is not a supported slug |
VALIDATION_ERROR | A malformed address, a trader that does not match the chain’s format, an unknown flag, a cursor that does not decode, or an unknown parameter |
curl "https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades?limit=50" \
-H "Authorization: Bearer $API_KEY"
curl "https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades?flags=bundler,insider" \
-H "Authorization: Bearer $API_KEY"
const url = new URL(
"https://api.metastreams.io/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/trades",
);
url.searchParams.set("limit", "50");
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.API_KEY}` },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const { trades, nextCursor, hasMore } = await response.json();
{
"trades": [
{
"id": "4xQmVb8e2kT1nR7pZcW3sLdHfA9jEuY6gVnX1oB5iC0wQ2rT8yU3iO7pA1sD4fG6h:2",
"chain": "solana",
"token": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"name": "Bonk",
"symbol": "Bonk",
"trader": "7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5",
"transactionHash": "4xQmVb8e2kT1nR7pZcW3sLdHfA9jEuY6gVnX1oB5iC0wQ2rT8yU3iO7pA1sD4fG6h",
"side": "buy",
"amount": "12500000",
"price": { "native": "0.000000121", "usd": "0.0000216" },
"volume": { "native": "1.51", "usd": "270.12" },
"marketCap": { "native": "10741962.1", "usd": "1917440000" },
"timestamp": 1789632015120
}
],
"nextCursor": "eyJ0cyI6MTc4OTYzMjAxNTEyMCwiaWQiOiI0eFFtVmI4ZTJrVDFuUjdwWmNXM3NMZEhmQTlq",
"hasMore": true
}
{
"trades": [],
"nextCursor": null,
"hasMore": false
}
Authorizations
Send the API key as Authorization: Bearer <key>.
Path Parameters
Chain the resource lives on. Chain slug. One spelling per chain, in paths and bodies alike. Only a chain with spot data is published.
Available options:
solana, base, bsc, robinhood, arc Token mint or contract address.
Query Parameters
Rows per page, clamped to 1-100; 20 when absent.
Required range:
1 <= x <= 100Opaque cursor from the previous page.
Restrict to one trader wallet.
Wallet classifications to keep, comma-separated. Absent or empty keeps every trade.
Response
Recent trades, newest first; an unknown token answers an empty page.
A page of trades, newest first: one token's (GET /v1/tokens/{chain}/{address}/trades)
or one identity's across every token (GET /v1/trades).