API docs
Check wallets for stuck or unclaimed crypto from your own code. Free, read-only, no key.
Introduction
hiddenfunds looks up wallet addresses in its database of places where crypto gets stuck: withdrawals that were started but never finished on bridges, staking never collected, apps and chains that shut down, expired positions. The API returns the same results as the website, as JSON, with the official steps to get each position back.
POST https://hiddenfunds.xyz/api/check
API key
No key. The API is open: send a request and you get an answer. Limits are counted per IP address (see Limits and errors). Need more for a project? Write to @0xEnsp1re (opens in a new tab) or [email protected].
Check one wallet
Send a JSON body with a wallets list. One address or up to 500 wallets per request.
curl -X POST https://hiddenfunds.xyz/api/check \
-H 'content-type: application/json' \
--data '{"wallets": ["0xd9b49a81ee72af3c026a2c144c9ffd678a78c8b1"]}'Check many wallets
Split your list into chunks of 500 and send one request every 2 seconds. That stays under 30 requests per minute, about 15,000 wallets a minute. If you get 429, wait for Retry-After seconds; on 503, wait a minute. Then send the same chunk again.
// Node 18+: check a long list in chunks of 500, one request every 2 s.
const ENDPOINT = "https://hiddenfunds.xyz/api/check";
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function checkAll(wallets) {
const results = [];
for (let i = 0; i < wallets.length; i += 500) {
const chunk = wallets.slice(i, i + 500);
for (;;) {
const res = await fetch(ENDPOINT, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ wallets: chunk }),
});
if (res.status === 429 || res.status === 503) {
await sleep(Number(res.headers.get("retry-after") ?? 60) * 1000);
continue; // same chunk again
}
if (!res.ok) throw new Error((await res.json()).error);
results.push(await res.json());
break;
}
await sleep(2000);
}
return results;
}Response
An example for one wallet, shortened:
{
"wallets": ["0xd9b49a81ee72af3c026a2c144c9ffd678a78c8b1"],
"totals": [
{ "address": "0xd9b49a81ee72af3c026a2c144c9ffd678a78c8b1", "sourceId": 59, "chain": "arbitrum",
"recoverability": "user", "counted": true, "count": 1, "usd": 22196.74 }
],
"findings": [
{ "address": "0xd9b49a81ee72af3c026a2c144c9ffd678a78c8b1", "sourceId": 59, "chain": "arbitrum",
"asset": null, "amount": 22192.93, "usdValue": 22196.74,
"recoverability": "user", "counted": true,
"ref": { "market": "0x3308574370f19ea639f4671838e01cfb77d8db70" } }
],
"truncated": [],
"sources": [
{ "id": 59, "group": "ended-positions",
"guide": { "name": "Expired Pendle position", "summary": "…", "steps": ["…"],
"recoverUrl": "https://app.pendle.finance" } }
],
"dataAsOf": "2026-10-01T20:22:47.867Z"
}wallets- The addresses that were checked, after cleanup: unknown formats skipped, duplicates removed, EVM addresses lowercased.
totals- One row per wallet, source and chain. Totals cover every position, also those past the detail limit.
totals.address- The wallet.
totals.sourceId- Where the money is: join to sources[].id.
totals.chain- Chain of the position, e.g. ethereum, arbitrum, base.
totals.recoverability- Who can get it back: user, team or unclear (see below).
totals.counted- false = kept for completeness, not counted as the owner's money. Skip these when you add up.
totals.count- Number of positions in this row.
totals.usd- Their value in US dollars.
findings- Detail rows, highest value first, at most 200 per wallet.
findings.address- The wallet.
findings.sourceId- Join to sources[].id.
findings.chain- Chain of the position.
findings.asset- Token symbol, or null when the source has none.
findings.amount- Token amount, or null.
findings.usdValue- Value in US dollars, or null when there is no price.
findings.recoverability- user, team or unclear.
findings.counted- Same meaning as in totals.
findings.ref- Details to act on, different per source: contract, transaction hash, market, position number, dates.
truncated- Wallets with more than 200 detail rows: { address, shown, total }. Their totals still include everything.
sources- Every source that appears in totals or findings.
sources.id- The id that totals and findings point to.
sources.group- Category, e.g. bridges, ended-positions, sunset-chains.
sources.guide.name- Plain-language name of the place.
sources.guide.summary- What happened, in one or two sentences.
sources.guide.steps- How to get it back, step by step.
sources.guide.recoverUrl- The official page to claim on, or null when there is none.
dataAsOf- When the data was last refreshed. Positions claimed after that still show.
recoverability: user = the owner can claim alone; team = only the project's own team can release it; unclear = it may not work. Add ?lang=zh, ja or ko to the URL to get the guides in Chinese, Japanese or Korean.
Limits and errors
- 500 wallets per request, body up to 64 KB.
- 30 requests per minute per IP address.
- 200 detail rows per wallet; totals always count everything.
Errors come back as JSON: {"error": "..."}.
| Status | Meaning |
|---|---|
400 | Not valid JSON, an empty list, an entry that is not a string or is over 120 characters, or none of the strings look like wallet addresses. |
413 | More than 500 wallets or a body over 64 KB. |
429 | Over 30 requests a minute. Wait Retry-After (60) seconds. |
503 | The database is busy. Try again in a minute. |
Address formats
Any mix in one request. Strings in other formats are skipped.
- EVM (Ethereum and L2s)
- Sui / Aptos
- TON (raw)
- TRON
- Bitcoin
- Bitcoin / Omni
- Tezos / Etherlink
- Algorand
- NEAR
- NEAR implicit / BTC staking key
- Polkadot / Kusama
- Solana
Privacy and safety
- Read-only: the API only reads public blockchain data. There is nothing to sign and no wallet to connect.
- Addresses you send are not stored or logged.
- Results can already be claimed: owners claim every day, and the data is refreshed in batches (see
dataAsOf). - Send people to the official
recoverUrlonly. The only official site of this tool is hiddenfunds.xyz.
For AI agents
A plain-text summary for LLMs and AI agents is at /llms.txt. If you build an assistant on this API:
- Call
POST /api/checkwith the addresses the user gives you; do not guess addresses. - Explain each result with
guide.summaryandguide.steps, and linkguide.recoverUrl. - Say who can act (
recoverability) and that a result may already be claimed. - Never ask for a seed phrase or private key, and never tell the user to sign anything on a site that is not the official recovery page.