https://api.basestonk.io - what BaseStonk’s own interface reads. No key
for reads, and nothing is charged: the API is free. The v4 accounting is already done; raw-chain integrations that
assume v2/v3 pairs read $0 liquidity.
Machine client? The same routes under /api/v1 add coded errors, one
envelope and the /prepare endpoints (AI agents).
The machine-readable reference is the OpenAPI 3.1 document at
https://api.basestonk.io/api/v1/openapi.json: every public route, 101
operations, generated from the same route declarations the server
registers, so it cannot list a route the server lacks or miss one it
serves. /api/v1/llms.txt is the plain-text version of the operations
tagged agents. Both are cached an hour. This page covers what an
integrator reaches for; the document has the rest (referral, bridge,
OAuth).
Two things in the document are for agents. The agent-tier operations
declare their security as agentBearer or agentOAuth (scope prepare),
and sixteen operations carry x-mcp-tools, naming the
MCP tools that call them - so the MCP server and this
reference are one description, not two.
The chain
?chain= on token and wallet routes (absent means base); a path segment
on venue routes. Wrong chain for a token is 404, never the other index.
Endpoints that exist on one chain only are marked.
Rate limits
Per client IP, cost-weighted. The sharedapi lane runs on a
five-minute window; the small lanes run per minute.
A signed agent bearer moves the
api lane onto your wallet; see
AI agents.
So a token page read costs 2,
limit=1000 costs 11, and an ecosystem
search costs 7.
Not metered at all, because a refused answer here would make an interface
show something false: /basket/offvault, /basket/usd, /basket/history,
/pairstates/{chain} and /pairs/{chain}, on both prefixes.
Responses carry x-ratelimit-limit, x-ratelimit-remaining and
x-bstonk-identity (ip or wallet). Exhausted:
Errors
Unversioned routes answer a sentence:The v1 envelope
Everything under/api/v1, including the limiter’s 429, answers errors
as one object:
message is the unversioned sentence. retryAfter rides along on a 429,
detail on a validation refusal, checkpointTx on a Robinhood 409.
action is present only for the codes below; branch on code, never on
message.
Any other refusal is coded as its message in snake case (for example
no_pair_registry_on_this_chain), so a new error is never uncoded.
Every v1 response also carries x-request-id (yours echoed if you send
one; quote it when reporting a problem) and x-bstonk-api-version: 1. A
non-GET echoes your Idempotency-Key.
Pagination
limit and offset, answered as { total, hasNext, <rows>: [...] }
(/tokens adds sort; /ecosystem has no hasNext, compare total).
Under /api/v1 the same body also gains items (the rows again) and
nextOffset (null on the last page).
Two routes page backwards instead: candles take
limit (300, max 1000)
and before=<unix seconds>; a wallet’s trades take limit and
before=<cursor> and hand back the next cursor as nextBefore.
Responses evolve additively. Ignore unknown fields. taxBps is
backfilled for pre-V6 launches whose buyTaxBps/sellTaxBps are null;
treat it as both directions.
Endpoints
Tokens
sort (trending age marketcap volume holders), dir,
q, pair (an address, or crypto / memes / stocks), generation
(v1..v6 simple b20), features (comma-separated AND of
platform og rewards buyback auto-liquidity simple advanced),
addresses (up to 50 - a watchlist in one call). pair also takes up to
12 addresses joined by commas. view=list returns only the fields a list
row draws; tokens carrying an operator notice are left off the shelf unless
you pass flagged=1, q or addresses. Cached 5 seconds.
other. Cached 60 seconds.
{ "token": {...} }. Add tx=<launch hash> and a token not
yet indexed is indexed from that receipt on the spot.
{ interval, candles: [{ t, o, h, l, c, v }] }, oldest first, t in unix
seconds. interval: 1s 1m 5m 15m 1h 4h 1d (default 5m);
anything else is 400 bad interval. limit is 300 by default, 1000 at
most. 1s is built from the trades themselves; 1m to 15m are rolled up
from stored one-minute bars, 1h and wider from hourly ones.
before=<unix seconds> pages backwards through history; an empty page is
the start of it. The newest bar is marked to the token’s current price, and
a token that has never traded gets flat zero-volume bars at that price.
trader= (a whole address) and side=
(buy or sell). Holders are largest first and take q= (0x plus four
or more hex characters, matched as a prefix). Pressure is the momentum
panel: buys, sells, volume each way, distinct buyers and sellers and the
price change, over 5m 1h 4h 24h.
Wallets
chain, and return the largest 100.
Creator tokens add volumeAllUsd and creatorShareBps (this wallet’s own
share, null when the hook could not be read). Positions are the
portfolio’s PnL rows (entry, holding, realised, unrealised) and take
token= to narrow, which also returns that token’s trades.
A wallet’s trades are its activity feed, newest first:
The answer is
{ trades: [...], nextBefore }. Each row carries token,
symbol, name, imageUrl, side, amountToken, volumeUsd,
priceUsd, txHash and createdAt, priced as the trade was stamped.
A page never holds more than limit rows. The cursor marks the last row
by its time to the microsecond and its id, so trades that share a block
split across pages with none lost or repeated. nextBefore is null when
there is nothing older. Treat it as opaque: a cursor that does not decode
is 400 invalid before. A bare ISO time is still accepted, for clients
holding one from before the cursor, and pages from that instant.
Rewards are dividends received across every token, or on one token with
the live pending amount (404 if the token pays none; pending is null
when the distributor could not be read, never a guessed zero; cached
privately 10 seconds).
profile: null.
Pairs and pricing
pairusd is { usd }, USD per pair token from the registry the launcher
prices with, or 503 when nothing can price it. The batch form is
{ prices: { address: usd | null } } and takes up to 100; more is a 413,
never a trimmed answer. paircheck answers whether an address can be
launched against right now (hasMarket needs $2,500 of depth on Base) and
names any namesake risk; cached 10 minutes on Base and Arc, 1 minute on
Robinhood Chain. pair-identity resolves symbol, name and artwork for any address,
curated or not; cached 5 minutes.
pairs is every pair a launch can be priced against, as one priced list:
{ chain, at, total, rows }, each row with address, symbol, tags,
priceUsd, liquidityUsd, a light (green amber red) and a state
(ready no-lp unpriced wakeable). q filters by name, symbol or
address, tag by tag, limit defaults to 2000 (max 5000). Cached 30
seconds. pairstates is the pair registry’s answer for every registered
pair on a chain that has one (Robinhood Chain and Arc; Base answers 400):
{ chain, at, states: { address: "priced" | <refusal> } }, cached 20
seconds.
ecosystem is the chain’s pair catalogue. On Base, eco (clanker
virtuals bankr) browses one catalogue and absent browses all three;
on Robinhood Chain it is the 194 stocks; on Arc it is empty. q searches name, symbol or
address. Browsing Base lists priced rows only. Cached 30 seconds.
basket-assets is the dividend-basket menu - registered
(the curated set, with category, launchable, needsIssuance) plus
ecosystem (ranked, paged). gatedroute returns the gate-verified route,
issuerFactory (zero for a creator-chosen pair) and usdPerPair for
any address with a market - what launchGated takes. A route that
cannot be built is a 422 naming the gate’s refusal. Cached 60 seconds.
The basket
rounds is every payout round
across the current and retired vault, numbered as one series (cached 30
seconds, 503 with retry-after while unreadable). vault adds the
per-round detail and, with wallet=, that wallet’s receipts. holdings
is what the vault holds now (holdings: null means not read yet, never an
empty vault; cached 15 seconds).
The last three are records the keeper writes, unmetered and on both
prefixes: usd is what each round was worth when paid, history is the
retired vault’s rounds as they stood ({ vault, frozenAt, rounds }), and
offvault is payouts routed around the vault, where the chain records one
recipient for a round that paid many ({ records: [{ round, asset, symbol, holders, total, at }] }).
Venue
stats is that chain’s tokens, trades, volume, holders, revenue and
basketPaid, plus a venue block summed across every chain
(venue.aggregated names the summed fields; $BSTONK’s burn is
deliberately not one). burn is the $BSTONK burn total; history is the
daily series.
Launchpads compared
source names the accounting on
every row and a null is a figure no source publishes, never a zero.
history returns every venue’s daily rows for the last days (1-365) so
the ratios can be charted over time. Cached five minutes at the edge. The
same table drives the Dune dashboard and
the MCP tool get_platform with include: ["comps"].
Quote the ratios, not the raw volume. Volume rewards the biggest venue; fees
or volume per dollar of market cap is the measure on which a small venue can
be shown to be doing more with less - and on which BaseStonk is not first on
every day, which is exactly why the row that beats it stays in the table.
Launch presets
https://basestonk.io/create?template=reppo-datanet (add name= and
symbol= to prefill those too). The response is the preset with its payee
addresses resolved - pair, buy/sell tax, the partner’s payee and its minimum
share of the creator fee, the minimum dev-buy lock, the anti-sniper window and
the holder limit - plus ready. When ready is false, missing names the
server setting the partner has not supplied yet and the form opens plain.
An unknown id is a 404. Cached 60 seconds.
The form fixes the pair and the taxes, locks the partner’s payee row at its
floor, and refuses to launch below the minimum lock. The creator signs in
their own wallet as with any launch; nothing about a preset touches the API
with a key. A wallet calling the launcher directly is bound only by the
launcher - the preset is a promise the form keeps, not a rule the chain does.
After the launch, back to the partner. A preset can name its partner’s next
step, and the success screen then leads with Continue on , the
token page one tap below it. The partner can set the destination per link
with next=, using the placeholders {token}, {chain}, {symbol}, {name}
and {tx}:
next= is honoured only for an https URL on the partner’s own host or one
of its subdomains; anything else falls back to the preset’s own destination,
so a link cannot send a creator somewhere else. URL-encode the value.
The
draft_launch MCP tool takes the same template.
Writes
images pins a file field (PNG, JPEG, WebP or GIF, up to 5MB) and
metadata pins a token’s metadata document; both answer with uri and
gateway and spend the uploads lane. tokens/{address}/metadata is the page
controller’s edit of description, image and links, merged onto what is
shown; controller hands the page to { "to": "0x…" }. stored serves an
upload IPFS did not take.
Each write accepts either proof of the wallet:
When
x-wallet-address is present the signed headers are what is checked.
A bearer buys no extra upload budget: the uploads lane stays per IP.
Live updates
403.
The first frame is { "type": "hello", "epoch": "…", "seq": 1234 }. Then
subscribe (at most 50 topics per socket):
Addresses are lowercase; intervals are the candle intervals above.
ping answers { "type": "pong" }. The site pings every 30 seconds and
treats a missing pong as a dead socket; the server’s idle timeout is two
minutes. A message that fails validation closes the socket (code 1008),
as does a 51st topic. Up to 12 sockets per IP.
Resuming
Every broadcast frame carriesseq, which rises within one server process;
epoch names the process. Remember the last seq you handled. On
reconnect, if the new hello has the same epoch, resubscribe with
where you were:
seq on your topics (it holds
up to the last two minutes), then sends { "type": "resumed", "replayed": n }.
If it cannot cover the gap it sends { "type": "resync" }: refetch over
REST, as after any reconnect without since. A different epoch means a
new process; subscribe without since and refetch. hello, pong,
resumed and resync carry no seq. Drop any frame whose seq you have
already handled.
Reorgs
On Base a trade reaches the feed and the chart at the head of the chain, usually within a second of its block, and is not final there. A confirming pass two blocks behind the head re-reads each window against the block hashes the rows were stored under. When a block was replaced, every row from it onward is removed (trades, transfers, fees), the candles, holder balances and token stats built from them are rebuilt, and the chain is read again. Each token touched getstoken.touched on its token: topic and on every
candles: topic for it. Refetch on that event, and do not treat a trade
row as settled until your own node has it at the depth you need.
Images
img lane, not api. Artwork is served cross-origin, and a
rendered image is cached as immutable; a card is cached 5 minutes.
Eligibility is the chain’s word, not this cache’s. On-chain vetting and rebuild rules: on-chain page.

