Token Approvals & Allowances
Monitor token approvals and allowances to protect your wallet from malicious contracts.
Try it Live
Open in Swagger UI โ to test these endpoints interactively.
Endpointsโ
| Endpoint | Description | Price |
|---|---|---|
GET /api/approvals/{address} | Active approvals | $0.02 |
GET /api/allowances/{address} | Token allowances | $0.01 |
GET /api/approvals/{address}โ
Get all active token approvals for a wallet address.
Requestโ
curl "https://api.web3identity.com/api/approvals/0xYourAddress?chain=ethereum"
Query Parametersโ
| Parameter | Type | Default | Description |
|---|---|---|---|
chain | string | ethereum | Chain: ethereum, polygon, arbitrum, optimism, base, bsc |
includeNFTs | boolean | true | Include NFT approvals |
includeRevoked | boolean | false | Include revoked approvals |
Responseโ
{
"address": "0xYourAddress",
"chain": "ethereum",
"totalApprovals": 23,
"riskScore": 45,
"risk": "MEDIUM",
"approvals": [
{
"token": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"type": "ERC20"
},
"spender": {
"address": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
"name": "Uniswap Universal Router",
"verified": true,
"protocol": "Uniswap V3"
},
"allowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"allowanceFormatted": "unlimited",
"approvedAt": {
"block": 18901234,
"timestamp": "2024-11-15T10:30:00Z",
"transaction": "0xabc..."
},
"lastUsed": {
"block": 19123456,
"timestamp": "2025-01-20T15:45:00Z"
},
"risk": {
"level": "LOW",
"score": 15,
"reasons": ["Verified protocol", "Active usage"]
},
"recommendations": {
"action": "monitor",
"reason": "Active, verified protocol"
}
},
{
"token": {
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"type": "ERC20"
},
"spender": {
"address": "0x1234567890123456789012345678901234567890",
"name": "Unknown Contract",
"verified": false,
"protocol": null
},
"allowance": "10000000000",
"allowanceFormatted": "10000 USDT",
"approvedAt": {
"block": 17890123,
"timestamp": "2024-03-10T08:15:00Z",
"transaction": "0xdef..."
},
"lastUsed": null,
"risk": {
"level": "HIGH",
"score": 75,
"reasons": [
"Unverified contract",
"Never used",
"6+ months old"
]
},
"recommendations": {
"action": "revoke",
"reason": "Unverified contract with no usage",
"urgency": "high"
}
},
{
"token": {
"address": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
"name": "Bored Ape Yacht Club",
"symbol": "BAYC",
"type": "ERC721"
},
"spender": {
"address": "0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC",
"name": "Seaport 1.5",
"verified": true,
"protocol": "OpenSea"
},
"approvalType": "setApprovalForAll",
"approved": true,
"approvedAt": {
"block": 18567890,
"timestamp": "2024-09-05T12:00:00Z",
"transaction": "0xghi..."
},
"risk": {
"level": "MEDIUM",
"score": 40,
"reasons": [
"NFT full approval",
"Verified marketplace"
]
},
"recommendations": {
"action": "review",
"reason": "Consider revoking when not actively trading"
}
}
],
"summary": {
"byRisk": {
"LOW": 8,
"MEDIUM": 10,
"HIGH": 4,
"CRITICAL": 1
},
"byType": {
"ERC20": 18,
"ERC721": 3,
"ERC1155": 2
},
"recommendations": {
"revoke": 5,
"review": 8,
"monitor": 10
}
}
}
GET /api/allowances/{address}โ
Get specific token allowances for spenders.
Requestโ
curl "https://api.web3identity.com/api/allowances/0xYourAddress?chain=ethereum&token=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
Query Parametersโ
| Parameter | Type | Default | Description |
|---|---|---|---|
chain | string | ethereum | Chain name |
token | string | - | Filter by token address |
spender | string | - | Filter by spender address |
Responseโ
{
"address": "0xYourAddress",
"chain": "ethereum",
"token": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6
},
"balance": "5000000000",
"balanceFormatted": "5000 USDC",
"allowances": [
{
"spender": {
"address": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
"name": "Uniswap Universal Router",
"verified": true
},
"allowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"allowanceFormatted": "unlimited",
"percentOfBalance": "unlimited",
"canSpend": "all"
},
{
"spender": {
"address": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
"name": "Uniswap V2 Router",
"verified": true
},
"allowance": "1000000000",
"allowanceFormatted": "1000 USDC",
"percentOfBalance": "20%",
"canSpend": "1000 USDC"
}
],
"totalAllowance": "unlimited"
}
Risk Levelsโ
| Risk | Score | Criteria | Action |
|---|---|---|---|
| LOW | 0-30 | Verified protocol, active usage | Monitor |
| MEDIUM | 31-60 | Known protocol, infrequent use | Review |
| HIGH | 61-80 | Unverified, old, or unused | Revoke |
| CRITICAL | 81-100 | Malicious contract, exploited | Revoke immediately |
Risk Factorsโ
| Factor | Weight | Description |
|---|---|---|
| Unverified contract | +40 | Contract not verified on block explorer |
| Unlimited allowance | +20 | Approval for max uint256 |
| Never used | +25 | Approval granted but never utilized |
| Old approval (>6mo) | +15 | Stale approval |
| Protocol exploit history | +50 | Protocol has been exploited before |
| NFT setApprovalForAll | +15 | Full NFT collection approval |
SDK Examplesโ
JavaScriptโ
import { Web3IdentityClient } from '@web3identity/sdk';
const client = new Web3IdentityClient();
// Get all approvals
const approvals = await client.getApprovals(
'0xYourAddress',
{ chain: 'ethereum', includeNFTs: true }
);
console.log(`Total Approvals: ${approvals.totalApprovals}`);
console.log(`Risk Score: ${approvals.riskScore}/100 (${approvals.risk})`);
// High-risk approvals
const highRisk = approvals.approvals.filter(
a => a.risk.level === 'HIGH' || a.risk.level === 'CRITICAL'
);
if (highRisk.length > 0) {
console.log(`\nโ ๏ธ ${highRisk.length} high-risk approvals found:`);
highRisk.forEach(approval => {
console.log(` ${approval.token.symbol} โ ${approval.spender.name || approval.spender.address}`);
console.log(` Risk: ${approval.risk.level} (${approval.risk.score})`);
console.log(` Reasons: ${approval.risk.reasons.join(', ')}`);
console.log(` Action: ${approval.recommendations.action.toUpperCase()}`);
});
}
// Unlimited approvals
const unlimited = approvals.approvals.filter(
a => a.allowanceFormatted === 'unlimited'
);
console.log(`\n๐ Unlimited approvals: ${unlimited.length}`);
// Get specific token allowances
const usdcAllowances = await client.getAllowances(
'0xYourAddress',
{
chain: 'ethereum',
token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
}
);
console.log(`\nUSDC Allowances:`);
console.log(`Balance: ${usdcAllowances.balanceFormatted}`);
usdcAllowances.allowances.forEach(a => {
console.log(` ${a.spender.name}: ${a.allowanceFormatted}`);
});
// Generate revoke transactions (pseudo-code)
const toRevoke = approvals.approvals.filter(
a => a.recommendations.action === 'revoke'
);
console.log(`\n๐ด Recommended revocations: ${toRevoke.length}`);
toRevoke.forEach(approval => {
console.log(` ${approval.token.symbol} โ ${approval.spender.address}`);
// In practice, would generate revoke transaction
});
Pythonโ
from web3identity import Client
client = Client()
# Get all approvals
approvals = client.get_approvals(
'0xYourAddress',
chain='ethereum',
include_nfts=True
)
print(f"Total Approvals: {approvals['totalApprovals']}")
print(f"Risk Score: {approvals['riskScore']}/100 ({approvals['risk']})")
# Analyze by risk level
print("\n๐ Approvals by Risk Level:")
for risk_level, count in approvals['summary']['byRisk'].items():
print(f" {risk_level}: {count}")
# Find revoke candidates
revoke_list = [
a for a in approvals['approvals']
if a['recommendations']['action'] == 'revoke'
]
print(f"\n๐ด Approvals to revoke: {len(revoke_list)}")
for approval in revoke_list:
token = approval['token']['symbol']
spender = approval['spender'].get('name') or approval['spender']['address'][:10]
print(f" {token} โ {spender}")
print(f" Reasons: {', '.join(approval['risk']['reasons'])}")
# Check specific token
def check_token_exposure(address, token_address, chain='ethereum'):
allowances = client.get_allowances(
address,
chain=chain,
token=token_address
)
total_exposure = 0
unlimited = False
for allowance in allowances['allowances']:
if allowance['allowanceFormatted'] == 'unlimited':
unlimited = True
break
total_exposure += float(allowance['allowance'])
return {
'token': allowances['token']['symbol'],
'balance': allowances['balanceFormatted'],
'spenders': len(allowances['allowances']),
'unlimited': unlimited,
'total_exposure': 'unlimited' if unlimited else total_exposure
}
usdc_exposure = check_token_exposure(
'0xYourAddress',
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
)
print(f"\nUSDC Exposure: {usdc_exposure}")
# NFT approval audit
nft_approvals = [
a for a in approvals['approvals']
if a['token']['type'] in ['ERC721', 'ERC1155']
]
print(f"\n๐ผ๏ธ NFT Approvals: {len(nft_approvals)}")
for nft in nft_approvals:
print(f" {nft['token']['name']} โ {nft['spender'].get('name', 'Unknown')}")
if nft.get('approvalType') == 'setApprovalForAll':
print(f" โ ๏ธ Full collection approved")
cURL Examplesโ
# Get all approvals
curl "https://api.web3identity.com/api/approvals/0xYourAddress?chain=ethereum"
# Include NFT approvals
curl "https://api.web3identity.com/api/approvals/0xYourAddress?chain=ethereum&includeNFTs=true"
# Get approvals on Polygon
curl "https://api.web3identity.com/api/approvals/0xYourAddress?chain=polygon"
# Get USDC allowances
curl "https://api.web3identity.com/api/allowances/0xYourAddress?chain=ethereum&token=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
# Check specific spender
curl "https://api.web3identity.com/api/allowances/0xYourAddress?chain=ethereum&spender=0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
Rate Limitsโ
| Tier | Rate Limit | Notes |
|---|---|---|
| Free | 100 requests/day | No payment required |
| Paid | Unlimited | $0.01-$0.02 per call via x402 |
Common Use Casesโ
Approval Security Auditโ
// Complete security audit of wallet approvals
async function auditApprovals(address, chains = ['ethereum', 'polygon', 'arbitrum']) {
const audits = await Promise.all(
chains.map(chain =>
client.getApprovals(address, { chain, includeNFTs: true })
)
);
const combined = {
totalApprovals: audits.reduce((sum, a) => sum + a.totalApprovals, 0),
highRisk: audits.flatMap(a =>
a.approvals.filter(ap => ap.risk.level === 'HIGH' || ap.risk.level === 'CRITICAL')
),
unlimited: audits.flatMap(a =>
a.approvals.filter(ap => ap.allowanceFormatted === 'unlimited')
),
nftApprovals: audits.flatMap(a =>
a.approvals.filter(ap => ap.token.type === 'ERC721' || ap.token.type === 'ERC1155')
)
};
return combined;
}
const audit = await auditApprovals('0xYourAddress');
console.log(`Total approvals across chains: ${audit.totalApprovals}`);
console.log(`High-risk approvals: ${audit.highRisk.length}`);
console.log(`Unlimited approvals: ${audit.unlimited.length}`);
console.log(`NFT approvals: ${audit.nftApprovals.length}`);
Auto-Revoke Stale Approvalsโ
// Identify stale approvals for revocation
async function findStaleApprovals(address, chain = 'ethereum', maxAgeDays = 180) {
const approvals = await client.getApprovals(address, { chain });
const now = Date.now();
const maxAgeMs = maxAgeDays * 24 * 60 * 60 * 1000;
const stale = approvals.approvals.filter(a => {
const approvedDate = new Date(a.approvedAt.timestamp).getTime();
const age = now - approvedDate;
const neverUsed = !a.lastUsed;
return age > maxAgeMs && neverUsed;
});
return stale.map(a => ({
token: a.token.symbol,
spender: a.spender.name || a.spender.address,
age: Math.floor((now - new Date(a.approvedAt.timestamp).getTime()) / (24 * 60 * 60 * 1000)),
risk: a.risk.level
}));
}
const stale = await findStaleApprovals('0xYourAddress', 'ethereum', 180);
console.log(`Stale approvals (180+ days, never used): ${stale.length}`);
Approval Monitoring Dashboardโ
// Real-time approval monitoring
async function monitorApprovals(address, chains) {
const results = [];
for (const chain of chains) {
const approvals = await client.getApprovals(address, { chain });
results.push({
chain,
totalApprovals: approvals.totalApprovals,
riskScore: approvals.riskScore,
criticalCount: approvals.summary.byRisk.CRITICAL || 0,
highCount: approvals.summary.byRisk.HIGH || 0,
revokeRecommended: approvals.summary.recommendations.revoke
});
}
return results;
}
const dashboard = await monitorApprovals('0xYourAddress', ['ethereum', 'polygon', 'arbitrum']);
console.table(dashboard);
Related Endpointsโ
- Wallet Balances โ Token balances
- Transaction History โ Wallet activity
- Token Security โ Token safety analysis
- NFT Holdings โ NFT portfolio