Appearance
Claimable API
Detect claimable token registrations for a connected wallet and check individual token eligibility.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v2/registration/claimable | Detect all claimable registrations for a wallet |
POST | /api/v2/registration/check-qualify | Check if a wallet qualifies for a specific token |
Detect Claimable Registrations
GET /api/v2/registration/claimableReturns the tokens a wallet can claim, based on the platform's on-chain provenance index across all supported chains. Used by the QuickClaim feature.
Headers
| Header | Required | Description |
|---|---|---|
X-API-Key | Yes | API key for authentication |
X-Wallet-Address | Yes* | Wallet address to scan (EVM or Solana) |
*If the request carries an authenticated wallet session (Authorization: Bearer <JWT>), the wallet is taken from the session and the X-Wallet-Address header is not needed. The header remains supported for API-key-only callers.
How Detection Works
- Provenance lookup: The platform keeps a reverse index of on-chain provenance (deployer, mint authority, update authority, majority holder) for tokens it has seen; the wallet is matched against it, with an indexer fallback for tokens that predate local capture
- Registration check: Tokens that already have active registrations (
claimedorgrace_period) are filtered out - Qualification mapping: Each remaining token is annotated with how the wallet qualifies
- Sort: Results ordered by qualification strength (deployer first)
Chains Scanned
| Chain | Chain ID | Detection Methods |
|---|---|---|
| Solana | solana | Deployer, Mint Authority, Update Authority, Majority Holder |
| Arbitrum | 42161 | Deployer, Majority Holder |
| Base | 8453 | Deployer, Majority Holder |
| Polygon | 137 | Deployer, Majority Holder |
| BNB Chain | 56 | Deployer, Majority Holder |
| Gnosis | 100 | Deployer, Majority Holder |
| Ethereum | 1 | Deployer, Majority Holder |
Response Format
json
{
"tokens": [
{
"address": "0x6982508145454ce325ddbe47a25d4ec3d2311933",
"chainId": "42161",
"symbol": "PEPE",
"name": "Pepe",
"qualification": {
"method": "deployer",
"confidence": 1.0,
"message": "You deployed this token"
}
}
],
"total": 1
}Response Fields
| Field | Type | Description |
|---|---|---|
tokens | array | List of tokens the wallet can claim |
tokens[].address | string | Token contract address |
tokens[].chainId | string | Chain identifier (numeric string for EVM, solana:... for Solana) |
tokens[].symbol | string | Token symbol |
tokens[].name | string | Token name |
tokens[].qualification | object | How the wallet qualifies |
tokens[].qualification.method | string | Qualification method (see table below) |
tokens[].qualification.confidence | number | Confidence score (0-1) |
tokens[].qualification.message | string | Human-readable explanation |
total | integer | Number of claimable tokens returned |
The claim fee is not included per token — fetch it once from GET /api/v2/registration/fee.
Qualification Methods
Results are sorted by method priority (highest priority first):
| Priority | Method | Confidence | Chains | Description |
|---|---|---|---|---|
| 1 | deployer | 1.0 | All | Wallet deployed the token contract |
| 2 | mint_authority | 0.95 | Solana | Wallet is the token's mint authority |
| 3 | update_authority | 0.9 | Solana | Wallet is the token's update authority |
| 4 | majority_holder | 0.8 | All | Wallet holds >50% of token supply |
majority_holder is evaluated by the live check-qualify endpoint; the detect endpoint's provenance index currently surfaces the first three methods.
Code Examples
bash
curl https://api.chaindaddy.io/api/v2/registration/claimable \
-H "X-API-Key: cd_live_abc123..." \
-H "X-Wallet-Address: 0x1234567890abcdef1234567890abcdef12345678"javascript
async function getClaimableTokens(apiKey, walletAddress) {
const response = await fetch('https://api.chaindaddy.io/api/v2/registration/claimable', {
headers: {
'X-API-Key': apiKey,
'X-Wallet-Address': walletAddress,
},
});
const data = await response.json();
console.log(`Found ${data.total} claimable tokens`);
return data.tokens;
}
// Usage
const claimable = await getClaimableTokens('cd_live_abc123...', '0x1234...5678');
for (const item of claimable) {
console.log(`${item.symbol} on chain ${item.chainId}, ${item.qualification.method}`);
}python
import requests
def get_claimable_tokens(api_key, wallet_address):
response = requests.get(
"https://api.chaindaddy.io/api/v2/registration/claimable",
headers={
"X-API-Key": api_key,
"X-Wallet-Address": wallet_address,
},
)
response.raise_for_status()
data = response.json()
print(f"Found {data['total']} claimable tokens")
return data["tokens"]
# Usage
claimable = get_claimable_tokens("cd_live_abc123...", "0x1234...5678")
for item in claimable:
print(f"{item['symbol']} on chain {item['chainId']} "
f"({item['qualification']['method']})")Check Qualification
POST /api/v2/registration/check-qualifyCheck if a specific wallet qualifies to claim a registration for a specific token. Use this to verify eligibility before initiating a claim transaction.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
wallet | string | Yes | Wallet address to check |
tokenAddress | string | Yes | Token contract address |
chainId | integer/string | No | Chain ID (integer for EVM, "solana" for Solana) |
symbol | string | No | Token symbol (used to check existing registration status) |
Response Format
Eligible:
json
{
"success": true,
"eligible": true,
"qualification": {
"method": "deployer",
"confidence": 1.0,
"message": "You deployed this token"
},
"price": 15.0,
"currency": "USD"
}Not eligible:
json
{
"success": true,
"eligible": false,
"reason": "not_eligible"
}Already claimed:
json
{
"success": true,
"eligible": false,
"reason": "already_claimed"
}Response Fields
| Field | Type | Description |
|---|---|---|
eligible | boolean | Whether the wallet can claim this token |
reason | string | Reason for ineligibility: not_eligible or already_claimed |
qualification | object | Qualification details (only present when eligible) |
qualification.method | string | Detected ownership method |
qualification.confidence | number | Confidence score (0-1) |
qualification.message | string | Human-readable description |
price | number | Claim fee in USD (only present when eligible) |
currency | string | Fee currency (only present when eligible) |
Code Examples
bash
curl -X POST https://api.chaindaddy.io/api/v2/registration/check-qualify \
-H "X-API-Key: cd_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"wallet": "0x1234567890abcdef1234567890abcdef12345678",
"tokenAddress": "0x6982508145454ce325ddbe47a25d4ec3d2311933",
"chainId": 42161,
"symbol": "PEPE"
}'javascript
async function checkQualification(apiKey, wallet, tokenAddress, chainId, symbol) {
const response = await fetch('https://api.chaindaddy.io/api/v2/registration/check-qualify', {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({ wallet, tokenAddress, chainId, symbol }),
});
const data = await response.json();
if (data.eligible) {
console.log(`Eligible via ${data.qualification.method}`);
console.log(`Claim fee: $${data.price} ${data.currency}`);
} else {
console.log(`Not eligible: ${data.reason}`);
}
return data;
}
// Usage
const result = await checkQualification(
'cd_live_abc123...',
'0x1234...5678',
'0x6982...1933',
42161,
'PEPE'
);python
import requests
def check_qualification(api_key, wallet, token_address, chain_id, symbol=None):
payload = {
"wallet": wallet,
"tokenAddress": token_address,
"chainId": chain_id,
}
if symbol:
payload["symbol"] = symbol
response = requests.post(
"https://api.chaindaddy.io/api/v2/registration/check-qualify",
headers={
"X-API-Key": api_key,
"Content-Type": "application/json",
},
json=payload,
)
response.raise_for_status()
data = response.json()
if data["eligible"]:
print(f"Eligible via {data['qualification']['method']}")
print(f"Claim fee: ${data['price']} {data['currency']}")
else:
print(f"Not eligible: {data['reason']}")
return data
# Usage
result = check_qualification(
"cd_live_abc123...",
"0x1234...5678",
"0x6982...1933",
42161,
"PEPE",
)Common Recipes
QuickClaim Flow (Detect + Claim)
Detection tells you what the wallet can claim. To actually claim, run the standard claim pipeline: POST /api/v2/claim/message → sign → POST /api/v2/claim/verify → POST /api/v2/claim (see the full claim walkthrough).
javascript
async function quickClaimFlow(apiKey, signer) {
const walletAddress = await signer.getAddress();
const post = (path, body) => fetch(`https://api.chaindaddy.io${path}`, {
method: 'POST',
headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify(body),
}).then(r => r.json());
// 1. Detect claimable tokens
const claimable = await getClaimableTokens(apiKey, walletAddress);
if (claimable.length === 0) {
console.log('No claimable tokens found');
return;
}
// 2. Show results to user (sorted by qualification strength)
for (const item of claimable) {
console.log(
`${item.symbol} on chain ${item.chainId} ` +
`(${item.qualification.method}, confidence: ${item.qualification.confidence})`
);
}
// 3. Claim the first token (user selects in UI)
const selected = claimable[0];
const chainId = parseInt(selected.chainId, 10);
// 3a. Get the ownership message and sign it
const { message, timestamp } = await post('/api/v2/claim/message', {
symbol: selected.symbol,
chainId,
tokenAddress: selected.address,
claimerAddress: walletAddress,
});
const signature = await signer.signMessage(message);
// 3b. Verify ownership
const verification = await post('/api/v2/claim/verify', {
symbol: selected.symbol,
chainId,
tokenAddress: selected.address,
walletAddress,
signature,
timestamp,
});
if (!verification.verified) throw new Error('Ownership verification failed');
// 3c. Build the claim transaction
const claim = await post('/api/v2/claim', {
symbol: selected.symbol,
chainId,
tokenAddress: selected.address,
walletAddress,
proofHash: verification.proofHash,
});
// 4. Sign and submit
const tx = await signer.sendTransaction(claim.transaction);
await tx.wait();
console.log(`Claimed ${selected.symbol} registration`);
}Check Before Manual Claim
python
import requests
BASE_URL = "https://api.chaindaddy.io"
def claim_if_eligible(api_key, signer, token_address, chain_id, symbol):
wallet = signer.address
def post(path, body):
res = requests.post(
f"{BASE_URL}{path}",
headers={"X-API-Key": api_key, "Content-Type": "application/json"},
json=body,
)
res.raise_for_status()
return res.json()
# 1. Check qualification
result = check_qualification(api_key, wallet, token_address, chain_id, symbol)
if not result["eligible"]:
if result["reason"] == "already_claimed":
print(f"{symbol} is already claimed on this chain")
else:
print(f"Not eligible to claim {symbol}")
return None
print(f"Eligible via {result['qualification']['method']}")
print(f"Fee: ${result['price']} {result['currency']}")
# 2. Get the ownership message and sign it
msg = post("/api/v2/claim/message", {
"symbol": symbol, "chainId": chain_id,
"tokenAddress": token_address, "claimerAddress": wallet,
})
signature = signer.sign_message(msg["message"]) # your wallet library
# 3. Verify ownership
verification = post("/api/v2/claim/verify", {
"symbol": symbol, "chainId": chain_id,
"tokenAddress": token_address, "walletAddress": wallet,
"signature": signature, "timestamp": msg["timestamp"],
})
if not verification["verified"]:
print("Ownership verification failed")
return None
# 4. Build the claim transaction, then sign and submit it
claim = post("/api/v2/claim", {
"symbol": symbol, "chainId": chain_id,
"tokenAddress": token_address, "walletAddress": wallet,
"proofHash": verification["proofHash"],
})
return signer.send_transaction(claim["transaction"])
# Usage
tx = claim_if_eligible(
"cd_live_abc123...",
signer,
"0x6982...1933",
42161,
"PEPE",
)Error Responses
| Status | Code | Description |
|---|---|---|
400 | INVALID_PARAMS | Missing wallet address header or invalid request body |
403 | FORBIDDEN | Invalid API key or insufficient tier |
429 | RATE_LIMITED | Rate limit exceeded |
Timeout
The claimable endpoint runs with a 15-second server-side timeout. Wallets with large token histories may take several seconds to resolve.
See Authentication for details on error handling and retry strategies.