A free, chain-agnostic API for EVM token search and bulk USD pricing, with 1h/24h/7d price changes and token metadata. No signup, no API key, CORS enabled.
Token identity is { chainId, address }. Addresses are case-insensitive. Native
currencies use the literal address native. Responses identify chains by numeric
chainId only.
| Endpoint | Description |
|---|---|
GET /v1 |
Machine-readable endpoint index. |
GET /v1/chains |
Supported chains with token counts. |
GET /v1/search |
Search by name, symbol, or exact address, ordered by market cap. |
GET /v1/tokens/{chainId}/{address} |
Metadata for one token. |
GET /v1/prices |
Cacheable bulk USD prices, price changes, and metadata for up to 50 tokens. |
GET /health |
Readiness and catalog status. |
curl 'https://tokens.stupidtech.net/v1/search?q=usdc&chainId=8453&limit=5'
q is required (2–100 characters) and matches a case-insensitive name or symbol
substring (a 2-character query matches prefixes), or an exact contract address.
chainId and limit (1–100, default 20) are optional. Results are
ordered by stored market cap descending, with unknown caps last, and are edge-cached for up to
60 seconds.
{
"tokens": [
{
"chainId": 8453,
"address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
"name": "USDC",
"symbol": "USDC",
"decimals": 6,
"imageUrl": "https://assets.coingecko.com/coins/images/6319/large/USDC.png",
"marketCapUsd": "74000000000",
"marketCapUpdatedAt": "2026-09-20T18:48:50.540Z",
"metadataUpdatedAt": "2026-09-20T18:48:50.540Z"
}
]
}
curl 'https://tokens.stupidtech.net/v1/tokens/1/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
Returns the metadata object shown above. An unlisted address on an imported chain is checked against its contract's ERC-20 metadata and stored on success; unresolved addresses return HTTP 404.
Tokens are comma-separated as chainId:address, and are sorted and deduplicated
automatically. Non-canonical requests receive a 308 redirect to the canonical
URL.
curl 'https://tokens.stupidtech.net/v1/prices?tokens=1:native,8453:0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'
The response is sent with Cache-Control: public, max-age=N, where
N is bounded by the next permitted refresh and any change from ok to
stale across the batch. It is never longer than five minutes. Stale prices remain
available and are cached until a refresh becomes possible, or served with
no-store when a refresh is already allowed.
One result per requested token, in canonical order. A valid batch returns HTTP 200 even when
individual tokens are unavailable. Each entry includes token metadata (name,
symbol, decimals, imageUrl,
metadataUpdatedAt) so a separate metadata request is not needed; these are
null for a not_found token.
{
"currency": "usd",
"prices": [
{
"chainId": 1,
"address": "native",
"name": "Ether",
"symbol": "ETH",
"decimals": 18,
"imageUrl": "https://coin-images.coingecko.com/coins/images/279/large/ethereum.png",
"status": "ok",
"priceUsd": "2629.256297515841",
"priceUpdatedAt": "2026-09-20T18:53:00.000Z",
"priceChange": { "h1": "0.42", "h24": "-1.35", "d7": "6.08" },
"marketCapUsd": null,
"marketCapUpdatedAt": null,
"metadataUpdatedAt": "2026-09-20T18:48:50.540Z",
"fetchedAt": "2026-09-20T18:53:02.000Z",
"nextRefreshAt": "2026-09-20T18:58:00.000Z"
}
]
}
priceChange holds percent changes over the last hour (h1), day
(h24), and week (d7), or null for a window with no
value. Changes come from DefiLlama's aggregation and are withheld whenever the entry is not
ok.
| Status | Meaning |
|---|---|
ok |
Price available, source timestamp within 5 minutes. |
stale |
Source timestamp older than 5 minutes or missing; the known price is returned. |
not_found |
Chain is not imported, or the contract could not be resolved on demand. |
price_unavailable |
No usable price from the latest refresh; a previously known price is retained. |
upstream_error |
The refresh failed or was interrupted; a previously known price is retained. |
rate_limited |
A source or shared budget limited the refresh; a previously known price is retained. |
Prices refresh on demand, at most once per token per 5 minutes, shared across callers.
priceUsd returns the last known price even when stale or a refresh fails, and is
null only when no price is known. Check priceUsd for availability,
status for freshness or the latest refresh outcome, and
priceUpdatedAt for the quote's source time. A retained price keeps its original
priceUpdatedAt and fetchedAt; nextRefreshAt indicates
when another attempt is allowed.
Metadata and market caps are stored locally and search never contacts an upstream provider.
Exact unlisted contract addresses on imported chains can be discovered from onchain ERC-20
metadata when metadata or prices are requested. Failed lookups have a shared five-minute
cooldown; unresolvable contracts return not_found.
Prices and percent price changes come from DefiLlama's aggregation. GeckoTerminal and DexScreener provide liquidity-gated price fallbacks and market caps; GeckoTerminal also supplies an image when the token list does not. Token metadata comes from CoinGecko token lists or, for unlisted contracts, directly from the contract; images use the largest available size (250×250). Native currencies have no list entry, so their logo is resolved from the chain's native coin, falling back to the chain image.
Up to 50 tokens per price request and 100 search results per request. The service is free and unauthenticated, so please cache responses and avoid tight polling.