Appearance
Launch on the Launchpad via the API
The launchpad launches a token with zero upfront capital, liquidity locked by design, and a free verified token page on chaindaddy.io. The whole flow is drivable by a single cd_live_… API key — an autonomous agent can go from nothing to a live, verified token without a browser or a wallet session.
There are two ways to broadcast:
- Operator-broadcast — you send one request and Chain Daddy signs + broadcasts the launch with its operator signer. Your API key's wallet is the fee-stream beneficiary. Best for agents that hold no chain gas.
- Wallet-relayed — the API returns an unsigned transaction; your own signer broadcasts it. Chain Daddy never holds your key.
Authentication
Send your key as a bearer token on every request:
Authorization: Bearer cd_live_…The key resolves to its owning wallet. That wallet is the launch creator and the default fee-stream beneficiary, and a server-side custody pin requires the creator in the request body to equal it — an agent cannot direct another wallet's fee stream. (Web-app callers may send a session JWT instead of a key; the endpoints accept either.)
1 — Discover what a chain supports
GET /api/v2/factory/evm/launchpad/capabilities?chainId=84532Returns what each offered chain can actually run, so an agent can pick a valid configuration before building. Nothing in it is hardcoded per chain — the engine fields are probed against what is deployed, so read them rather than assuming.
| Field | Notes |
|---|---|
chains[].launchKinds | the launch modes this chain can run, most-capable first. |
chains[].poolFeatures | the pool knobs available here, including boost. |
chains[].preOpenAuctionEngine | dynamic-auction (Dutch price decay, with a raise target it must clear to graduate) or multicurve-rehype (decaying fee, no raise target). Empty when unprobed or when neither runs. This decides whether a pool has one fee stream or two — see the two streams — and whether a boosted launch starts routing at the first trade or only at graduation. |
chains[].numeraireSymbol / numerairePriceUsd | the chain's default quote asset and its live USD price. Price is 0 when unavailable. It is no longer the only accepted numeraire — read chains[].numeraires below. |
chains[].numeraires[] | the closed set of assets this chain's launches may quote against, and the only values numeraire accepts. Each entry carries symbol, address (send this back verbatim — treat it as opaque), decimals, wrappedNative (the default entry, first in the list) and devBuyEligible. Rendered from the same function the build endpoint validates against, so it can neither offer an asset that would be refused nor omit one that would be accepted. Do not hardcode addresses from it. See what a launch can be paired against. |
chains[].numeraires[].decimals | the scale that asset is issued at. Do not assume 6 for a dollar stablecoin — BNB Chain's "USDC" is 18-decimal Binance-Peg. Format amounts with this field. |
chains[].numeraires[].devBuyEligible | whether the creator's optional first buy is available on a launch quoted against this asset. True only for the wrapped native: the first buy is paid in the chain's native currency, which cannot buy into a pool quoted in anything else. |
chains[].numeraires[].dutchAuctionMinProceeds | the pre-open auction's minimum raise in this asset's base units. Use this, not the top-level preOpenAuction.dutchAuctionMinProceedsWei, whenever the launch is quoted against anything but the wrapped native. |
chains[].gaslessDripEligible | a gasless social launcher can be dripped registration gas here. |
chains[].operatorBroadcastEligible | the operator will pay this chain's launch gas. false on Ethereum L1 by default — launching there is offered only through the wallet-relayed /build path. |
boostShareBps | the operator's default boost share. |
boostSharePresetsBps | the boost shares the pad offers, ascending, 0 ("off") first. The largest entry is the accepted ceiling — a boost.shareBps above it is a 400. |
marketCapPresetsUsd / defaultMarketCapUsd | the offered opening market caps, and the preselected one. |
marketCapCeilingRatio | the multiple of the opening market cap the pool's book reaches when a request names only the opening figure. |
preOpenAuction.dutchAuctionDurationSeconds / dutchAuctionMinProceedsWei | the auction window, and the raise it must clear inside that window to graduate to a permanent pool. dutchAuctionMinProceedsWei is the wrapped-native figure only. The raise is an amount of the quote asset, so against a 6-decimal stablecoin the real floor is a different (and far smaller) integer — read chains[].numeraires[].dutchAuctionMinProceeds for the asset you are actually launching against, or you will caption a floor 10¹² too high. |
preOpenAuction.feeDecaySeconds / feeDecayStartFee | the decaying-fee mechanism's window and opening fee (hundredths of a bip). |
whaleCap | the operator's per-wallet cap defaults. |
Every number here is operator-tunable and served for exactly that reason. Copying one into your own code makes it wrong the first time it is retuned.
2 — Build or broadcast the launch
Both take the same body. /build returns an unsigned tx; /broadcast signs + sends it operator-side and returns the tx hash.
POST /api/v2/factory/evm/launchpad/build
POST /api/v2/factory/evm/launchpad/broadcastjson
{
"chainId": 84532,
"name": "My Token",
"symbol": "MYT",
"tokenUri": "ipfs://…",
"initialSupply": "1000000000000000000000000000",
"numTokensToSell": "900000000000000000000000000",
"numeraire": "0x4200000000000000000000000000000000000006",
"creator": "0xYourApiKeyWallet",
"launchMode": "static",
"poolConfig": { "startMarketCapUsd": 30000, "fee": 10000 },
"antiSnipe": { "whaleCap": { "enabled": true, "shareBps": 200 } }
}Core fields
| Field | Notes |
|---|---|
launchMode | static (permanently-locked lockable-V3 + optional whale cap) or dynamic-auction (a pre-open auction — which mechanism depends on the chain's preOpenAuctionEngine). |
initialSupply / numTokensToSell | wei strings (whole tokens × 10¹⁸). Sell fraction is your choice; the rest is the beneficiary allocation. |
numeraire | allowlisted, not merely validated. It must be one of the addresses that chain reports in numeraires[] — its wrapped native token, or a canonical dollar stablecoin the chain registry carries (USDC where Circle deploys it, USDG on Robinhood Chain). Anything else is a 400: numeraire must be this chain's wrapped native token or one of its canonical dollar stablecoins. There is no way to register a further address. See what a launch can be paired against. |
numeraire — non-18-decimal | a launch quoted against an asset that is not 18-decimal must send poolConfig.startMarketCapUsd; a tick-only request is a 400. Every default tick band was derived against an 18-decimal asset, and a tick value encodes a ratio of base units — reusing one against a 6-decimal asset opens the pool at the wrong price silently, since the resulting tick is still inside int24 and nothing reverts. Price in dollars and the server derives the ticks correctly. |
poolConfig.startMarketCapUsd / endMarketCapUsd | the preferred way to price a launch — the opening market cap in US dollars, and optionally the ceiling. These win over startTick/endTick when above 0. Omit endMarketCapUsd and the book reaches marketCapCeilingRatio × the opening figure. |
poolConfig.startTick / endTick | the raw tick path. Only read when no market-cap figure is given; prefer the dollar fields. |
poolConfig.fee | swap-fee tier in hundredths of a bip — 3000 (0.3%) or 10000 (1%). Ticks are snapped to the tier's spacing server-side, so any preset works with any fee tier. On a multicurve-rehype chain this rate is written into both the pool's own fee and the hook's standing fee, so a trade pays it on each leg — see the two streams. |
antiSnipe.whaleCap | optional per-wallet max-balance cap (shareBps of supply) for an anti-snipe window. |
antiSnipe.feeTier / antiSnipe.lockDurationSeconds | optional overrides for a static launch's pool tier and lock. |
feeRecipient | optional — the address the pool records for the creator's fees. On a chain with two fee streams it moves both of them, and it does not override boost.destination: "burn". The launch identity stays creator, so the predicted token address is unchanged. |
beneficiaries | optional [{ address, shareBps }] — extra addresses recorded on the pool's own swap fee. A split divides that stream only; the hook's stream records one address and no split reaches it. Refused together with boost.enabled. |
collabDealId | optional — launch under an agreed split. Refused together with boost.enabled, for the same reason. |
imageUrl, bannerUrl, description, website, xUrl, telegram | optional token-page metadata, carried through to the free verified page. |
anthemUrl, anthemLoop, anthemAutoplay | optional audio for the token page. |
launcherSocial | optional social identity recorded with the launch. |
boost — routing a share of the fees
Optional. Routes a share of the numeraire fee row into buying the launched token back, and sends what is bought to one of two places. Read Fee routing before sending it: every field here is written into the pool when the token is created and there is no setter to change it.
json
{
"boost": {
"enabled": true,
"shareBps": 2000,
"destination": "creator",
"mix": { "walletBps": 1500, "liquidityBps": 500 }
}
}| Field | Notes |
|---|---|
enabled | turns the whole block on. Sending shareBps, destination or mix with enabled: false is a 400, not a silent drop — the settings would otherwise be discarded on a pool nobody can edit. |
shareBps | basis points of the fee row to route, 0 < x < 10000. Above the largest entry in boostSharePresetsBps is a 400. Omit it and the operator default applies. |
destination | "creator" or "burn" — words, never an address. "creator" resolves to feeRecipient when one was given, else the launching wallet; "burn" resolves to 0x…dEaD. Anything else is a 400. |
mix.walletBps / mix.burnBps | the buyback leg, seen from its two possible destinations. They are the same bucket, so only one may be positive, and it must agree with destination. |
mix.liquidityBps | the leg added to the pool as liquidity instead. Accepted only on a multicurve-rehype chain; a 400 elsewhere. The position is held by the hook contract at full range and the contract has no function to remove it — see the liquidity slice. |
all mix legs zero | a 400. A basket that divides nothing is boost off under another name. |
burn with no buyback leg | a 400. With the whole share going to liquidity there is nothing to buy and send to the burn address. |
destination: "burn" is bigger than shareBps. The pool records one address for the hook's entire stream, so a burn sends all of it — the buyback and the beneficiary bucket alike — to 0x…dEaD for the life of the pool. The creator's share of the pool's own swap fee is a separate stream and is not affected. See Where the buybacks go.
Boost forces launchMode: "dynamic-auction". The response reports the override as launchModeOverridden: true; do not assume the mode you asked for is the mode that ran.
Responses
/build (unsigned tx you sign + send yourself):
json
{ "chainId": 84532, "to": "0x…Airlock", "data": "0x…", "value": "0",
"predictedTokenAddress": "0x…", "predictedPoolAddress": "0x…",
"engine": "multicurve-rehype", "launchMode": "dynamic-auction",
"launchModeOverridden": true, "openingMarketCapUsd": 30000 }/broadcast (Chain Daddy already sent it):
json
{ "chainId": 84532, "txHash": "0x…", "operator": "0x…",
"predictedTokenAddress": "0x…" }| Response field | Notes |
|---|---|
engine | which engine the launch actually used — probed per launch, not a chain constant. |
launchMode | the mode that ran. |
launchModeOverridden | true when the requested mode was replaced (boost forces dynamic-auction). The only way to learn it from the response. |
openingMarketCapUsd | the opening market cap the calldata was built for. |
poolId | a dynamic-auction launch returns this bytes32 instead of a predictedPoolAddress. |
beneficiaries | the split as recorded, including any co-creator. |
Read the actual launched token/pool from the
Createevent in the transaction receipt — the predicted address can lag on a load-balanced RPC.
3 — Register the free verified token page
Every launchpad token is eligible for a free verified token page. After the launch is on-chain, register it — also fully API-key driven:
- Create the free order —
POST /api/v2/payments/og/create-orderjsonReturns an{ "items": [ { "chain": "84532", "symbol": "MYT", "address": "0xLaunchedToken", "type": "crown_claim" } ] }orderIdfor a $0 order. - Issue the receipt —
POST /api/v2/payments/receiptswithpaymentId= theorderId,recipient= your wallet, and one item marking the existing token (status: "unclaimed",address,initialSupply: "0"). Returns a server-signed receipt. - Redeem — send the receipt's
mintCrownForExistingPaid(receipt, signature)call to the returnedfactoryAddress. This step is bound to the recipient, so your wallet signs it (gasless drip is available for embedded wallets).
The token page resolves at chaindaddy.io/{symbol} once the indexer catches up.
4 — Read and claim the fees
A launchpad pool's fees accrue continuously and are claimed by whoever sends the claim transaction. Nothing is claimed for you.
On a chain running the multicurve-rehype engine a pool has two independent fee streams, on two contracts, claimed by two different calls.Two streams explains the shape; the endpoints below are one per stream.
Stream two — the hook's fee
POST /api/v2/factory/evm/launchpad/fees { "chainId": 4663, "token": "0x…" }
POST /api/v2/factory/evm/launchpad/claim { "chainId": 4663, "poolId": "0x…", "token": "0x…" }/fees previews what is undistributed, keyed by pool (a static V3 launch) or token (a dynamic-auction one). /claim returns the unsigned claim, keyed by pool for static V3 or by poolId plus token for dynamic-auction — the presence of poolId is the V4 discriminator, and sending both lets the backend serve either migration mode.
On a staticV3 launch this is the only pot there is. The second stream below exists only where the chain runs the multicurve-rehype engine. Both claim entrypoints are permissionless: anyone may send them, and they pay the parties the pool recorded rather than the sender.
| Response field | Notes |
|---|---|
assetFees / numeraireFees | base-unit decimal strings. Pool totals, never one party's share. |
mechanism | staticV3 (claim keyed by pool) or v4Rehype (claim keyed by token). A claim keyed the wrong way reverts, and the two are otherwise indistinguishable from outside. |
distributesToAll | true for staticV3, where one call pays every beneficiary at once. false for v4Rehype, whose hook pays one destination. |
payee | who the totals go to under this mechanism. |
feeDestination | on a v4Rehype read, the one address the pool actually recorded for its hook fees, read from the chain. This is the only field that tells a burn launch from an ordinary one — payee cannot, and the amounts look identical either way. Classify the address yourself (0x…dEaD is a burn; 0x0 would be a bricked pool). Absent means unknown, never "not burn" — the read can fail, and a staticV3 pool has no such address at all. |
Stream one — the pool's own swap fee
POST /api/v2/factory/evm/launchpad/fees/creator-share { "chainId": 4663, "token": "0x…", "from": "0x…" }
POST /api/v2/factory/evm/launchpad/fees/claim-creator { "chainId": 4663, "token": "0x…", "from": "0x…" }The stream a burn does not touch. creator-share is the read and answers a zero share plainly; claim-creator is the same read plus the calldata, and refuses a zero share.
from is required and is not defaulted. It is the wallet that will send the claim and therefore the only address it can pay — collectFees(bytes32) does not revert for a sender holding no share, it pulls the pool's accrual in and pays nobody. The transaction costs gas, succeeds, and looks exactly like one that paid, so the share read is the only place a wrong token, chain or wallet is catchable.
| Response field | Notes |
|---|---|
share | getShares(poolId, from) read on-chain, as WAD (1e18 = 100%; a standard creator share reads 8e17). |
assetFees / numeraireFees | this sender's share, attributed to the launched token and to what it trades against. Both sides accrue and which one carries the balance depends on the launch, so do not read one side only. |
feesAreAtLeast | always true, and not decoration. The contract counts only what it has already pulled in, and the only thing that pulls is this claim — so a claim transfers these amounts or more, never less. Nothing may present them as exact. |
poolId | the bytes32 the calldata carries, echoed so you can check the claim against the pool you asked about. |
to / data / value | the unsigned claim. Present on claim-creator only. |
Fees & limits
- Launch and registration are free. Nothing is charged upfront. Chain Daddy takes a slice of the pool's own swap fee — 20% on the free tier, 5% with a subscription, leaving the creator 75% or 90% after the underlying protocol's mandatory 5%. That is a share of one stream: see the split for the figures and two streams for which stream they divide.
- Wallet-relayed launches are unmetered — you pay your own gas.
- Operator-broadcast launches (where Chain Daddy pays gas) are subject to a per-account weekly allowance on the free tier; a subscription lifts it. The read-only builders are IP-rate-limited.
Testnet
The full flow runs on Base Sepolia (chainId 84532) against https://staging-api.chaindaddy.io for integration testing before mainnet.