Import a token over the API
Importing registers a token that was created somewhere else: a wallet proves it controls the token, and the token gets its verified page. On the site this is Import an Existing Token. This page does the same thing from code, in five calls.
You need an API key and the wallet that controls the token: the one that deployed it, owns the contract, holds a majority of the supply, or (on Solana) holds its mint or update authority. The wallet signs one transaction; nothing here needs a session. Every field of every call is in the API Explorer under Registrations.
1. Find what the wallet can import
curl -H "X-API-Key: $CHAINDADDY_API_KEY" \
-H "X-Wallet-Address: 0x1234567890abcdef1234567890abcdef12345678" \
https://api.chaindaddy.io/api/v2/registration/claimable{
"tokens": [
{
"address": "0x6982508145454ce325ddbe47a25d4ec3d2311933",
"chainId": "8453",
"symbol": "MYTKN",
"name": "My Token",
"qualification": { "method": "deployer", "confidence": 1, "message": "You deployed this token" }
}
],
"total": 1
}Tokens that are already registered are left out, so {"tokens": [], "total": 0} means there is nothing to import. The wallet goes in the X-Wallet-Address header on every call to this route, session or not; without it the answer is 400. A 503 means the lookup failed, not that the list is empty: retry.
This list only finds deployers and Solana authorities. A wallet that qualifies another way (contract owner, majority holder) will not see its token here, but step 2 still says yes.
2. Check one token
curl -X POST https://api.chaindaddy.io/api/v2/registration/check-qualify \
-H "X-API-Key: $CHAINDADDY_API_KEY" -H "Content-Type: application/json" \
-d '{
"wallet": "0x1234567890abcdef1234567890abcdef12345678",
"tokenAddress": "0x6982508145454ce325ddbe47a25d4ec3d2311933",
"chainId": 8453,
"symbol": "MYTKN"
}'{
"eligible": true,
"qualification": { "method": "deployer", "confidence": 1, "message": "You deployed this token" },
"price": 15,
"currency": "USD",
"proTrialDays": 0
}price is what importing costs; 0 means free, as it is for a token launched through Chain Daddy. When eligible is false, reason says why:
reason | Meaning |
|---|---|
not_eligible | The chain shows no way this wallet controls the token. |
already_claimed | The token is registered. Read who holds it with GET /api/v2/registration/{symbol}/{chain}. |
copycat, not_claimable | The wallet qualifies, but the token cannot be registered: it imitates an established token, or is a major coin. claimability carries the reason and a supportEmail to contest it. |
Send symbol: without it an existing registration is not detected and a free import is quoted at full price.
3. Build the transaction
curl -X POST https://api.chaindaddy.io/api/v2/claim \
-H "X-API-Key: $CHAINDADDY_API_KEY" -H "Content-Type: application/json" \
-d '{
"symbol": "MYTKN",
"chainId": 8453,
"tokenAddress": "0x6982508145454ce325ddbe47a25d4ec3d2311933",
"walletAddress": "0x1234567890abcdef1234567890abcdef12345678"
}'{
"success": true,
"transaction": { "to": "0x…", "data": "0x…", "value": "0x2386f26fc10000", "gasLimit": 250000, "chainId": 8453 },
"feeEstimate": { "contractFee": "0x2386f26fc10000", "gasEstimate": 250000, "gasPrice": "0x…", "totalGasCost": "0x…", "totalEstimate": "0x…" },
"message": "Sign and submit the transaction to claim your token page"
}The server checks ownership again here, from the chain, before it builds anything. Nothing is signed or sent for you: transaction is unsigned. value is the registration fee, paid in the chain's native coin; feeEstimate.totalEstimate adds the gas (the network's charge for running a transaction). Every amount is wei, as a hex string.
4. Sign and send it
Send the transaction from the same wallet, with any wallet library. With viem:
const { transaction: t } = await res.json(); // res: the response from step 3
const hash = await wallet.sendTransaction({ to: t.to, data: t.data, value: BigInt(t.value) });5. Confirm it landed
curl -H "X-API-Key: $CHAINDADDY_API_KEY" \
"https://api.chaindaddy.io/api/v2/claim/status/0xc1377ce582266b185e571766406924b0ba4537627692ae0dae007c2ac3aa8730?chainId=8453"{ "txHash": "0xc1377ce5…8730", "status": "confirmed", "confirmations": 332408, "blockNumber": 51807835 }status is pending, confirmed or failed. Always pass chainId: left out, the lookup reads Arbitrum and reports a transaction on any other chain as missing. Once it confirms, GET /api/v2/registration/MYTKN/base answers "status": "claimed" with your wallet as owner, and the page is live at chaindaddy.io/MYTKN.
If a step is refused
Errors carry a message in error and a stable code.
| Status | code | Meaning |
|---|---|---|
400 | VALIDATION_INVALID_INPUT | A field is missing, or the chain is not one tokens are registered on. |
403 | CLAIM_UNAUTHORIZED | The chain shows no way this wallet controls the token. |
409 | CLAIM_DUPLICATE | The symbol is already registered on this chain. |
422 | TOKEN_NOT_REGISTRABLE | A copycat or a major coin. check names the rule. |
503 | TOKEN_UNVERIFIED | The token could not be checked right now. Retry shortly. |
Solana
Steps 1 and 2 are the same, with "chainId": "solana". For step 3, POST /api/v2/claim/solana/build takes { "claimer", "symbol", "tokenMint" } and returns the unsigned transaction as base64, with the registration's account address (crownPda). Sign and send it, then read GET /api/v2/claim/solana/status/{symbol}.
Before and after
- Is the ticker usable?
POST /api/v2/verify/symbolwith{ "symbol" }answersallowed,warning(it resembles a well-known asset),og_required(only the original project may register it) orblocked. - Who holds a ticker?
GET /registration/v2/symbol/{symbol}/all-chainslists every registration of it, one per chain. This route andGET /registration/unified/{symbol}have no/api/v2prefix. - Is it healthy?
GET /api/v2/heartbeat/{symbol}/{chain}returns the score that keeps a registration alive (EVM chains). See Token Health. - Edit the page.
PUT /api/v2/registration/{id}/profile?chain=basechanges the name, description, links and media. It needs a session for the owner or a manager, andchainis required because the same id names a different page on each chain. Send only the fields you are changing.
Where a path takes {chain}, use a chain key (eth, base, arbitrum, polygon, bnb, avax, robinhood, solana) or a numeric chain id.