Muup.fun
Open the app

Public API

Read-only, anonymous and CORS-open. Built for aggregators, wallets and explorers to pull a coin’s art and its launch metadata without an agreement, a key, or a conversation with us first.

# base URLhttps://api.muup.fun/api/public# live examplehttps://api.muup.fun/api/public/v1/tokens?chainId=8453&limit=3

Why this exists

An aggregator can show a launchpad’s badge and a coin’s image only if it can fetch that metadata from somewhere. On Solana it reads the Metaplex metadata URI straight off the token account. ERC-20 has no equivalent field — there is nowhere on the token to put a logo — so for an EVM launchpad the metadata has to come from an endpoint like this one.

Concretely: Muup.fun coins already appear on GMGN, but with a letter placeholder instead of the coin’s art and launchpad_platform reading Unknown. Those two fields are filled from a launchpad integration. This API is the half of it we control.

Endpoints

GET /v1/tokens

A page of launched coins, newest first.

QueryTypeDefaultNotes
chainIdintall chains5042 (Arc), 4663 (Robinhood), 8453 (Base), 988 (Stable)
limitint50capped at 200
cursorstring—nextCursor from the previous page

Pagination is cursor-based rather than offset-based. Launches arrive continuously at the head of this ordering, so an offset would make a crawler re-read rows it already had and skip others. Ordering is createdAt DESC, id DESC — the id tiebreak matters because coins minted in the same block share a timestamp.

The response

Trimmed to one coin. Every field below is present on every entry; nullable ones are marked in the notes that follow.

{  "launchpad": {    "id": "muupfun",    "name": "MUUP.FUN",    "url": "https://www.muup.fun",    "logoURI": "https://www.muup.fun/logo.png"  },  "tokens": [    {      "chainId": 8453,      "address": "0xb200000000000000000000dd0d5d410257337e18",      "name": "Broot",      "symbol": "BROOT",      "decimals": 18,      "totalSupply": "1000000000000000000000000000",      "logoURI": "https://gateway.pinata.cloud/ipfs/Qm...",      "description": "...",      "links": {        "website": null, "twitter": null, "telegram": null,        "launchpad": "https://www.muup.fun/token/0xb200...",        "explorer": "https://basescan.org/token/0xb200..."      },      "creator": "0x...",      "createdAt": "2026-09-02T00:00:00.000Z",      "market": {        "protocol": "uniswap-v4",        "poolAddress": null,        "poolId": "0xf3c5d706fe386aae3797a21c2cdf57d30b49312d...",        "positionId": "3038362",        "factoryAddress": "0x16e60002451ad549aea409ea2924a14f9bff5f2e"      },      "fees": {        "tradeFeeBps": 400,        "protocolFeeBps": 100,        "creatorTaxBps": 300,        "holderRewardsVault": null      },      "stats": {        "currency": "ETH",        "quoteAsset": null,        "quoteDecimals": 18,        "priceNative": "0.000000001866909775",        "marketCapNative": "1.866909775",        "liquidityNative": "0.000012851445252997",        "volume24hNative": "0",        "priceChange24h": null,        "holderCount": 0      }    }  ],  "nextCursor": "b1f0..."}

GET /v1/tokens/:chainId/:address

One coin, the same shape as an entry above. The address match is case-insensitive, so a checksummed address and a lower-cased one both resolve. An address this chain has never launched returns 404 — including an address that exists on a different chain, which is a 404 rather than a redirect.

GET /v1/tokenlist.json

The same coins as a tokenlist.org list — the format wallets and explorers ingest with no integration work at all. Accepts chainId.

Names and symbols are sanitised to the schema’s character set, and an entry is dropped when nothing usable survives. One unsanitised memecoin ticker would otherwise invalidate the whole list for a strict consumer.

Attributing a launch to us

market.factoryAddress is the field that says a coin came from Muup.fun. These are read from the same registry the apps resolve through, so this table cannot name a factory the product is not using, or miss one that has been switched on.

NetworkChain IDFactoryVenue
Arc50420x16e60002451ad549aea409ea2924a14F9BfF5f2eUniswap V4
Robinhood Mainnet46630x4a3F3917e5eF514f5682abFD3dDd2C6DA039935FUniswap V3
Robinhood Mainnet46630x35f120fE125Cd7D0630bb4D22B81D6b007FFaD21Uniswap V4
Base84530x16e60002451ad549aea409ea2924a14F9BfF5f2eUniswap V4
Stable Mainnet9880x42D0C82B794c19d5D607D7018E516b4070b27E8dUniswap V3

Notes for integrators

A V4 pool has no address

market.protocol is uniswap-v3, uniswap-v4 or bonding-curve. Every V4 pool lives inside one PoolManager singleton and is identified by poolId, the keccak of its pool key — there is no per-pool contract to watch. Exactly one of poolAddress and poolId is non-null. Anything keyed on pool address silently misses half the catalogue.

What a trade costs, and why it is not one number

A creator may add a trade tax of up to 10% on top of the platform’s 1%, chosen once at launch and never changeable afterwards. Most coins set none; some set several percent. So there is no single platform fee to hardcode, and fees.tradeFeeBps is the figure to show a trader.

FieldMeaning
tradeFeeBpsTotal the trader pays on the quote leg. The headline number
protocolFeeBpsOur cut, split with the creator
creatorTaxBpsThe creator’s own tax, paid entirely to them
holderRewardsVaultSet when this creator signed their whole fee share over to holders, irreversibly. Their tax is not part of that

Basis points of the trade — not Uniswap units, and not a share of the fee

Every figure here is bps of the quote leg of a swap: 400 is 4%. Uniswap’s own fee tiers are hundredths of a bip, so its 10000 tier is 100 here — reading one as the other is out by 100x. And these are not a share of the fee: a creatorFeeBps of 9000 elsewhere in this product means the creator keeps 90% of the fee, which is a different quantity entirely.

null means not known, never zero — 0 is a real answer and the common one for creatorTaxBps. A market we cannot price publishes nulls rather than a plausible default: the fee on a pool without our hook lives in that pool’s own immutable key, which we do not store per coin, and quoting the current default tier would misreport any coin launched under a different one. tradeFeeBps is null whenever either component is, because a sum with an unknown term is unknown rather than smaller.

Stats are in the quote currency, as decimal strings

Everything under stats is denominated in the market’s quote currency, named by stats.currency, and written as a decimal string — not wei, and not USD. Internally these are wei, which is right for our own UI and useless to anyone else: a market cap of ~1.87 ETH reads as 1867152374000000000 raw.

USD was rejected deliberately. It would freeze our price feed, and the moment it was sampled, into someone else’s cache; consumers already carry their own rates. totalSupply is the one exception and stays raw, pairing with decimals the way every ERC-20 explorer expects.

The quote is not always the chain's native asset

Since 5 September 2026 a Uniswap V4 market on Robinhood can be opened against a registered ERC-20 — the tokenised equities NVDA, TSLA, AAPL and others. When it is, priceNative, marketCapNative, liquidityNative and volume24hNative are all in that asset.

They are the same shape as an ETH figure, the same decimal string, and most of these assets carry ether’s 18 decimals too — so nothing in the numbers distinguishes them. Read stats.quoteAsset (the contract address, null for native) before valuing anything. Prefer it over stats.currency: symbols are chosen by whoever deployed the token and are not unique, and an asset our registry does not recognise publishes its address there rather than a symbol that would be confidently wrong. Assuming the chain’s native symbol prices an NVDA market at ether’s rate — roughly 11x out, with nothing in the payload looking wrong.

Stats are advisory

Aggregators normally recompute price and volume from chain data, and should. These figures are a convenience, not a source of truth. priceChange24h is null rather than zero when the window predates the data it needs — a flat market and an unanswered question are different readings.

Caching and rate limits

  • Responses are cached about 5 seconds and carry Cache-Control: public, max-age=5.
  • 120 requests per minute per IP on the token routes, 60 on the token list. Both report X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset on every response.
  • Access-Control-Allow-Origin: *. There is no key, no signup and no referer check.

Ask us for what is missing

This endpoint exists to be consumed. If a field you need is absent, or a shape here is awkward for your indexer, that is worth telling us — the schema is deliberately separate from the one our own UI uses, so it can change for you without touching the product.