# BStocks Launchpad: full API reference > BStocks Launchpad launches tokens on Base that trade against a Coinbase tokenized stock (NVDAc, TSLAc, AAPLc and the rest) in a permanently locked Uniswap v4 pool. Every token has a fixed supply of 1,000,000,000, opens at the same valuation priced from the stock's Chainlink feed, and has no admin. Every swap pays a 1% fee in the stock: 70% to the token's creator, 30% to the platform. ## Conventions - Base URL: https://launchpad.basestocks.finance/api · JSON in and out · Base mainnet (8453) only - Keys: none · no API key and no login · the one cookie is the visitor's eligibility answer - Amounts: integer strings in the smallest unit: a stock has 8 decimals (1 NVDAc = 100000000), a launched token 18 - Addresses: any case in, lowercase out - Errors: { error: { code, message, details? } } with a 4xx or 5xx status · 429 carries retry-after · 451 means the eligibility answer is missing - Signing: never on the server · /api/tx returns calls for the visitor's own wallet, which signs and sends them - From a browser: another site's page may call the API only when its origin is on the partner list · a server may call any route, but then the limits and the eligibility rule apply to the server, not to each visitor - Limits per caller, a minute: 120 quotes, 30 transaction builds, 120 token reads, 60 wallet reads. Over the limit: 429 with retry-after. - Eligibility: from a restricted country (the United States), POST /api/quote, /api/metadata and /api/tx/* answer 451 REGION_RESTRICTED until the visitor confirms they do not live in the United States and are not a US citizen or resident (POST /api/region, or the header `x-bstocks-eligibility: confirmed` sent after your own checkbox). Never send the header without asking. - Sending: hand every item of `calls` to the user's wallet in order (`to`, `data`, `value` as a decimal string of wei). An approval comes first when the allowance is short. The deadline is ten minutes; ask again if the approval took longer. ## Quick start ### A trade ```js // 1. Ask for the calls. amountIn is in the input's smallest unit: the stock for a buy, the token for a sell. const res = await fetch('https://launchpad.basestocks.finance/api/tx/swap', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ token, side: 'buy', amountIn: '100000000', account, slippageBps: 100, builderCode: 'bc_yourcode' }), }); const tx = await res.json(); if (tx.error) throw new Error(tx.error.message); // 2. The visitor's wallet sends them in order: the approval first, when there is one. // The deadline is ten minutes; if the approval takes longer, ask again before the swap. for (const call of tx.calls) { const hash = await walletClient.sendTransaction({ account, to: call.to, data: call.data, value: BigInt(call.value) }); await publicClient.waitForTransactionReceipt({ hash }); } ``` ### A launch ```js // 1. Pin the image and profile to IPFS. The answer is the token's contractURI. const form = new FormData(); form.set('name', 'My Token'); form.set('symbol', 'MYT'); form.set('description', 'What it is about'); form.set('image', file); const { contractURI } = await (await fetch('https://launchpad.basestocks.finance/api/metadata', { method: 'POST', body: form })).json(); // 2. Ask for the launch calls. The account that sends them is the creator and earns 70% of every fee. const tx = await (await fetch('https://launchpad.basestocks.finance/api/tx/launch', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ account, name: 'My Token', symbol: 'MYT', contractURI, stock, builderCode: 'bc_yourcode' }), })).json(); // 3. Send them in order, then open tx.tokenUrl. The token lands at tx.predictedToken. for (const call of tx.calls) { const hash = await walletClient.sendTransaction({ account, to: call.to, data: call.data, value: BigInt(call.value) }); await publicClient.waitForTransactionReceipt({ hash }); } ``` ## Markets and tokens Read what the indexer recorded: tokens, prices, trades, candles, holders and wallets. Every figure comes from confirmed events or a live pool read. ### GET /api/markets List markets. Every launched token with its price, FDV, 24-hour volume and change, newest first or by volume. (partner browsers allowed) Parameters: - `stock` (query, address, optional): Only tokens paired with this stock. - `creator` (query, address, optional): Only tokens this address launched. - `q` (query, string, optional): Search name or symbol, up to 64 characters. - `limit` (query, integer 1..200, optional) (default 50): Rows to return. - `offset` (query, integer 0..10000, optional) (default 0): Rows to skip. - `orderBy` (query, enum one of newest | volume24h, optional) (default newest): Sort order. Returns: { markets: Market[], asOf } · asOf is when the indexer last advanced Errors: 400 INVALID_QUERY, 400 INVALID_STOCK, 400 INVALID_CREATOR ```sh curl 'https://launchpad.basestocks.finance/api/markets?limit=5' ``` ### GET /api/stocks List quote stocks. The Coinbase tokenized stocks a token can pair with, with the latest Chainlink price, feed status and number of launches. (partner browsers allowed) Returns: { stocks: Stock[] } Errors: 503 STOCKS_UNAVAILABLE ```sh curl 'https://launchpad.basestocks.finance/api/stocks' ``` ### GET /api/tokens/{address} Get one token. The market row with fees, lifetime figures, pool reserves and links. A launch that is confirmed but not indexed yet answers status "indexing", read from its factory. (partner browsers allowed · 120/min per caller) Parameters: - `address` (path, address, required): The launched token. Returns: { status: "indexed", market, details, launch, profile } | { status: "indexing", launch } Errors: 400 INVALID_ADDRESS, 400 INVALID_QUERY, 404 TOKEN_NOT_FOUND, 429 RATE_LIMITED ```sh curl 'https://launchpad.basestocks.finance/api/tokens/0xb20000000000000000000023b657130129ad33e5' ``` ### GET /api/tokens/{address}/swaps List trades. A token's swaps, newest first, with the creator's own trades flagged. Page back with the block and log index of the last row. (partner browsers allowed · 120/min per caller) Parameters: - `address` (path, address, required): The launched token. - `limit` (query, integer 1..200, optional) (default 50): Rows to return. - `before` (query, integer, optional): Only swaps before this block. - `beforeLog` (query, integer 0.., optional): With before: the log index within that block. Returns: { token, stock, stockUsd, swaps: Swap[] } Errors: 400 INVALID_ADDRESS, 400 INVALID_QUERY, 404 TOKEN_NOT_FOUND, 429 RATE_LIMITED ```sh curl 'https://launchpad.basestocks.finance/api/tokens/0xb20000000000000000000023b657130129ad33e5/swaps?limit=10' ``` ### GET /api/tokens/{address}/candles Get candles. OHLCV in stock units per bucket, each with the stock's USD price that was live when it printed. (partner browsers allowed · 120/min per caller) Parameters: - `address` (path, address, required): The launched token. - `bucket` (query, enum one of 1 | 5 | 15 | 60 | 240 | 1440, optional) (default 1): Bucket width in minutes. - `from` (query, string, optional): ISO date: first bucket. - `to` (query, string, optional): ISO date: last bucket. - `limit` (query, integer 1..2000, optional) (default 500): Buckets to return. Returns: { token, interval, quote: { symbol, usd }, candles: { time, open, high, low, close, volumeStock, volumeToken, trades, stockUsd }[] } Errors: 400 INVALID_ADDRESS, 400 INVALID_QUERY, 404 TOKEN_NOT_FOUND, 429 RATE_LIMITED ```sh curl 'https://launchpad.basestocks.finance/api/tokens/0xb20000000000000000000023b657130129ad33e5/candles?bucket=60&limit=24' ``` ### GET /api/tokens/{address}/holders List holders. Balances ranked, with the pool, the creator and burned dust labelled, and how concentrated the supply is. (partner browsers allowed · 120/min per caller) Parameters: - `address` (path, address, required): The launched token. - `limit` (query, integer 1..500, optional) (default 100): Rows to return. Returns: { token, holderCount, concentration, holders: { rank, address, label, balance, sharePercent }[] } Errors: 400 INVALID_ADDRESS, 400 INVALID_QUERY, 404 TOKEN_NOT_FOUND, 429 RATE_LIMITED ```sh curl 'https://launchpad.basestocks.finance/api/tokens/0xb20000000000000000000023b657130129ad33e5/holders?limit=10' ``` ### GET /api/tokens/{address}/image Get the token image. The image bytes from this site's own origin, at most 5 MB. Link it with ?v= as the market row gives it: a matching v on an ipfs:// image is cached for good. (same-origin in browsers) Parameters: - `address` (path, address, required): The launched token. - `v` (query, string, optional): First 12 hex of the image URI's sha256. Returns: image bytes Errors: 400 INVALID_ADDRESS, 404 TOKEN_NOT_FOUND, 404 NO_IMAGE, 413 IMAGE_TOO_LARGE, 415 NOT_AN_IMAGE, 502 IMAGE_UNREACHABLE ```sh curl 'https://launchpad.basestocks.finance/api/tokens/0xb20000000000000000000023b657130129ad33e5/image' ``` ### GET /api/tokens/{address}/dex-paid DEX Screener paid status. Whether the token has a paid DEX Screener profile: approved, pending, none or unavailable. Cached for five minutes; 20 calls a minute per caller. (same-origin in browsers) Parameters: - `address` (path, address, required): The launched token. Returns: { status } Errors: 400 INVALID_ADDRESS, 429 RATE_LIMITED ```sh curl 'https://launchpad.basestocks.finance/api/tokens/0xb20000000000000000000023b657130129ad33e5/dex-paid' ``` ### GET /api/tokens/{address}/profile Get the creator profile. The creator-signed profile of a fixed-profile token: description, image, website, X, Telegram. Null when the creator never signed one. (same-origin in browsers) Parameters: - `address` (path, address, required): The launched token. Returns: { profile: { description, imageUri, website, twitter, telegram, signer, updatedAt } | null } Errors: 400 INVALID_ADDRESS ```sh curl 'https://launchpad.basestocks.finance/api/tokens/0xb20000000000000000000023b657130129ad33e5/profile' ``` ### POST /api/tokens/{address}/profile Update the creator profile. Multipart: a payload field with the EIP-712 TokenProfile the creator signed, and the image whose keccak256 it names. Stored only when the signer is the launch creator. A token with an editable profile changes it onchain instead (409). (same-origin in browsers) Parameters: - `address` (path, address, required): The launched token. - `payload` (form, string, required): JSON: signer, signature, description, website, twitter, telegram, imageHash, issuedAt. - `image` (form, file, optional): The new image; its keccak256 must equal imageHash. Returns: { ok: true, ... } Errors: 400 INVALID_FORM, 400 INVALID_PAYLOAD, 400 INVALID_FIELDS, 409 ONCHAIN_PROFILE, 4xx from the signature check ```sh curl -X POST 'https://launchpad.basestocks.finance/api/tokens/0xb20000000000000000000023b657130129ad33e5/profile' \ -F 'payload={…signed…}' \ -F image=@logo.png ``` ### GET /api/wallet/{address} Get a wallet. What an address launched, holds, earned as a creator and can claim now, with its recent trades. (partner browsers allowed · 60/min per caller) Parameters: - `address` (path, address, required): Any wallet. Returns: { wallet, created, holdings, holdingsUsd, claimable, claimableUsd, recentSwaps, ... } Errors: 400 INVALID_ADDRESS, 429 RATE_LIMITED, 503 WALLET_UNAVAILABLE ```sh curl 'https://launchpad.basestocks.finance/api/wallet/0x1111111111111111111111111111111111111111' ``` ### GET /api/activity Activity feed. Launches and swaps as one feed, newest first. Poll it to follow the launchpad; there is no webhook. (partner browsers allowed) Parameters: - `limit` (query, integer 1..200, optional) (default 50): Rows to return. - `token` (query, address, optional): Only this token. - `actor` (query, address, optional): Only this trader or creator. Returns: { items: { kind: "launch" | "swap", at, txHash, token, name, symbol, ... }[], asOf } Errors: 400 INVALID_QUERY, 400 INVALID_TOKEN, 400 INVALID_ACTOR, 503 ACTIVITY_UNAVAILABLE ```sh curl 'https://launchpad.basestocks.finance/api/activity?limit=10' ``` ### GET /api/stats Platform totals. Launches, traders, swaps, volume and fees, with the fees and volume per stock. (same-origin in browsers) Returns: { launches, creators, traders, swaps, holders, volumeUsd, feesUsd, volumeByStock, feesByStock, topCreators, asOf, ... } Errors: 503 STATS_UNAVAILABLE ```sh curl 'https://launchpad.basestocks.finance/api/stats' ``` ### GET /api/names Resolve Basenames. Base names for up to 100 addresses at once, memoised on the server. (same-origin in browsers) Parameters: - `a` (query, string, required): Comma-separated addresses. Returns: { names: { [address]: name | null } } ```sh curl 'https://launchpad.basestocks.finance/api/names?a=0x1111111111111111111111111111111111111111' ``` ## Trading and launching Quote a trade, pin a profile, and get the exact calls a wallet sends to trade or launch. Nothing here signs or sends a transaction. ### GET /api/launch-config Launch configuration. The factory, hook and router new launches use, the builder code, the deadline and the form limits. The creation fee and opening valuation are left out on purpose: read them from the factory right before the wallet opens, or let POST /api/tx/launch do it. (partner browsers allowed) Returns: { chainId, factory, hook, router, deployBlock, builderCode, deadlineSeconds, limits, urls } Errors: 503 NOT_CONFIGURED ```sh curl 'https://launchpad.basestocks.finance/api/launch-config' ``` ### POST /api/quote Quote a trade. An exact-input quote from the Uniswap v4 Quoter against the token's own pool, including a launch that is confirmed but not indexed yet. (partner browsers allowed · 120/min per caller · eligibility rule applies) Parameters: - `token` (body, address, required): The launched token. - `side` (body, enum one of buy | sell, required): buy spends the stock, sell spends the token. - `amountIn` (body, uint, required): Input in its smallest unit: 8 decimals for a stock, 18 for a token. Returns: { amountIn, amountOut, feeBps, midPrice, executionPrice, priceImpactPercent, poolKey, zeroForOne, gasEstimate, liquidity } Errors: 400 INVALID_BODY, 404 TOKEN_NOT_FOUND, 409 NO_LIQUIDITY, 429 RATE_LIMITED, 451 REGION_RESTRICTED, 503 NOT_CONFIGURED ```sh curl -X POST 'https://launchpad.basestocks.finance/api/quote' \ -H 'content-type: application/json' \ -d '{"token":"0xb20000000000000000000023b657130129ad33e5","side":"buy","amountIn":"100000000"}' ``` ### POST /api/tx/swap Build a swap. The calls for one exact-input trade, for the account that will send them: an approval of exactly amountIn to the token's router when the allowance is short, then swapExactIn with the minimum output and a ten-minute deadline. The swap is simulated when no approval is needed. (partner browsers allowed · 30/min per caller · eligibility rule applies) Parameters: - `token` (body, address, required): The launched token. - `side` (body, enum one of buy | sell, required): buy spends the stock, sell spends the token. - `amountIn` (body, uint, required): Input in its smallest unit. - `account` (body, address, required): The wallet that sends the calls and pays the input. - `recipient` (body, address, optional): Who receives the output. Defaults to account. - `slippageBps` (body, integer 10..500, optional) (default 100): Tolerance below the quote, in basis points. - `builderCode` (body, string, optional): Your ERC-8021 builder code. It goes on every call beside the launchpad's, so the transaction is attributed to both. Returns: { calls: { to, data, value, description }[], quote, approval, deadline, expiresAt, simulation, router, tokenIn, tokenOut } Errors: 400 INVALID_BODY, 400 INVALID_AMOUNT, 404 TOKEN_NOT_FOUND, 409 NO_LIQUIDITY, 429 RATE_LIMITED, 451 REGION_RESTRICTED, 502 TX_FAILED, 503 NOT_CONFIGURED ```sh curl -X POST 'https://launchpad.basestocks.finance/api/tx/swap' \ -H 'content-type: application/json' \ -d '{"token":"0xb20000000000000000000023b657130129ad33e5","side":"buy","amountIn":"100000000","account":"0x1111111111111111111111111111111111111111"}' ``` ### POST /api/metadata Pin a token profile. Multipart: pins the image and the ERC-7572 document to IPFS and returns the contractURI a launch takes. With token, it pins a new profile for an editable token, keeping its name and symbol. 10 pins an hour per caller. (partner browsers allowed · eligibility rule applies) Parameters: - `name` (form, string, required): 1 to 64 characters. - `symbol` (form, string, required): A to Z and 0 to 9, up to 16. - `description` (form, string, optional): Up to 1,000 characters. - `website` (form, string, optional): An https link. - `twitter` (form, string, optional): An X handle or x.com link. - `telegram` (form, string, optional): A Telegram handle or t.me link. - `image` (form, file, optional): PNG, WebP, JPEG or GIF, up to 2 MB. - `token` (form, address, optional): An editable token to pin a new profile for. Returns: { contractURI, imageUri, metadata } Errors: 400 INVALID_FIELDS, 400 IMAGE_INVALID, 409 PROFILE_FIXED, 409 PROFILE_LOCKED, 429 RATE_LIMITED, 451 REGION_RESTRICTED, 502 UPLOAD_FAILED ```sh curl -X POST 'https://launchpad.basestocks.finance/api/metadata' \ -F 'name=Example Token' \ -F 'symbol=EXMPL' \ -F image=@logo.png ``` ### POST /api/tx/launch Build a launch. The calls that launch a token from the account: an approval of exactly stockIn to the factory when a buy at launch needs one, then launchWithOptions or launchAndBuy with the creation fee as value. The account is the creator and earns 70% of every fee. Send the same salt to keep the same token address. (partner browsers allowed · 30/min per caller · eligibility rule applies) Parameters: - `account` (body, address, required): The creator's wallet, which sends the calls. - `name` (body, string, required): 1 to 64 bytes. - `symbol` (body, string, required): A to Z and 0 to 9, up to 16. - `contractURI` (body, string, required): ipfs://, as POST /api/metadata returns it. - `stock` (body, address, required): The stock it trades against. - `metadataEditable` (body, boolean, optional) (default false): Let the creator point the token at a new profile later. Needs a bare-CID contractURI. - `salt` (body, bytes32, optional): Fixes the token address; random when absent. - `buy` (body, object, optional): A buy for the creator in the same transaction. - `stockIn` (body, uint, required): Stock to spend, 8 decimals. - `toleranceBps` (body, integer 50..500, optional) (default 200): How far the opening price may move before the launch reverts. - `acknowledgeShare` (body, boolean, optional): Required once the buy is 15% of the supply or more. - `builderCode` (body, string, optional): Your ERC-8021 builder code. It goes on every call beside the launchpad's, so the transaction is attributed to both. Returns: { calls, functionName, predictedToken, salt, creationFee, openingFdvUsd8, buy, approval, deadline, expiresAt, simulation, tokenUrl } Errors: 400 INVALID_BODY, 400 UNKNOWN_STOCK, 409 STOCK_NOT_ENABLED, 409 BUY_TOO_LARGE, 409 SHARE_UNCONFIRMED, 409 SHARE_LIMIT, 429 RATE_LIMITED, 451 REGION_RESTRICTED, 502 TX_FAILED, 503 NOT_CONFIGURED ```sh curl -X POST 'https://launchpad.basestocks.finance/api/tx/launch' \ -H 'content-type: application/json' \ -d '{"account":"0x1111111111111111111111111111111111111111","name":"Example Token","symbol":"EXMPL","contractURI":"ipfs://bafkreibm6jg3ux5qumhcn2b3flc3tyu6dmlb4xa7u5bf44yegnrjhc4yeq","stock":"0xb20000000000000000000078ee7ce2fe4908108c"}' ``` ## Eligibility Where the caller connects from, and the "not a US person" answer that quotes, pins and transaction builds wait for in a restricted country. ### GET /api/region Where the caller is. The country the host reports, the mode, and whether quotes, pins and transaction builds wait for the eligibility answer. (partner browsers allowed) Returns: { country, blocked, mode, blockedCountry, attested, restricted } ```sh curl 'https://launchpad.basestocks.finance/api/region' ``` ### POST /api/region Give the eligibility answer. The visitor's own statement that they do not live in the United States and are not a US citizen or resident, kept as a cookie for 30 days. Refused from another site's page. A site that asks in its own UI sends x-bstocks-eligibility: confirmed on each request instead. (same-origin in browsers) Parameters: - `confirm` (body, boolean, required): true to confirm, false to withdraw. Returns: the same as GET, and a Set-Cookie Errors: 400 INVALID_BODY, 403 CROSS_SITE ```sh curl -X POST 'https://launchpad.basestocks.finance/api/region' \ -H 'content-type: application/json' \ -d '{}' ``` ## Service Health of the indexer and the database, and this reference in machine-readable form. ### GET /api/health Health. Database, schema version, contracts, indexer lag and chain head. ok is false while the schema is behind or a launch hook is not configured. (partner browsers allowed) Returns: { ok, database, schema, contracts, deployments, indexer, head } ```sh curl 'https://launchpad.basestocks.finance/api/health' ``` ### GET /api/openapi.json OpenAPI spec. This reference as OpenAPI 3.1, for Swagger, Postman, code generators and AI agents. Any origin may fetch it. (partner browsers allowed) Returns: OpenAPI 3.1 document ```sh curl 'https://launchpad.basestocks.finance/api/openapi.json' ``` ## Contracts Each deployment is a factory, a hook and a router; every one stays live for its own tokens. New launches go to the newest. Trade a token through the router of the deployment that launched it (POST /api/tx/swap picks it). - Newest (takes launches): factory 0x888bc129704a4158c07614c234bb7eb8126aad47, hook 0xc81a728c6f4034e9249bb905f30e3013ca95e0cc, router 0x7cb00face8a634fc0a2a953a562c15f3f67f96a8 Quote stocks (13): NVDAc 0xb20000000000000000000078ee7ce2fe4908108c, AAPLc 0xb200000000000000000000c2e324d24d7eecd1fb, METAc 0xb2000000000000000000008bc8786b856e61707c, GOOGLc 0xb2000000000000000000002d0ba3164cc74f58b7, TSLAc 0xb2000000000000000000001e800a7f5189430cd0, MSFTc 0xb200000000000000000000ab99cfa739e253872b, AMZNc 0xb200000000000000000000d9192b6b456483c2e8, MSTRc 0xb2000000000000000000004884b426556b92883d, SNDKc 0xb200000000000000000000397293cb8cda9a10c5, SPCXc 0xb2000000000000000000007b9fcbd005511acbd5, COINc 0xb200000000000000000000c85a31389d71f3ecfb, CRCLc 0xb20000000000000000000019f6e7c675b73c2e4d, INTCc 0xb2000000000000000000004aff16039ba04bdfbc ## Widgets - Trade: https://launchpad.basestocks.finance/embed/trade/{token} · query: side=sell, show=chart,trades,holders, theme=light|dark, eligibility=always, accent=, hide=header,presets,notes - Create: https://launchpad.basestocks.finance/embed/create · query: stock=
, picker=select, theme, eligibility, accent, hide=header,stocks,links,buy,profile,steps (hide=stocks with stock fixes it) - Events posted to the host page: { source: "bstocks-launchpad", type: "ready" | "resize" | "swap" | "launch" }. Verify a swap or launch onchain before rewarding it. Endpoints in this file: 23.