Skip to main content

Tok{In} API

The Tok{In} API offers an array of features that can help determine whether a token is malicious or not. From storage checks, to simulation and static analysis features. The Tok{In} API supports all ERC20 contracts on Ethereum, Binance Smart Chain, Arbitrum, Base, Avalanche, and Robinhood Chain (New). The features cover all Uniswap V2/V3/V4 forks, Aerodrome V2/Slipstream (Base), and launchpad tokens — both bonding curves (four.meme and flap.sh on BSC, trench.today and flap on Robinhood Chain) and launchpads that seed a standard DEX pool directly (Pons, Noxa, Virtuals, Doppler, varo.rialto, bow.fun and letscash.fun on Robinhood Chain).

For AI coding agents (Claude Code, Cursor, Copilot, etc.): a migration guide written specifically for you lives at AGENTS.md alongside this page (canonical URL: https://docs.dedaub.com/docs/token_safety/AGENTS). Read it end-to-end before changing any code that integrates with Tok{In} — it covers the GoPlus → Tok{In} drop-in swap, field mappings, always-null fields, and common migration pitfalls.

Usage

curl -X 'GET' \
'https://tokin-api.dedaub.com/token/{chain}/{token_address}' \
-H 'accept: application/json' \
-H 'X-API-Key: YOUR-API-KEY'

chain: The chain of the token token_address: The address of the token

User Interface

A Swagger UI for easier interaction with the API is available at https://tokin-api.dedaub.com .

Available Chains

ChainSlugChain ID
Ethereumethereum1
Binance Smart Chainbinance56
Arbitrumarbitrum42161
Basebase8453
Avalancheavalanche43114
Robinhood Chain (New)robinhood4663

DEX coverage is most complete on Ethereum, with more pools being added to the other chains over time.

Quote tokens per chain

Pool discovery and liquidity valuation are anchored on each chain's wrapped native token plus its canonical ~$1 stablecoins. That anchor set is not the same on every chain:

ChainWrapped nativeStable anchors
Ethereum, Arbitrum, BaseWETHUSDC, USDT
Binance Smart ChainWBNBUSDC, USDT
AvalancheWAVAXUSDC, USDT
Robinhood ChainWETHUSDG, USDE

Robinhood Chain has no canonical USDC or USDT — USDG and USDE are the real ~$1 tokens there, and any USDC/USDT-named deployment on 4663 is an impostor. Pools quoted in a non-anchor token can still be valued when a price is available (see Notes on liquidity).

Response Formats

The Tok{In} API supports multiple response formats via the response_format query parameter.

Available Formats

FormatDescription
dedaubDefault format
goplusGoPlus-compatible format

Usage

# Default (Dedaub format)
GET /token/{chain}/{token_address}

# GoPlus format
GET /token/{chain}/{token_address}?response_format=goplus

GoPlus Format Mapping

The GoPlus format transforms the default Tok{In} schema to a GoPlus-compatible one, with the following caveats.

Direct Mappings

Dedaub FieldGoPlus FieldNotes
is_open_sourceis_open_sourceBoolean → "1"/"0" string
is_proxyis_proxyBoolean → "1"/"0" string
mint_or_burn_functionis_mintableBoolean → "1"/"0" string
owner_addressowner_addressDirect string
can_selfdestructselfdestructBoolean → "1"/"0" string
external_callexternal_callBoolean → "1"/"0" string
is_in_dexis_in_dexBoolean → "1"/"0" string
receive_taxbuy_taxDecimal as string — pool-aware, see caveat 4
send_taxsell_taxDecimal as string — pool-aware, see caveat 4
cannot_buycannot_buyBoolean → "1"/"0" string
tax_can_be_modifiedslippage_modifiableBoolean → "1"/"0" string
trading_cooldowntrading_cooldownBoolean → "1"/"0" string
creator_addresscreator_addressDirect string
creator_percentcreator_percentDecimal as string
is_launchpad_tokenlaunchpad_tokenBoolean → "1"/"0" string

Computed Mappings

GoPlus FieldDerived FromLogic
transfer_pausablecannot_buy, pause_status_can_be_modifiedTrue if either is True
is_blacklistedhas_blacklist_or_whitelistSame value (temporary)
is_whitelistedhas_blacklist_or_whitelistSame value (temporary)
is_anti_whalehas_trading_cap, has_position_capTrue if either is True
anti_whale_modifiabletrading_cap_can_be_modified, position_cap_can_be_modifiedTrue if either is True
hidden_ownerallowance_bypass, privileged_spendersTrue when the allowance-bypass probe named at least one address
owner_change_balanceowner_can_change_balanceSame value

Fields Without Direct Equivalent (returns null)

GoPlus FieldReason
cannot_sell_allNot currently tracked
can_take_back_ownershipNot currently tracked
gas_abuseNot currently tracked
personal_slippage_modifiableNot currently tracked
lp_total_supplyNot currently tracked
is_airdrop_scamNot currently tracked
trust_listNot currently tracked
holder_countNot currently tracked
owner_balanceNot currently tracked
owner_percentNot currently tracked

Caveats

  1. is_blacklisted / is_whitelisted: Currently both map from has_blacklist_or_whitelist. We cannot distinguish between blacklist-only, whitelist-only, or both.

  2. Boolean Format: GoPlus uses string format ("1" / "0") instead of booleans. All boolean fields are converted accordingly.

  3. Tax Terminology: Our send_tax maps to GoPlus sell_tax, and our receive_tax maps to GoPlus buy_tax. Note the direction inverts — code computing slippage must follow the rename.

  4. buy_tax / sell_tax are pool-aware, and may disagree with the contract-level tax. In goplus mode these are taken from the first pool in dex[] that reports a tax, falling back to the contract-level receive_tax / send_tax only when no pool reports one. The pool figure reflects what a real swap would cost and is usually the more useful number, but it means buy_tax in a goplus response can differ from receive_tax in the equivalent dedaub response for the same token. If you compare the two formats, expect this and prefer the pool figure for trade decisions.

  5. is_honeypot is always null. It is present in the response shape but not yet produced. Integrations that gate trades on is_honeypot === "1" will treat every token as safe after migrating. Derive an equivalent from cannot_buy, the per-pool dex[].buy_success / sell_success (dedaub mode), and the tax fields — or block while the field is unavailable. See Reading buy_success / sell_success first, because the null/"pending" states matter for exactly this decision.

  6. hidden_owner is narrower than it looks: it is "1" only when the bypass is address-specific. A universal bypass — where the allowance check is skipped for everyone — sets allowance_bypass but leaves privileged_spenders empty, and maps to "0" because no undisclosed owner exists. It is null when the probe could not run, which is not the same as "0". Use the Dedaub format if you need to tell those three apart, or to read the offending addresses.

Static Analysis Features

We leverage the Gigahorse decompiler to analyze contracts whose source code is unavailable. The decompiled bytecode is checked for patterns commonly associated with undesirable behaviors in ERC20 tokens.

mint_or_burn_function:

There is a public function that changes the token's total supply.

can_selfdestruct:

The contract contains a selfdestruct call. (Note: The EVM no longer supports the SELFDESTRUCT opcode, so this is now a no-op.)

transfer_guarded_by_storage:

The transfer function's execution depends on a storage variable (e.g., a flag or mapping check). This is a signal that transfers can be conditionally blocked by the contract owner or via some internal logic.

transfer_from_guarded_by_storage:

The transferFrom function's execution depends on a storage variable. Same implications as transfer_guarded_by_storage — indicates that delegated transfers can be conditionally blocked.

trading_cooldown:

An address must wait for a certain period after its last transfer before it can transfer tokens again.

view_function_modifies_state:

A function with the signature of one of the view functions defined by EIP-20 updates a storage variable.

has_trading_cap:

The amount of tokens transferred by a single call to transfer cannot exceed a value, either constant or held in storage.

has_trading_cap_functionality:

There is code that could enforce a trading cap. This can be true even if the cap is disabled.

trading_cap_can_be_modified:

The transfer amount cap is held in storage and there is a function that can update it.

has_position_cap:

The amount of tokens an address can hold cannot exceed a value, either constant or held in storage.

has_position_cap_functionality:

There is code that could enforce a position cap. This can be true even if the cap is disabled.

position_cap_can_be_modified:

The position cap is held in storage and there is a function that can update it.

has_owner_functionality:

There is functionality that could let one or more addresses have access to functionality of the token that the rest do not. This can be true even if the owner has been renounced.

owner_address:

The address of the owner.

has_pause_functionality:

The token has code that could pause trading. Can be true even if the current state of the contract does not allow pausing functionality to be re-enabled.

pause_status_can_be_modified:

The pause status can be changed in the future.

has_blacklist_or_whitelist:

Addresses can be restricted from trading the token.

external_call:

There is a call to another contract, whose target is not statically known and/or returns arbitrary data that are used by the token.

timebomb:

Certain functionality is only enabled after a specific timestamp.

has_tax_functionality:

This token has a tax functionality implemented. This could be true even if the current tax is 0 as the taxes could have been wiped.

tax_can_be_modified:

Tax value can be updated.

is_open_source:

This indicates whether the contract's source code is available.

has_open_source_implementation:

For proxy contracts: indicates whether the implementation contract's source code is verified. Only relevant when is_proxy is true. null for non-proxy contracts.

is_proxy:

Indicates if the contract is a proxy contract.

balance_update_function:

A list of function selectors (e.g., "0xa9059cbb") that modify the token's balance storage slot. Expected selectors are transfer and transferFrom; additional selectors may indicate hidden mint/burn or fee-skimming logic.

"balance_update_function": [
"0xa9059cbb",
"0x23b872dd"
]

allowance_update_function:

A list of function selectors that modify the token's allowance storage slot. Expected selectors include approve, transferFrom, increaseAllowance, and decreaseAllowance; unexpected selectors may indicate allowance manipulation.

"allowance_update_function": [
"0x095ea7b3",
"0x23b872dd",
"0x39509351",
"0xa457c2d7"
]

Simulation Features

transfer_success:

A test transfer was simulated on-chain. If false, the transfer failed — the token may block transfers entirely (potential honeypot).

allowance_bypass:

true when some caller can move another holder's tokens through transferFrom without ever having been approved — the shape of a hidden drain backdoor.

Detection is a differential simulation rather than a pattern match, because a backdoor address is rarely a plain literal in the code. Candidate callers are drawn from the declared owner, the address literals in the runtime bytecode, and the ABI-encoded address arguments in the constructor tail of the creation bytecode. Each candidate is simulated calling transferFrom against a control caller that provably holds no approval:

Control callerCandidateVerdict
revertssucceedstrue — address-specific bypass, candidate listed in privileged_spenders
succeedstrue — universal bypass; the token does not enforce allowances at all
revertsrevertsfalse — allowances are enforced

Tri-state. null means the probe could not run (no suitable holder, or the node did not answer) and must not be rendered as safe. Only false is an all-clear.

privileged_spenders:

The addresses observed moving a holder's balance with zero allowance. Empty when allowance_bypass is false, and also when the bypass is universal rather than address-specific — so read it together with allowance_bypass, never on its own.

"allowance_bypass": true,
"privileged_spenders": [
"0x961c7a5dde069aa1a4ea73e5b506e4312105f08d"
]

transfer_tax:

  • send_tax (%): Calculated as the percentage loss from the sender's balance — e.g., if the sender sent 100 tokens and 110 were deducted, the send tax is 10%.
  • receive_tax (%): Calculated as the percentage the recipient received — e.g., if the sender sent 100 tokens and the recipient only received 90, the receive tax is 10%.
  • All values are expressed as percentages (e.g., 0.0 means 0%).

dex:

An array of liquidity pools where the token is paired with one of the chain's quote tokens — the wrapped native or a canonical stablecoin — along with details on liquidity and trading behavior. Launchpad bonding curves are reported here too, as synthetic pools.

{
"pair": "0x...",
"liquidity_type": "UniV2",
"liquidity": 2455608.22,
"buy_success": true,
"buy_tax": 0.0,
"sell_success": true,
"sell_tax": 0.0,
"errorMessage": null,
"errorCode": null,
"pool_id": null,
"is_launchpad": null
}
  • pair: Address of the liquidity pair.

  • liquidity_type: Type of the pool:

    TypeDescription
    UniV2Uniswap V2 or compatible fork
    UniV3Uniswap V3 or compatible fork
    UniV4Uniswap V4 or compatible fork
    SolidlyAerodrome (more Solidly forks coming!)
    SolidlyV3Aerodrome Slipstream
    four.memeFour.Meme bonding curve (BSC)
    flapFlap.sh bonding curve (BSC, Robinhood Chain)
    trench.todayTrench bonding curve (Robinhood Chain)

    The last three are bonding curves rather than DEX pools; they always carry is_launchpad: true.

    Uniswap V4 pools are simulated like V2 and V3. buy_success, sell_success, buy_tax and sell_tax are populated for UniV4 pools, including pools quoted in the chain's native coin and pools sitting behind a custom hook. Earlier releases returned no buy/sell result for V4 and reported every V4 pool as 0% tax; a client that cached those values, or that special-cased V4 as "tax unknown, assume zero", should stop doing so. A hook that taxes a swap now shows up in buy_tax / sell_tax like any other tax.

  • liquidity: USD value of the pool's known-token reserves:

    • Estimated using balanceOf() on the known token — while not exact, it is a practical approximation that serves as a useful indicator of pool health and liquidity status.
  • buy_success: Whether buying the token (e.g., WETH -> token) succeeded. Four-valued — see below.

  • buy_tax (%): Tax incurred on a buy. null or "pending" on the same terms as buy_success.

  • sell_success: Whether selling the token succeeded. Four-valued, same as buy_success.

  • sell_tax (%): Tax incurred on a sell.

  • errorMessage / errorCode: Populated for failed queries (e.g., low liquidity, failed swaps).

  • pool_id: ID of the pool in case of Uniswap V4, otherwise null.

  • is_launchpad: true if this pool is from a launchpad bonding curve (e.g., four.meme, flap.sh, trench.today). null otherwise.

Reading buy_success / sell_successnull is not a failure

These four fields are not booleans. Each carries one of four values, and conflating the last two with false is the most common way to misread a Tok{In} response:

ValueMeaningSafe reading
trueSimulated, and the trade succeededTradeable on this pool
falseSimulated, and the trade failedA real negative signal
"pending"Simulation is still runningNot yet known — poll again
nullNo simulation was attempted for this poolUnknown, carries no signal

null occurs where a swap simulation does not apply or was not run — bonding-curve pools are the common case, since a curve is not swapped against like a DEX pool.

Do not render null or "pending" as "cannot buy" or "cannot sell". A client that treats these as falsy will report a healthy token as unsellable. Branch on === true and === false explicitly and handle the other two as "unknown". If you need a single tradeability verdict, require sell_success === false before calling a token unsellable, not merely "not true".

Because these fields are typed as boolean-or-string, statically typed clients should model them as a union (e.g. bool | "pending" | None) rather than bool.

is_liquid:

This boolean indicates if the token is liquid, i.e. if at least one pool has more than $100 of value in it, measured on the chain's quote token side — WETH/USDC/USDT on most chains, WETH/USDG/USDE on Robinhood Chain.

Notes on liquidity

  • For V2 pools, using the known token side (e.g., WETH in WETH/XYZ) is reliable since the reserves are fixed.
  • For V3 pools, the balanceOf() method on the known token offers a fast heuristic to assess pool liquidity. While it has some limitations — such as including uncollected fees or dust and not reflecting active price ranges — it still provides a strong signal of pool activity and health. In most cases, very low balances are a reliable indicator of illiquidity or abandoned pools.
  • For V4 pools, balanceOf() on the pool address is not viable — all token balances are held by a single PoolManager contract, not per-pool contracts. Liquidity is currently fetched via the CoinGecko API using the pool ID (Base token Liquidity $ / Quote token Liquidity $).
  • For launchpad bonding curve pools (four.meme, flap.sh, trench.today), liquidity is derived from the on-chain reserve data of the bonding curve contract, converted to USD using the quote token price. Curves that quote in the chain's native coin rather than naming a quote token — trench.today, and flap on Robinhood Chain — are valued against the wrapped native.
  • When neither side of a pool is a chain anchor, it can still be valued if a price is available for one side via DefiLlama enrichment. This is what makes Robinhood Chain's tokenised equities usable as quote assets: a launchpad pool quoted in COIN, TSLA, GOOGL or SPCX carries real, reportable liquidity. A pool with no priced side at all is dropped rather than reported at $0.

Launchpad Detection

Tok{In} detects tokens issued by launchpad platforms and reports which platform issued them, on every supported chain.

PlatformSlugChains
Ape.storeape.storeEthereum, BSC, Base, Robinhood Chain
ArenaarenaAvalanche, Robinhood Chain
ArrowPadarrowpadRobinhood Chain
BagsbagsRobinhood Chain
bow.funbow.funRobinhood Chain
CircuscircusRobinhood Chain
ClankerclankerEthereum, BSC, Base, Arbitrum, Robinhood Chain
CoinbarrelcoinbarrelRobinhood Chain
Doppler (bankr, long.xyz)dopplerBase, Robinhood Chain
DYOR Fundyor.funBase, Robinhood Chain
Flap.sh (bonding curve)flapBSC, Base, Robinhood Chain
Four.Meme (bonding curve)four.memeBSC, Base, Arbitrum
HoloLaunch (Holoworld)hololaunchBSC, Robinhood Chain
hood.funhood.funRobinhood Chain
hyper.memehyper.memeRobinhood Chain
KlikklikEthereum, BSC, Robinhood Chain
LaunchHoodlaunchhoodRobinhood Chain
LeaveHoodleavehoodRobinhood Chain
Lemon.funlemon.funRobinhood Chain
letscash.funletscash.funRobinhood Chain
LivolivoEthereum, Robinhood Chain
Lunch.funlunch.funRobinhood Chain
Memecoin.funmemecoin.funRobinhood Chain
MintFastmintfastRobinhood Chain
NoxanoxaRobinhood Chain
o1.exchangeo1.exchangeRobinhood Chain
OROoroRobinhood Chain
Pew.funpew.funRobinhood Chain
Pmav.funpmav.funRobinhood Chain
PonsponsRobinhood Chain
Pons (unofficial fork)pons-forkRobinhood Chain
Potato.fmpotato.fmRobinhood Chain
Real.funreal.funRobinhood Chain
RobinfunrobinfunRobinhood Chain
Stoxesstoxes.funRobinhood Chain
SushisushiBSC, Robinhood Chain
Trench (bonding curve)trench.todayRobinhood Chain
varo.rialtovaro.rialtoRobinhood Chain
Virtuals ProtocolvirtualsBase, Robinhood Chain
Unrecognised launchpadlaunchpadAll chains

Notes on reading the slugs:

  • One slug per platform, not per product line. Where a platform runs several launch routes — Pons V1/V2, Stoxes and its RWA line, o1's crypto- and stock-quoted routes, DYOR Fun's versions — they all report the platform's single slug. Screeners that list those routes separately will show more entries than this table does.
  • pons-fork is an independent operator running the same Pons launcher template. Its tokens look like official Pons tokens, but the launcher belongs to someone else, so it is labelled separately — launchpad reputation is the point of the field, and conflating the two would defeat it.
  • launchpad is a deliberate catch-all. A token that proves it came off a launchpad but whose platform we cannot yet name is still reported as launchpad-issued rather than dropped. Treat it as "yes, launchpad — platform unknown", not as a specific platform.
  • A platform on one chain is not the same product on another. Ape.store, Clanker, Arena and Virtuals are native to Base, Avalanche or Ethereum and also deployed on Robinhood Chain; the slug is the same, the deployment is not.

Detection is exact — it identifies the contract that issued the token, rather than guessing from the token's address. The one exception is documented below.

Graduated tokens (BSC). Four.Meme and Flap tokens mine a vanity address suffix (4444, ffff, 7777, 8888). That suffix is used as a last-resort fallback on BSC only, for tokens that have left their bonding curve for a standard DEX such as PancakeSwap. It is a pattern match rather than an exact one, so it can occasionally label a token whose address ends that way by coincidence; the exact signals are always preferred when available.

Bonding curves appear as pools. Four.Meme, Flap and Trench hold their reserves in a curve contract, so a token still on its curve appears in the dex array with liquidity_type set to the platform slug and is_launchpad: true. Every other platform in the table seeds a standard Uniswap pool at launch, so its tokens carry is_launchpad_token: true while their pools look like ordinary V2/V3/V4 pools.

How a platform is identified

For a curve platform the curve contract itself is the evidence. For everything else the pool is an ordinary Uniswap pool that pair discovery already finds, so only the label is missing, and four exact signals supply it — tried cheapest-first, so most tokens are labelled without an extra RPC call:

#SignalCostExample platforms
1Token deployerFree — already on token metadataVirtuals
2Runtime bytecode hashFree — reuses the static-analysis md5Trench
3Minimal-proxy implementationOne eth_getCodeFlap, Doppler, varo.rialto
4An issuer-naming view callOne eth_call per name triedPons, Noxa, bow.fun, letscash.fun, and new launchpads on those templates

All four are exact matches, not heuristics — the vanity-suffix fallback described above is the only pattern match in the set, and it applies on BSC only.

Signal 4 is where most launchpads land, and templates disagree on what to call the view: Pons and Noxa expose launchFactory(), varo.rialto and bow.fun expose launchpad(), letscash.fun exposes factory(). Each name is tried in turn and the first that names a known launchpad wins.

Signal 4 is also the only one with a generic fallback — an issuer that answers but is not recognised still reports launchpad rather than nothing, which is what keeps a newly launched platform from being silently missed. That fallback is per view name, not blanket: factory() is excluded from it, because liquidity-pool tokens answer factory() with their DEX factory, and treating that as evidence would label every Uniswap LP token on the chain as launchpad-issued.

A platform can match more than one signal. Flap on Robinhood Chain is identifiable by its clone implementation and runs a curve whose reserves are worth reporting as a pool.

  • is_launchpad_token: tri-state.
    • true — the token was issued by a launchpad platform.
    • false — pools were resolved for this token and none of them, nor any provenance signal, indicates a launchpad.
    • nullunknown. No pools were resolved, so no determination could be made. Do not read this as "not a launchpad".
  • launchpad_name: The launchpad platform slug (e.g. "four.meme", "pons", "doppler", or the generic "launchpad"). null if is_launchpad_token is not true.
  • is_launchpad (per pool): true if the specific pool is a launchpad bonding curve. null otherwise. A launchpad token that graduated, or that never ran a curve, has is_launchpad_token: true while every pool in dex has is_launchpad: null — the two fields answer different questions.

Supply & Burn Features

decimals:

Number of decimal places the token uses (e.g., 18 for most ERC20 tokens). Used to convert between raw and human-readable amounts.

supply:

Total supply of the token, normalized by decimals (raw_supply / 10^decimals). This is the human-readable value (e.g., 1000000000 for a token with 1 billion supply).

burned_supply:

Total supply held by known burn addresses (0x000...0000 and 0x000...dead), normalized by decimals. The value is verified on-chain via multicall. 0 if no tokens have been sent to burn addresses.

burned_supply_pct:

Percentage of the total supply held by known burn addresses, capped to 2 decimal places (e.g., 6.13). 0 if no tokens have been burned.

circulating_supply:

Circulating supply of the token, calculated as supply - burned_supply. Represents the tokens that are still in active circulation.

burn_addresses:

An array of burn address balances. Each entry is a holder object with the burn address and its token balance. Only addresses with a balance > 0 are included.

"burn_addresses": [
{
"owner_address": "0x000000000000000000000000000000000000dead",
"token_amount": 61256610.0,
"pct_held": 6.13
}
]

normalized_supply (deprecated):

Use supply instead. Returns the same value as supply. Kept for backwards compatibility.

Other Features

name:

Name of the token.

symbol:

Symbol of the token.

creator_address:

Address of the creator (EOA) of the token.

creator_balance:

Amount of tokens held by the creator (normalized by decimals).

creator_percent:

Percentage of the total supply held by the creator of the token, capped to 2 decimal places.

top_holders:

Top 10 token holders, returned as an array of holder objects. Balances are verified on-chain via multicall.

[
{
"owner_address": "0x...",
"token_amount": 1234567.89,
"pct_held": 12.34
}
]

Each entry in top_holders has the following fields:

  • owner_address: Address of the token holder.
  • token_amount: Amount of tokens held by that address (normalized by decimals).
  • pct_held: Percentage of the total token supply held by that address.

is_in_dex:

The token is in at least one DEX.

cannot_buy:

Returns true if the token cannot be bought through any of the listed pools or if all the pools are too illiquid (less than $100).

owner_can_change_balance:

The token owner can modify any holder's balance directly. This field is part of the extended analysis set and may be absent from the response entirely — an absent field means "not assessed", which is not the same as false. Key off its presence before reading it.

is_launchpad_token:

true if the token was issued by a launchpad platform. false if pools were resolved and none indicates a launchpad. null if no pools were resolved, meaning no determination could be made — see Launchpad Detection for the full platform list.

launchpad_name:

The launchpad platform slug (e.g. "four.meme", "clanker", "doppler", "pons"). Falls back to the generic "launchpad" when the token is provably launchpad-issued but the platform is not yet named. null if is_launchpad_token is not true. The full list of slugs is in Launchpad Detection — treat it as an open set and keep a default branch, since new platforms are added over time.

last_scanned_at:

ISO 8601 UTC timestamp of when this token was last analyzed (e.g., "2025-01-15T12:30:00Z").

Token Safety Summary

The summary endpoint returns a compact, pre-processed view of a token's safety data — designed for dashboards and quick-scan UIs where you need actionable signals without parsing the full feature set.

curl -X 'GET' \
'https://tokin-api.dedaub.com/token/{chain}/{token_address}/summary' \
-H 'accept: application/json' \
-H 'X-API-Key: YOUR-API-KEY'

Response Fields

active_flag_count:

The number of risk signals currently active across the token's static analysis and simulation features. A flag is counted as active when it indicates a potential risk — for example, has_blacklist_or_whitelist: true or transfer_success: false. is_open_source: true is not counted (safe state), and neither is a flag whose value is null — an unknown is not a risk signal, so allowance_bypass: null leaves the count unchanged.

major_flags:

A curated list of three key safety signals covering the most impactful risk categories. Each flag has:

  • label: Human-readable name.
  • description: What the flag means.
  • value: true if the condition is present, false if not, null if unknown.
LabelDerived FromActive When
Access Restrictionshas_blacklist_or_whitelisttrue
Transfer Restrictionshas_trading_cap_functionality or has_position_cap_functionalityeither is true
Has enough liquidityis_liquidfalse (lack of liquidity is the risk)

detected_pool_count:

Total number of liquidity pools found for the token.

dominant_pool:

The pool with the highest liquidity, or null if no pools exist.

  • type: Pool type (e.g. UniV2, UniV3).
  • address: Pool contract address.
  • liquidity: Liquidity in USD.
  • can_buy / can_sell: Whether buys/sells succeed in this pool.
  • buy_tax / sell_tax: Tax as a percentage (e.g. 1.0 = 1%). null if unavailable.

Example

curl -X 'GET' \
'https://tokin-api.dedaub.com/token/ethereum/0x2328434559f7dec44373822cf68052de0d671b7f/summary' \
-H 'accept: application/json' \
-H 'X-API-Key: YOUR-API-KEY'

Result:

{
"active_flag_count": 9,
"major_flags": [
{
"label": "Access Restrictions",
"description": "Addresses can be restricted from trading the token. This could be a blacklist, whitelist, or both.",
"value": true
},
{
"label": "Transfer Restrictions",
"description": "The contract limits how much can be traded in a single transaction or held by a single address.",
"value": true
},
{
"label": "Has enough liquidity",
"description": "The token has at least one WETH, USDC, or USDT pair with more than $100 in liquidity.",
"value": true
}
],
"detected_pool_count": 1,
"dominant_pool": {
"type": "UniV2",
"address": "0xa954213fb0F410c8f1b2fca9B65F11A63ab3fFdb",
"liquidity": 59292.71,
"can_buy": true,
"can_sell": true,
"buy_tax": 1.0,
"sell_tax": 1.0
}
}

Example

curl -X 'GET' \
'https://tokin-api.dedaub.com/token/ethereum/0x2328434559f7dec44373822cf68052de0d671b7f' \
-H 'accept: application/json' \
-H 'X-API-Key: YOUR-API-KEY'

Result:

{
"chain": "ethereum",
"contract_address": "0x2328434559f7dec44373822cf68052de0d671b7f",
"features": {
"mint_or_burn_function": true,
"can_selfdestruct": false,
"transfer_guarded_by_storage": true,
"transfer_from_guarded_by_storage": true,
"trading_cooldown": false,
"view_function_modifies_state": false,
"has_blacklist_or_whitelist": true,
"external_call": true,
"timebomb": true,
"has_pause_functionality": true,
"pause_status_can_be_modified": false,
"has_owner_functionality": true,
"has_tax_functionality": true,
"tax_can_be_modified": false,
"has_trading_cap_functionality": true,
"trading_cap_can_be_modified": false,
"has_position_cap_functionality": true,
"position_cap_can_be_modified": false,
"balance_update_function": [
"0xa9059cbb",
"0x23b872dd",
"0xcd05e4ad",
"0x3bd5d173"
],
"allowance_update_function": [
"0xa9059cbb",
"0x23b872dd",
"0x39509351",
"0xa457c2d7",
"0x95ea7b3"
],
"name": "Simon the Gator",
"symbol": "SIMON",
"decimals": 18,
"supply": 690000000.0,
"normalized_supply": 690000000.0,
"burned_supply": 0.0,
"burned_supply_pct": 0.0,
"circulating_supply": 690000000.0,
"is_open_source": true,
"has_open_source_implementation": null,
"is_liquid": true,
"is_proxy": true,
"owner_address": "0x0000000000000000000000000000000000000000",
"send_tax": 0,
"receive_tax": 1,
"transfer_success": true,
"allowance_bypass": false,
"privileged_spenders": [],
"creator_address": "0x9cb1a958ad57f59a91582b81ac88378c1c12ee58",
"creator_balance": 400000,
"creator_percent": 0.0,
"is_in_dex": true,
"cannot_buy": false,
"is_launchpad_token": false,
"launchpad_name": null,
"has_trading_cap": true,
"has_position_cap": false,
"last_scanned_at": "2025-06-15T10:22:33Z",
"dex": [
{
"errorMessage": null,
"errorCode": null,
"pair": "0xa954213fb0F410c8f1b2fca9B65F11A63ab3fFdb",
"liquidity_type": "UniV2",
"liquidity": 59292.7097022566,
"buy_success": true,
"buy_tax": 1,
"sell_success": true,
"sell_tax": 1,
"pool_id": null,
"is_launchpad": null
}
],
"top_holders": [],
"burn_addresses": []
},
"error": ""
}

API Response Reference

All endpoints use JSON unless otherwise noted. Authentication endpoints redirect via 307.


Common Response Codes

CodeMeaning
200Success
307Redirect (OAuth flows)
400Bad request (invalid input, failed precondition)
401Missing or invalid API key / unauthenticated
404Resource not found
409Conflict (e.g. max API keys reached)
422Validation error (invalid address format, missing params)
429Rate limit or quota exceeded
500Internal server error
503Service not configured (billing)

Token

GET /token/{chain}/{contract_address}

Returns token safety features.

CodeBody / Detail
200TokenResponse with features populated
422TokenResponse with error: "Contract address needs to be EVM compatible"
422TokenResponse with error: "Error validating item data: ..."
500TokenResponse with error: "Unable to retrieve safety features for this token"
500TokenResponse with error: "Error fetching items: ..."
401{"detail": "API Key is missing"} or {"detail": "Invalid API Key"}
429See Rate Limiting

TokenResponse schema:

{
"chain": "ethereum",
"contract_address": "0x...",
"features": { ... },
"error": ""
}

Query param response_format=goplus returns GoPlus-compatible features shape.


GET /token/{chain}/{contract_address}/summary

Returns a compact safety summary. Uses the same cache as the full token endpoint.

CodeBody / Detail
200TokenSummaryResponse
422TokenSummaryResponse with zeroes/nulls (invalid or burn address)
500TokenSummaryResponse with zeroes/nulls (analysis failure)
401{"detail": "API Key is missing"} or {"detail": "Invalid API Key"}
429See Rate Limiting

TokenSummaryResponse schema:

{
"active_flag_count": 9,
"major_flags": [
{
"label": "Access Restrictions",
"description": "...",
"value": true
}
],
"detected_pool_count": 1,
"dominant_pool": {
"type": "UniV2",
"address": "0x...",
"liquidity": 59292.71,
"can_buy": true,
"can_sell": true,
"buy_tax": 1.0,
"sell_tax": 1.0
}
}

Auth

GET /auth/login/{provider}

CodeDetail
307Redirect to OAuth provider (Google or GitHub)

GET /auth/callback/{provider}

CodeDetail
307Redirect to {FRONTEND_URL}/auth/success?token=<jwt> on success
400OAuth callback failure (provider error)

Profile

All profile endpoints require a valid JWT (set via cookie from auth callback).

GET /profile/me

CodeBody
200User object
401{"detail": "Not authenticated"}

GET /profile/api-keys

CodeBody
200Array of APIKey objects
401{"detail": "Not authenticated"}

POST /profile/api-keys

CodeBody / Detail
200Created APIKey object
401{"detail": "Not authenticated"}
409{"detail": "Maximum of N API key(s) allowed per user"}
500{"detail": "Error creating API key"}

DELETE /profile/api-keys/{api_key_id}

CodeBody
200{"message": "API key deleted successfully"}
200{"message": "API key not found or does not belong to the user"} (no-op)
401{"detail": "Not authenticated"}

GET /profile/logs

CodeBody
200Array of APILog objects
401{"detail": "Not authenticated"}

GET /profile/logs_status_codes

CodeBody
200Array of {"status_code": int, "count": int}
401{"detail": "Not authenticated"}

GET /profile/logs_chains

CodeBody
200Array of {"chain": string, "count": int}
401{"detail": "Not authenticated"}

GET /profile/logs_addresses

CodeBody
200Array of {"address": string, "count": int}
401{"detail": "Not authenticated"}

GET /profile/linked-accounts

CodeBody
200Array of {"id", "provider", "provider_id", "email", "linked_at"}
401{"detail": "Not authenticated"}

DELETE /profile/linked-accounts/{account_id}

CodeBody / Detail
200{"message": "Account unlinked successfully"}
200{"message": "Account not found or does not belong to user"} (no-op)
400{"detail": "Cannot unlink last provider account"}
401{"detail": "Not authenticated"}

Rate Limiting

429 responses are returned by the auth middleware for API-key-authenticated endpoints. Three independent checks:

CheckScopeHeaders
Per-minute QPSPer API key (Redis)Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining: 0
Daily quotaPer user (Redis)X-Quota-Daily-Limit, X-Quota-Daily-Used, Retry-After
Monthly quotaPer user (PostgreSQL)X-Quota-Monthly-Limit, X-Quota-Monthly-Used

Admin users bypass all limits. Requests from app.dedaub.com bypass auth and rate limiting entirely.