debundle API
Data on every token launched on pons (Robinhood Chain, chain id 4663), indexed from the chain, with an organic score that separates volume from many real buyers from bundled and wash volume. REST, MCP and webhooks share one API key.
Unofficial. Not affiliated with pons or Pons Labs. ponsfamily.com. The organic score is a heuristic, not proof and not financial advice.
Quickstart
- Open Keys, sign in with a wallet on Robinhood Chain, and create a key. It is shown once.
- Send it as a Bearer token. The example asks for young tokens labelled organic.
curl -H "Authorization: Bearer $DEBUNDLE_API_KEY" \ "https://debundle.xyz/api/v1/feeds/hot-new?limit=10"Every screener view has a Copy as API call button that turns the current feed and filters into this request.
Keys and limits
- Send
Authorization: Bearer psk_live_…orx-api-key: psk_live_…. - Keys are created by signing in with a wallet (SIWE on chain 4663). Up to 5 active keys per wallet. Only a hash is stored.
- Free tier: 60 requests per minute per key. Pro: 600. Every response carries
X-RateLimit-Limit,X-RateLimit-RemainingandX-RateLimit-Reset. GET /statusneeds no key and is limited per IP.- CORS is open for GET, so browser apps can call the API directly. Do not ship a key in public frontend code.
Responses
Every success is { data, meta }. meta has the indexed block, how many seconds the data trails the chain, the score version, and a cursor when there are more rows. Pass cursor back to get the next page. Wei amounts are strings, ETH and USD amounts are numbers, missing values are null.
{ "data": [ { "address": "0x…", "symbol": "…", "organicScore": 82, "organicLabel": "organic", … } ], "meta": { "indexedBlock": "41234567", "indexedAt": "2026-10-06T12:00:00.000Z", "lagSeconds": 3, "scoreVersion": 1, "page": { "nextCursor": "eyJ2Ijo…", "limit": 50 } }} { "error": { "code": "rate_limited", "message": "Rate limit of 60 requests per minute exceeded." } }Endpoints
Base URL https://debundle.xyz/api/v1. The full schema is in openapi.json (OpenAPI 3.1) and a short version for language models is in llms.txt.
get/statusIndexer head and lag. No API key needed.no key
No query parameters.
get/statsProtocol summary over the last 24h
No query parameters.
get/feeds/{feed}Preset feeds: new, hot-new (young, organic, many entities), trending, near-graduation, graduated
| Query parameter | Type | Notes |
|---|---|---|
| period | 5m | 1h | 24h | trending only. Default 1h. |
| limit | integer | Page size, 1 to 100. Default 50. |
| cursor | string | Opaque cursor from meta.page.nextCursor. |
get/tokensScreen tokens with any combination of filters
| Query parameter | Type | Notes |
|---|---|---|
| minAgeMin | number | Minimum age in minutes. |
| maxAgeMin | number | Maximum age in minutes. |
| minMcap | number | USD. |
| maxMcap | number | USD. |
| minLiquidity | number | USD. |
| maxLiquidity | number | USD. |
| minVolume | number | 24h total volume, USD. |
| maxVolume | number | 24h total volume, USD. |
| minOrganicVolume | number | 24h organic volume, USD. |
| maxOrganicVolume | number | 24h organic volume, USD. |
| minScore | number | |
| maxScore | number | |
| label | string | Comma-separated: organic,mixed,bundled,insufficient_data. |
| minBuyers | integer | |
| minEntities | integer | |
| minHolders | integer | |
| maxHolders | integer | |
| maxTop10Pct | number | Top-10 holder share in percent, excluding pool, locker and burn. |
| maxDevPct | number | Deployer holding in percent. |
| devSold | true | false | |
| hasSocials | true | false | |
| minProgress | number | Graduation progress 0 to 1. |
| maxProgress | number | |
| graduated | true | false | |
| version | v1 | v2 | |
| minCreatorTaxBps | integer | v2 only. |
| maxCreatorTaxBps | integer | v2 only. |
| pairToken | string | v2 only: quote asset address. |
| q | string | Name, symbol or address search. |
| sort | launched | age | mcap | liquidity | volume24h | organicVolume5m | organicVolume1h | organicVolume24h | score | buyers | entities | holders | progress | graduatedAt | Default launched. |
| order | asc | desc | Default desc. |
| limit | integer | Page size, 1 to 100. Default 50. |
| cursor | string | Opaque cursor from meta.page.nextCursor. |
get/tokens/{address}One token with all score windows, smart wallets buying and copycat original
No query parameters.
get/tokens/{address}/tradesTrades, newest first
| Query parameter | Type | Notes |
|---|---|---|
| limit | integer | Page size, 1 to 100. Default 50. |
| cursor | string | Opaque cursor from meta.page.nextCursor. |
| side | buy | sell |
get/tokens/{address}/scoreOrganic score with per-metric breakdown and clusters
| Query parameter | Type | Notes |
|---|---|---|
| window | launch | 1h | 24h |
get/tokens/{address}/holdersTop holders. Pool, locker and burn are marked as excluded from top-10 %
| Query parameter | Type | Notes |
|---|---|---|
| limit | integer | Default 50. |
get/tokens/{address}/candlesOHLC candles in ETH from indexed trades
| Query parameter | Type | Notes |
|---|---|---|
| interval | 1m | 5m | 1h | Default 5m. |
| limit | integer | Default 300. |
get/deployers/{address}All launches by a deployer, graduation rate, average score, quick-sell and bundle patterns
No query parameters.
get/wallets/{address}A wallet's pons trades, positions, realized PnL and smart label
| Query parameter | Type | Notes |
|---|---|---|
| limit | integer | Page size, 1 to 100. Default 50. |
| cursor | string | Opaque cursor from meta.page.nextCursor. |
get/webhooksList your webhooks
No query parameters.
post/webhooksRegister a webhook. The response includes the signing secret.
Deliveries are POSTed as JSON with header x-debundle-signature: t=<unix>,v1=<hex HMAC-SHA256 of '<t>.<raw body>' with your secret>. Failed deliveries retry after 1m, 5m, 30m, 2h and 12h. URLs must be public https.
No query parameters.
delete/webhooks/{id}Delete a webhook
No query parameters.
Feeds
new: latest launches.hot-new: younger than 60 minutes, labelled organic, at least 15 distinct buyer entities, sorted by organic volume. Launches that are busy because many people buy, not because of a bundle.trending: highest organic volume overperiod5m, 1h or 24h.near-graduation: 70% or more of the way to graduation.graduated: most recently graduated first.
MCP for agents
A Model Context Protocol server runs at https://debundle.xyz/api/mcp over Streamable HTTP, with the same key as a Bearer token and the same rate limit. Tools: get_feed, search_tokens, get_token, get_token_score, get_deployer, get_wallet.
claude mcp add --transport http debundle https://debundle.xyz/api/mcp \ --header "Authorization: Bearer $DEBUNDLE_API_KEY"Webhooks
Register a public https URL in the dashboard or with POST /webhooks. Events: token.launched, token.hot (entered the hot-new feed), token.graduated and token.score_changed (label changed). Each delivery is a POST with the JSON body { event, createdAt, data }. Answer with any 2xx within 10 seconds. Failures are retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, then dropped.
Check the x-debundle-signature header, t=<unix seconds>,v1=<hex>, where v1 is HMAC-SHA256 of `${t}.${rawBody}` keyed with the webhook's secret. Reject old timestamps to stop replays.
import { createHmac, timingSafeEqual } from "node:crypto"; export function verify(rawBody: string, header: string, secret: string, toleranceSec = 300) { const parts = Object.fromEntries(header.split(",").map((p) => p.split("=") as [string, string])); const t = Number(parts.t); if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false; const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex"); const got = Buffer.from(parts.v1 ?? "", "hex"); return got.length === 32 && timingSafeEqual(got, Buffer.from(expected, "hex"));}Organic score
A number from 0 to 100 for a window of trading: the first 30 minutes after launch, the last hour, and the last 24 hours. It starts at 100 and loses points for nine signals. Each signal is a share from 0 to 1 of buy volume in the window, multiplied by its weight.
organic_score = round(100 − Σ weight × signal), clamped to 0..100| Signal | What it measures | Weight |
|---|---|---|
Clustered buyerscluster_share | Buy volume from entities of 3 or more wallets linked by funding or a shared transaction. | 25 |
Dev-linkeddev_linked_share | Buy volume from the deployer or wallets it funded or that share its funder. | 15 |
Top-10 concentrationtop10_entity_share | Share of buy volume from the 10 largest entities, scaled so 30% scores 0 and 90% scores 1. | 15 |
Fresh walletsfresh_share | Buy volume from wallets with almost no history or funded less than 24 hours before buying. | 10 |
Launch burstearly_burst_share | Share of first-30-minute volume inside the launch protection window, or from wallets that bought close to the 5% cap. | 10 |
Wash tradingwash_share | Buy volume from wallets that bought and sold back and forth with little net change. | 10 |
Uniform sizesuniform_size_share | Share of buys that match another wallet's buy size within 2% in nearby blocks. | 5 |
Via other contractsvia_contract_share | Buy volume sent through a contract other than the official router. | 5 |
Low persistencelow_persistence | Share of 5-minute periods in which no new buyer entity arrived. | 5 |
Labels
70 and above is organic, 40 to 69 is mixed, below 40 is bundled. With fewer than 20 buys or 10 distinct buyers the score is null and the label is insufficient_data.
Entities
Buyer wallets are grouped into entities. Two wallets join when they share their first funder, when one funded the other, when the deployer funded them, or when one transaction bought for both. Bridges, exchanges and other hubs that fund many wallets across many tokens never join wallets together. The trader is the transaction sender, not the router in the swap event.
Organic volume
Volume from entities that are not a cluster of 3 or more wallets, not linked to the deployer, and not wash trading. Total volume is reported next to it.
Limits
The score is a heuristic built from public chain data. A careful bundler can fund wallets through hubs and look organic, and a real community can trip a signal. Every response includes each signal and the clusters behind it so you can judge for yourself. Weights are versioned in scoreVersion and will be recalibrated as data accumulates. The organic score is a heuristic, not proof and not financial advice.