Chain id 56 · schema version 1 · index verdict serving — block 128511955, 4 behind the head, 0 open gap(s).
Four things and no fifth: discovery (what launched), quote (what a trade returns), events (what happened), candles (what to draw). No write endpoints, no keys, no accounts, and no trade construction on the server.
| Base | /api/v1 |
|---|---|
| Versioning | In the path. v1 never changes shape; fields are added, never repurposed. A breaking change is v2. |
| Chain | Every response carries chainId. A client that does not check it is a client that will trade the wrong chain. |
| Amounts | Decimal strings of base units, never JSON numbers — a uint256 does not fit in a double. |
| Times | RFC3339 UTC and blockNumber: a bot reconciles on blocks, a human reads dates. |
| Errors | {"error":{"code","message"}}. Codes are stable strings; messages are not. |
| Rate limit | 60 requests a minute per IP, across the whole of v1. X-RateLimit-* headers; 429 carries retry-after. |
| CORS | * on every GET. These are public reads. |
source | indexer or chain — see below. |
source means, exactlyA pool's structure — the full poolKey, the opening window, the fee
split, the coin's name — is always a chain read; the index holds events, and a pool key
is state. source names where the market figures came from: 24-hour
volume, trade count, holders and last price. When it says chain, the
market object on each pool is null rather than zero — an absent
figure and a zero figure are different facts.
The new-launch feed. Cursor-paged, never offset-paged: a launch arriving between two pages would shift every later row by one, and an offset-paged consumer would silently skip a coin.
GET /api/v1/pools?order=created_desc&limit=50
GET /api/v1/pools?created_after=2026-09-18T00:00:00Z
GET /api/v1/pools?quote=0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c
GET /api/v1/pools/{poolId}
order | created_desc (default) or created_asc |
|---|---|
limit | 1–200, default 50 |
cursor | Opaque, from the previous nextCursor. A cursor this endpoint did not issue is a 400; a cursor whose row has since gone is an empty page. |
created_after | RFC3339. Requires the index; coins with no indexed launch time are excluded rather than assumed recent. |
quote | Quote asset address |
Cached 12 s at the edge. /api/v1/pools/{poolId} adds live
state and the hook's fee buckets, with accrued and paid kept apart — they are
different facts and summing them answers nothing.
opening.perWalletCap (PurchaseCapExceeded) in the pool's
first two blocks with trades, counted from its first public trade, however long
that takes: waiting does not lift it, trading does. opening.servedBlocks is the
hook's own count and opening.capBinding is true until it reaches 2. It refuses
entirely before opening.openAtSecond (PoolNotOpenYet; zero on every
ordinary coin). A creator's own pre-buy at launch is exempt and does not start the window.
A sniper sizing off pool liquidity alone gets a reverted transaction and files the coin under
"rug".opening.capEndBlock
and opening.openAtBlock are now always null. The window no longer ends
at a block known in advance, so there is no number to publish.A simulation, not a formula, against
0xd0737C9762912dD34c3271197E362Aa736Df0926 — PancakeSwap's own CLQuoter, named in
quotedVia so you can re-run the identical call yourself.
GET /api/v1/quote?poolId=0x…&side=buy&amountIn=10000000000000000 GET /api/v1/quote?coin=0x…&side=sell&amountIn=1000000000000000000&referrer=0x…
amountIn / 101 — which is 0.990% of the
gross input, and the same again on the way out of a sell: a round trip costs
2.01% of the stake. This is charged on top of
poolKey.fee (0.01%), which is why hookFeeBps: 100 is published on
every pool. A router that reads only poolKey.fee and does closed-form maths
quotes 1% high, and its slippage guard reverts the trade. Use
amountOut from this endpoint; it is the simulated number and it already has the
fee taken out. hookFee.amount is derived: true — the documented rule
applied to your input, not a second simulation.hookData, so no referrer is credited and the referrer's share
falls to the creator — the feeSplit returned reflects that fold.
Feast's platform share is unaffected by who routed the trade. Pass
?referrer=0x… to price the trade you would actually send.hookData: the referrer's address, abi.encode(referrer).
Send empty bytes when nobody referred the trade. The 64-byte
abi.encode(referrer, wallet) form still parses but binds nobody; there is no
reason to send it. A referrer named this way is paid for that trade only.
A wallet that has bound a referrer in the FeastReferrals registry — by its own
call, or by its own EIP-712 signature relayed for it — pays that referrer on every trade it
originates, and the hook does not read hookData for it; feeSplit here
is the split for an unbound wallet.A reverted simulation is a 200 with a named refusal, not an
error: it is a true answer to "what would this trade do".
PurchaseCapExceeded carries retryAfterBlock: once the window's two
blocks have traded, a buy in any block after it is uncapped. While fewer than two have traded,
the cap lifts after the next block somebody trades in successfully, which nobody can
name yet, so retryAfterBlock is null and opening.capBinding
is true. A buy under perWalletCap goes through and counts its block like any
other.
Exact-output quotes (amountOut=) are not in v1 and are refused
by name rather than silently treated as exact-in.
One ordered stream — launches, trades and fee rows — filterable and replayable. Every
event carries txHash + logIndex, which is its identity;
cursor is opaque and monotonic, and since_cursor is
exclusive.
GET /api/v1/events?types=launch,trade,fee&limit=200 GET /api/v1/events?poolId=0x…&types=trade&since_cursor=… GET /api/v1/events?types=window&limit=200
Ordered by (blockNumber, logIndex), ascending. Every event carries
depth — final, confirmed or tip — because a
tip row may still unwind, and it is served labelled rather than withheld or served silently.
Fee events carry settled: accrued and paid are different facts.
types=window is the FEAST sale's launch window, served only when named: no
types means launch,trade,fee. A window event's kind is the
contract's event — Committed, Withdrawn, Settled,
Claimed or Refunded — beside account, amount
and amountAsset: coin on a claim, which pays FEAST, and
quote on the other four. total is the pot a commit, a withdrawal or
the settlement states. The settlement also carries sold, the FEAST tranche sold,
and clearingSqrtPriceX96. A window event names no coin and no pool, so a
coin= or poolId= page has none.
Requires the index; there is no chain fallback, because the chain reads would give a sequence with holes in it under a cursor that claims completeness — and missing events look exactly like a quiet market.
The newest fee payouts, newest first — the tail the stream deliberately has no cursor for.
A payout has settled: FeeAccrued and ReferralCredited
are money still in the pool and are on /events, not here.
GET /api/v1/payouts?limit=6 GET /api/v1/payouts?coin=0x…&limit=20
Ordered by (blockNumber, logIndex), descending, and bounded at
50. No cursor: there is nothing after the newest row to resume from, and a consumer that wants
to walk the whole ledger has /api/v1/events, which is ascending and resumable.
Each row carries seat — creator, referrer,
house or burn — and amountAsset, which says whether
amount is in the pool's quote (five of the six kinds) or in the coin
itself (FilledCoinBurned). Read it: the two are different tokens.
Requires the index; there is no chain fallback, because no chain read answers "the last six payouts across every pool" without the walk the index exists to prevent.
Candles, in GeckoTerminal's own row shape: [ts, o, h, l, c, v], ts
in unix seconds. Anyone who has written a GeckoTerminal client has written a Feast client.
GET /api/v1/ohlcv?poolId=0x…&timeframe=minute&aggregate=5&limit=300
timeframe/aggregate: minute 1/5/15,
hour 1/4, day 1. An unsupported pair is refused rather than rounded
to the nearest one — a chart drawn on a silently different bucket disagrees with its own axis.
The weekly settlement artifact, once FeastEmissions.settle(n) has run for
that week: fees per quote asset, FEAST emitted and burned, the three tracks' pots and
shares, and who claimed. Every figure carries its source — the contract, the
block, and the event or function it came from — because this is a claim about money made
to people who were not in the room.
GET /api/v1/announcements/2958
A week that has not settled is a 404, never a document full of zeroes: before settlement every pot is zero, and publishing that would read as a quiet week rather than as a job that has not run. A settled week is immutable, so the artifact is built into the deployment and cached for an hour.
to/data/value. It looks helpful and makes us a trusted party in your transaction. poolKey is returned in full because PancakeSwap's Universal Router takes that struct verbatim — you can build the call yourself, and a Feast pool needs no adapter.