Data API
A public REST API for large on-chain transfers, wallet balances, token checks, decoded transactions, curated labels and market context on Ethereum, Base, BNB Chain, Arbitrum, OP Mainnet, Polygon and Solana. Reading needs no sign-up. A free key, created after a wallet sign-in, raises the limit.
Base URL: https://farbeamlabs.com/api/v1. The API reference covers every parameter, and the OpenAPI file is machine-readable. You can send requests from the playground.
#Endpoint groups
| Group | Endpoints | Cost in units | What it returns | Reference |
|---|---|---|---|---|
| Service | 3 | 0, 0, 1 | Health, poller and source status, 30 days of samples | status |
| Chains | 5 | 1 | Coverage, recent blocks, gas, prices | chains |
| Transfers | 3 | 1, or 0 for the stream | Stored transfers of $100,000 or more, totals, live SSE | transfers |
| Wallets | 2 | 3 | Balances on six EVM chains or Solana, recent activity | wallet |
| Tokens | 1 | 3 | Market data, contract checks, holders, pools | token |
| Transactions | 1 | 2 | Status, fee, parties, decoded token movements | tx |
| Labels | 2 | 1 | The curated address label set | labels |
| Markets | 4 | 1 | Chain TVL, stablecoin supply, DEX volume, trending pools | stablecoins |
| Account | 7 | 0 or 1 | Solana wallet sign-in, session, account view, Telegram link | sign-in |
| Keys | 4 | 0 | Create a key after sign-in, read usage, revoke | create |
| Alert rules | 8 | 1 | Validate, store and test rules, read deliveries | create |
#Example request
This call asks for the newest USDT transfer on Ethereum of at least $1,000,000.
curl -s "https://farbeamlabs.com/api/v1/transfers?chain=ethereum&token=USDT&min_usd=1000000&limit=1"const url = new URL("https://farbeamlabs.com/api/v1/transfers");
url.search = new URLSearchParams({ chain: "ethereum", token: "USDT", min_usd: "1000000", limit: "1" });
const res = await fetch(url);
const { data, meta, error } = await res.json();
if (error) throw new Error(`${error.code}: ${error.message}`);
console.log(data[0].uid, data[0].usd, "next:", meta.next_cursor);import requests
res = requests.get(
"https://farbeamlabs.com/api/v1/transfers",
params={"chain": "ethereum", "token": "USDT", "min_usd": 1000000, "limit": 1},
timeout=30,
)
body = res.json()
if "error" in body:
raise RuntimeError(body["error"]["code"])
print(body["data"][0]["uid"], body["data"][0]["usd"], body["meta"]["next_cursor"])#Real response
This response was captured from the running API at 2026-11-04T19:24:11Z. It is complete and unedited. The call also returned the headers x-ratelimit-limit: 120, x-ratelimit-remaining: 119 and x-request-id: req_9e666357141a.
{
"data": [
{
"id": 1217,
"uid": "ethereum:0x5fe8bf27f732de57e963cb92a0f17173c1e2cdadfdabb241e7d3dc25a346c342:335",
"ts": "2026-11-04T19:12:59.000Z",
"chain": "ethereum",
"block": 26343466,
"tx": "0x5fe8bf27f732de57e963cb92a0f17173c1e2cdadfdabb241e7d3dc25a346c342",
"kind": "token",
"token": "USDT",
"token_address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"amount": 2500000,
"usd": 2498505,
"from": "0x8c5d0c5339c282b3e7f22a207e47d73d0227cba9",
"to": "0x8b820fe67e8367d322d0c1bfc809cd9fe478df52",
"sampled": false,
"from_label": null,
"from_type": null,
"to_label": null,
"to_type": null
}
],
"meta": {
"request_id": "req_9e666357141a",
"as_of": "2026-11-04T19:24:11.890Z",
"next_cursor": 1217,
"min_stored_usd": 100000,
"retention_days": 7
}
}The fields worth reading first:
uidis stable. Use it to remove duplicates between the stream, the REST API and webhooks.usdis the amount times the price at indexing. Here the price of USDT was $0.999402.from_labelandto_labelare null because neither address is in the label set. Null means unlabeled, not unknown to the chain.next_cursorgoes intobeforeon the next call.
#Limits
| Limit | Value |
|---|---|
| Without a key | 30 units per minute per network |
| With a free key | 120 units per minute and 20,000 units per UTC day, per key |
| Window | Fixed one-minute windows, reset on the minute |
| Keys per account | 5 active keys |
| Sign-in attempts | 30 per hour per network |
| Rows per page | 100 on /transfers |
| Request body | 32,768 bytes |
| Open SSE streams | 6 per network, 400 in total |
| Transfer history | 7 days |
| Stored threshold | $100,000 |
Cost per call: wallet and token endpoints cost 3 units, transaction lookup costs 2, health, status, key endpoints and /me cost 0, and most other endpoints cost 1. The cost is charged before the handler runs, so a request with a bad parameter still spends units. See rate limits.
#Error format
Every error has one shape. This one is real, from GET /chains/fantom at 2026-11-04T19:23:10Z, with HTTP status 400.
{
"error": {
"code": "invalid_chain",
"message": "Unknown chain. Use one of: ethereum, base, bnb, arbitrum, optimism, polygon, solana.",
"request_id": "req_fddb4d074326"
}
}| HTTP | Codes | What to do |
|---|---|---|
| 400 | invalid_chain, invalid_address, invalid_hash, invalid_parameter, invalid_json | Fix the request |
| 401 | missing_key, invalid_key | Send a valid key. A revoked key returns 401 even on public endpoints |
| 401 | sign_in_required, invalid_challenge, invalid_signature | Sign in again with a Solana wallet |
| 404 | not_found | The item does not exist, or the address has no label |
| 405 | method_not_allowed | Use another method |
| 409 | rule_limit, key_limit, telegram_not_linked | Remove a rule or a key, or link Telegram first |
| 413 | payload_too_large | Send a smaller body |
| 422 | invalid_rule, invalid_url | Fix the rule or webhook URL. The message gives the position |
| 429 | rate_limited, daily_limit | Wait for Retry-After seconds, or for the next UTC day |
| 502 | upstream_unavailable | A public source failed and no saved copy exists. The source field names it. Retry later |
| 503 | telegram_not_configured | The Telegram bot is not connected |
Details are on the errors page.
#What makes it different
This API is small, and these are the choices that shape it.
- Every token check names its source and the exact field it read, in
checks[].sourceandchecks[].field. - A missing field is
unknown. It never counts as a pass. There is no composite score to hide that in. - Coverage is part of the data:
sampledon every event,large_transfer_indexon every chain,coverage_noteon wallets,blocks_scannedon activity,staleon a saved copy. - Accounts need no email and no password, only a Solana wallet signature. The server stores only a SHA-256 hash of each key.
- Status reports measured poller and source state, including failure counts since the last restart.
#What it lacks
Check this list before you build on it.
- History ends at 7 days. There is no archive and no export. Planned
- The index covers curated tokens on four EVM chains, plus a Solana sample. You cannot ask for all transfers of an arbitrary token.
- Transfers below $100,000 are not stored. There is no time-range filter, only the
beforecursor. - There is no raw RPC, no trace data, no internal transfers, no decoded events beyond ERC-20
Transfer. - Time fields are not uniform.
/transfersreturns ISO 8601 strings./txandindexed_transfersinside/walletsreturn Unix milliseconds. - There is no SLA, no paid tier, no official SDK, no GraphQL and no WebSocket. Planned
- Sign-in works with Solana wallets only, so an EVM-only user cannot create a key today. EVM sign-in is Planned.
If you need any of these today, see the RPC provider comparison and the explorer comparison.
#Start
- Send a request without a key to confirm the shape.
- Sign in to the console with a Solana wallet, and create a free key. Save it, because it is shown once.
- Send it as
Authorization: Bearer <key>. - Read the quickstart.
Farbeam data is for information only. It is not financial advice.