Every endpoint, what it costs, and what it returns.
Twelve endpoints across identity resolution, trader theses and two live feeds. This page covers what a machine-generated spec cannot: how billing works, what a miss means, and how to read each response. For exact request and response shapes, the OpenAPI 3.1 document at GET /openapi.json is the source of truth. The running service generates it, so it cannot drift. The interactive Swagger UI (opens in a new tab) renders the same document and calls any endpoint live with your key.
Authentication
Send your key as a bearer token. X-Api-Key: $KEY is accepted as an alternative. Keys look like fsk_live_… (production) or fsk_test_… (sandbox).
Three families. Every paid plan reaches every REST endpoint, and pricing is per call, in compute units. Free keys reveal wallets for the sample set only. The live feed starts at Growth, and legacy plans keep it.
Identity
FomoScan identity endpoints: forward and reverse handle-to-wallet resolution.
Endpoint
Answers
Cost
GET /v2/user/handle/{handle}
handle → user + verified wallets
100 CU found, 200 not found
GET /v2/user/id/{id}
FOMO user id → user + verified wallets
100 CU found, 200 not found
GET /v2/user/wallet/{address}
wallet → the trader(s) behind it
30,000 CU found, 200 not found
POST /v2/user/handle/{handle}/resolve
go and resolve this handle, live
30,000 CU found, 200 on a 202 or 404
GET /v2/user/handle/{handle}/pnl
handle → realized, total and unrealized profit, whole wallet
30,000 CU ready, 200 not ready or not found
POST /v2/user/handles/pnl
up to 100 handles → the same, in one call
30,000 CU per entry ready, 200 per entry not ready or missing
FomoScan identity endpoints: forward and reverse handle-to-wallet resolution.
GET /v2/user/handle/{handle}/pnl reads one trader's profit and loss. You are billed on every call. Three outcomes carry three different meanings:
What each PnL endpoint result means
Result
Meaning
404
We do not hold this handle.
200, wallet: null
We know the trader but hold no proven wallet — never that they have none.
200, wallet set, every window null
We asked about that address and got nothing back. This does not mean the trader made no trades.
Theses
A thesis is a trader's written rationale attached to a token. All four endpoints are newest-first and take a before cursor to page backwards.
Endpoint
Answers
Cost
GET /v2/thesis
every thesis, newest first
200 CU per 20 rows
GET /v2/thesis/token/{tokenAddress}
one token's wall
200 CU per 20 rows
GET /v2/thesis/user/{id}
one author's wall
200 CU per 20 rows
GET /v2/thesis/user/{id}/token/{tokenAddress}
one author on one token
200 CU per 20 rows
A thesis is a trader's written rationale attached to a token. All four endpoints are newest-first and take a before cursor to page backwards.
Live feed
The theses feed, pushed over a WebSocket as items are indexed.
Endpoint
Answers
Cost
GET /v2/ws
theses pushed as they are indexed
20,000 CU per minute held open
The theses feed, pushed over a WebSocket as items are indexed.
One socket carries the whole thesis feed. Attach, then send one subscribe frame naming either every token or up to 50 token addresses, and change it later without reconnecting. A connection holds one subscription, and a new subscribe replaces whatever you had. pump.fun callouts have their own socket, described below.
The feed is included from Growth ($899). Growth, Scale and Enterprise keys can connect. Keys on legacy plans keep the access they already have. Self-serve free, Starter and Builder keys are refused during the handshake with 403 WEBSOCKET_PLAN_REQUIRED.
It authenticates with the same Authorization header, so the key cannot come from a browser — hold the socket in your backend.
There is no replay. Take a snapshot from GET /v2/thesis/token/{tokenAddress} on connect and reconcile on id after any reconnect.
The pong is mandatory: we ping every 30 seconds and close, with code 1011, a socket we have not heard from for 90 seconds.
Running out of quota closes the socket with code 1008.
A restart on our side closes the socket with code 1001. Reconnect and send your subscribe again.
Pump callouts (live)
New pump.fun callouts, sent over a WebSocket as they appear.
Endpoint
Answers
Cost
GET /v2/ws/pump
new pump.fun callouts as they appear
20,000 CU per minute held open
New pump.fun callouts, sent over a WebSocket as they appear.
New pump.fun callouts, sent to your server as they appear. Most callouts reach you within about a second of being posted on pump.fun. Each one is the same record GET /v2/pump/thesis returns, so your code reads one shape.
1. Connect
Open a WebSocket to this address with your key in the Authorization header, the same header as every other call. A browser cannot set that header, so hold the socket on your server and pass callouts on to your app from there.
You receive nothing until you subscribe. Send one of these messages. all gives you every new callout. tokens narrows it to up to 50 coins. A new subscribe replaces the one before it.
id: The callout. Match on it so nothing shows twice.
wallet: The author. On pump.fun the wallet is the account.
coinMint: The coin the callout is about.
thesis: What the author wrote.
calledOutAtMcap: Market cap in USD when the callout was posted.
multiple: Price move since the callout, as a multiple.
createdAt: Post time, in epoch milliseconds.
If the connection drops
There is no replay. Reconnect, send your subscribe again, then fetch GET /v2/pump/thesis to pick up anything you missed. Match on id so nothing shows twice.
A restart on our side closes the socket with code 1001. Reconnect at once and subscribe again.
Answer our pings. Standard WebSocket libraries do this for you. A socket we have not heard from for 90 seconds is closed with code 1011.
Plans and billing
Included from Growth ($899): Growth, Scale and Enterprise keys can connect. Keys on legacy plans keep the access they already have. Self-serve free, Starter and Builder keys are refused with 403 WEBSOCKET_PLAN_REQUIRED.
Billed per minute the socket is open, 20,000 CU a minute, from the same credits as your REST calls. Running out of credits closes the socket with code 1008.
This socket is billed on its own. Holding the thesis feed and the pump feed at once means two sockets and two meters.
Resolving on demand
POST /v2/user/handle/{handle}/resolve asks for a handle's wallet when FomoScan holds nothing for it yet, and waits for the answer. A handle already held comes back immediately.
When the answer is not ready in time you get a 202 instead of an error, with a reason that is one of queued, timeout, unavailable, rate_limited or not_ingested, all worth retrying, or no_preview, which is a property of the account and not worth retrying. Honour retryAfterSeconds rather than tight-looping.
Repeat calls for the same handle join the request you already have rather than starting a second one.
Billing
Every call costs compute units (CU) from your monthly allowance, at the price listed beside its endpoint above. Plan prices are published at partner.fomoscan.sh (opens in a new tab).
A miss still costs. A lookup that finds nothing is charged 200 CU.
A free key reveals wallets for a fixed sample set of accounts and nobody else. The interactive Swagger UI lists them. Those lookups cost nothing. Outside the set, a lookup that would return a wallet answers 403 SAMPLE_SET_ONLY. Profiles without a wallet still answer.
GET /v2/ws and GET /v2/ws/pump are metered per minute held open rather than per call, from the same credits as your REST calls. Each socket is billed on its own.
Errors that are FomoScan's fault or your client's fault — 401, 403, 429, 5xx — are never billed.
Your monthly allowance is a hard cap with no rollover. Once spent, calls return 402 QUOTA_EXCEEDED until the counter resets; topping up lifts that cap immediately. Wallet reveals draw on a separate monthly allowance; past it, reveal calls return 402 REVEAL_LIMIT_REACHED, which top-ups cannot lift. Check remaining units any time with the unbilled GET /v2/me.
Quota exceeded402
{
"error": { "code": "QUOTA_EXCEEDED", "message": "out of credits - update billing on https://partner.fomoscan.sh" }
}
404 NOT_FOUND
A lookup that finds nothing answers 404 with the code NOT_FOUND. On a handle or id lookup it means FomoScan holds no user under that handle or id. On a wallet lookup it means FomoScan holds no verified link from that address to a trader. It does not mean the subject is unknown to FOMO. Treat it as "no answer today," cache the negative briefly, and ask again later. A user we hold without a verified wallet answers 200 with both addresses null.
Error codes
Every error uses the same shape: { "error": { "code": "...", "message": "..." } }. A 429 additionally carries retryAfter in seconds.
FomoScan API error codes and their meaning
HTTP
Code
Meaning
400
VALIDATION_ERROR
A malformed handle, address, or query parameter.
401
UNAUTHORIZED
Missing or invalid API key.
402
QUOTA_EXCEEDED
Out of credits — top up at partner.fomoscan.sh.
402
REVEAL_LIMIT_REACHED
Monthly wallet-reveal allowance spent. Top-ups cannot raise it; upgrade the plan or wait for the period to reset.
403
FORBIDDEN_SCOPE
Your key is not provisioned for this endpoint.
403
SAMPLE_SET_ONLY
A free key asked for a wallet outside the sample set.
403
WEBSOCKET_PLAN_REQUIRED
Your plan has no WebSocket. It is included from Growth ($899), and legacy plans keep it.
404
NOT_FOUND
No answer for the handle, id or wallet you asked about, or no such route.
429
RATE_LIMITED
Per-minute limit exceeded; retry shortly.
503
OVERLOADED
We are shedding load. Nothing was charged; retry.
Rate limits
Each key has one per-minute request limit across every endpoint, readable from GET /v2/me as ratePerMinute, set by your plan:
FomoScan API rate limits by plan
Plan
Requests / minute
Explore (free)
60
Starter
150
Builder
300
Growth
600
Scale
1,200
Enterprise
per contract
A per-IP burst ceiling sits behind the plan limit as an anti-abuse backstop. Exceeding either returns 429 RATE_LIMITED with a retryAfter.
A thesis page can come back empty the first time a token is asked for. Ask the same endpoint again on your normal interval.
OpenAPI
Paste your key into the interactive reference and call any endpoint directly, or import the OpenAPI 3.1 document into Postman, Insomnia or your code generator.