Market state API
Public read endpoints for Candle’s view of a market: its lifecycle, a curve quote, launch verification, the trade page’s feed buckets, and agent records. None requires authentication. They are convenience reads: the on-chain registry and contract state remain authoritative for market identity, as described in Terminals and indexers.
Market state
Section titled “Market state”GET /api/v1/markets/:chain/:mintchain is solana or hood. The response is one chain-agnostic shape regardless of whether the mint is a Solana bonding curve or a Hood CandleCurve, cached about 5 seconds server-side:
{ "success": true, "market": { "chain": "solana", "mint": "...", "lifecycle": "trading", "buysOpen": true, "sellsOpen": true, "curveAddress": "...", "poolAddress": null, "quoteMint": "...", "feeBps": 100, "graduationVenue": "meteora-damm-v2", "tier": "open", "crossingModel": "full-fill-surplus", "candleLaunched": true, "launchpad": "candle", "venue": "candle-curve", "trade": { "endpoint": "POST /api/v1/trade/agent/quote", "routable": true }, "decimals": 6, "quoteDecimals": 9, "metadata": { "...": "..." }, "migration": { "status": "not_started", "reserveRaw": "...", "thresholdRaw": "...", "progressBps": 4120 } }}| Field | Notes |
|---|---|
lifecycle | trading, completed, migrated, or recovery. |
buysOpen, sellsOpen | Whether each side is currently executable. The two are independent; see the table below. |
curveAddress | The bonding curve (Solana pool or Hood CandleCurve) address. |
poolAddress | The post-migration venue pool on Solana (Meteora DAMM v2); null before migration and always null on Hood, where v3 and v4 pool discovery is on-chain. See Hood market integration. |
quoteMint | The quote asset’s mint or token address. |
feeBps | Curve trading fee in basis points. |
graduationVenue | meteora-damm-v2 on Solana; uniswap-v3 or uniswap-v4 on Hood. |
tier | open or exclusive, when known. |
crossingModel | full-fill-surplus on Solana, capped-refund on Hood. |
candleLaunched, launchpad | Whether Candle launched this mint, and the launchpad that did (candle for a Candle curve). |
venue | Where a trade routes now: candle-curve, jupiter, dex, hood-dex, or null while none is available. |
trade | { endpoint, routable, reason? }. Stored eligibility for the agent quote endpoint, never a quote or an authorization check. reason says why a market is not routable (for example solana_graduating). |
decimals, quoteDecimals | The token’s decimals and its quote asset’s decimals, for converting amounts to raw base units. |
metadata | The token’s name, symbol, image and socials as Candle holds them, or null. |
migration | Graduation progress. See below. |
Migration status
Section titled “Migration status”"migration": { "status": "in_progress", "attempts": 3, "nextAttemptAt": 1754400120000 }status | Meaning |
|---|---|
not_started | The curve is still trading. |
in_progress | The curve is done and the graduated venue is being seeded. |
completed | Trading has moved to the graduated venue. Carries migratedAt. |
delayed | Automated seeding exhausted its retries and a human has been alerted. |
migratedAt is stamped when a token first completes migration, so markets that graduated before this release report completed without one. On Hood the block also carries the keeper’s attempts, nextAttemptAt, and gaveUpAt where they apply. While a Solana curve is still trading, the block carries live graduation progress read from the pool: reserveRaw (quote raised so far), thresholdRaw (the graduation threshold), both in the quote asset’s raw units, and progressBps (capped at 10000). Watch these rather than the curve address’s balance: the quote sits as wrapped SOL in the pool’s vault.
The target is that a completed curve is live on its graduated venue within 10 minutes: the graduation keepers sweep every 2 minutes and retry with backoff. delayed is the machine-readable form of “this one needs a human”, not a normal step in the sequence.
Buys and sells are independent
Section titled “Buys and sells are independent”buysOpen and sellsOpen do not always move together:
lifecycle | Solana | Hood |
|---|---|---|
trading | Buys and sells open | Buys and sells open |
completed | Both closed during migration | Buys closed, sells still open until migration completes |
migrated | Both open on the graduated venue | Both open on the graduated venue |
recovery | n/a | Both closed; recovery is a claim flow, not a trade |
External markets (no Candle tokens row)
Section titled “External markets (no Candle tokens row)”When the mint is in Candle’s feed index or Jupiter can name it, the same endpoint returns HTTP 200
with external: true plus discovery flags (jupiterOk, externalTradeable, paperDiscoveryOk,
organic0LiveOk). That shape means Jupiter-routable (Solana) or Hood DEX reachable, not a
Candle-launched curve, but tradeable on the agent rail when tier allows.
MARKET_NOT_FOUND (404) carries error.routing.reason (chain_mismatch, token_unknown, and others) and
error.discovery. On chain_mismatch the mint is indexed on the other chain: discovery.indexed is
true and discovery.chain names the chain to retry with. On token_unknown nobody knows the mint
(discovery.indexed: false).
Errors use the structured envelope described in the Headless launch API: an invalid chain is VALIDATION_FAILED (400), an unknown market is MARKET_NOT_FOUND (404), and a dependency failure is QUOTE_UNAVAILABLE (503, retryable).
GET /api/v1/markets/:chain/:mint/quote?side=buy|sell&amountIn=<base units>&slippageBps=50Prices one trade through the exact same integer math the curve runs on-chain, so terminals do not have to re-implement crossing edge cases. Public, rate-limited to 120 requests per minute per client, cached about 5 seconds.
{ "success": true, "chain": "hood", "mint": "0x...", "side": "buy", "amountIn": "5000000000000000000", "crossingModel": "capped-refund", "quote": { "amountOut": "...", "fee": "...", "minAmountOut": "...", "crossesGraduation": true, "refund": "...", "quoteConsumed": "..." }}Every amount is a decimal string in the smallest unit of the quote asset (buys) or the base token (sells).
crossesGraduation applies to buys only, and what it implies differs by chain, which is why crossingModel travels with it. On Hood a crossing buy is capped at the threshold and the remainder refunded, so refund and quoteConsumed tell you how much was actually spent. On Solana a crossing buy fills in full and the surplus stays in the pool, so the refund fields never appear.
minAmountOut applies your slippageBps to the capped fill rather than the uncapped one, so a quote is always satisfiable on-chain, even across graduation.
A curve that cannot execute the requested side returns MARKET_NOT_TRADABLE (409), and the message names where trading continues: the Uniswap pool, the Jupiter or Meteora route, or “buys closed while graduating, sells remain open”.
This quote covers Candle curves only. A mint that is not a Candle market returns MARKET_NOT_FOUND (404) with a message pointing to POST /api/v1/trade/agent/quote, which quotes external tokens. Other errors: RATE_LIMITED (429), QUOTE_PAIR_UNKNOWN for an unrecognized quote asset, and QUOTE_UNAVAILABLE (503, retryable) when a dependency fails.
Verify
Section titled “Verify”GET /api/v1/verify/:chain/:mintThe authoritative answer to “is this mint a genuine Candle launch”, so users and terminals can reject look-alike mints. Public, cached about 60 seconds.
{ "success": true, "candleLaunched": true, "chain": "hood", "mint": "0x...", "tier": "open", "quoteMint": "0x...", "graduated": false, "pool": null, "createdAt": 1754400000000, "creator": "0x...", "viaAgentKey": true, "provenance": { "curve": "0x...", "factory": "0x...", "configHash": "0x...", "dexVersion": "v4" }}An unknown mint, or one launched with non-production visibility, returns 200 with { "candleLaunched": false } rather than a 404, so a caller branches on one response shape either way.
Hood responses carry the provenance block above, re-verifiable against the registry. Solana responses instead carry attribution (the bonding-curve program and the attribution signer), so an indexer can re-derive the same conclusion on-chain using the procedure in Solana market identification.
viaAgentKey is true when the launch came through an agent API key, which is the same signal behind the agent badge in the Candle UI.
GET /api/v1/markets/feed?bucket=new|graduated|onfire|bluechip&chain=solana|hoodA thin public read onto the same feed buckets the trade page tabs use, optionally filtered to one chain. It is served live from the feed engine (no cache); while the engine starts it answers 503 FEED_UNAVAILABLE with Retry-After. bucket is required; chain is optional.
The feed also takes where, sort, fields, limit, since_seq and discovery=paper, and the response carries matched, scanned, cursor, warming, organicScoreGuidance, and on a since_seq read reset and removed. See Reading the feed for the query syntax.
{ "success": true, "bucket": "new", "tokens": [ { "chain": "solana", "address": "...", "name": "Trend Coin", "symbol": "TREND", "image": "https://...", "isAgent": true } ]}Each row carries chain, address, name, symbol, image, price, volume, and market-cap statistics, and isAgent, which is true for a Candle-origin launch created through an agent API key. An unknown bucket or chain is VALIDATION_FAILED (400).
Agent profile
Section titled “Agent profile”GET /api/v1/users/:idOrWallet/agentA public read for any account: whether it has agent features enabled, its address and username, and its launch counts, total versus those attributed to an agent key.
{ "success": true, "agent": { "enabled": true, "address": "...", "username": "trendbot", "launches": 12, "launchesViaApi": 9, "tier": "pro" }}tier is the account’s plan today: max, pro, believer or free.
Unlike the market endpoints, this route’s errors are plain: { "error": "User not found" } with status 404.
Hood mark
Section titled “Hood mark”GET /api/v1/markets/hood/:mint/markA Hood token’s mark: the market provider’s indexed price (priceUsd), plus sellUsd and buyUsd adjusted for the deepest pool’s fees (feeBps, lpFeeBps, hookFeeBps), the pool, and asOf. It is a price for carrying positions, not a quote for a trade. Public, limited to 600 requests per minute per client, cached 10 seconds per mint. A token with no usable price is MARKET_NOT_FOUND (404); a provider failure is QUOTE_UNAVAILABLE (503, retryable).
Copy score
Section titled “Copy score”GET /api/v1/markets/agents/:profileId/copy-scoreWhether a published agent’s edge is one a follower could capture, computed from that agent’s own fills. The response carries score with profileId, name, wallet, the assessment, and the inputs it used (a null input was not measured). An agent whose record is not published answers 404 MARKET_NOT_FOUND, the same as an unknown one. Public, 60 requests per minute per client, cached 60 seconds.
Cohorts
Section titled “Cohorts”GET /api/v1/markets/cohorts/:cohort?limit=10Agents worth watching, curated from published records and ordered by how followable they are. cohort is steady, high_conviction or early_finder; limit is 1 to 50 (default 10). The response carries cohort, members (each with profileId, name and address), and truncated. Only agents whose owner published their record are eligible. Public, 60 requests per minute per client, cached 2 minutes.