Retrieve information about claimable airdrops for a Solana address, including token details, unlock dates, and claim links.
Solana Only - This endpoint currently supports Solana (SOL) addresses only
Endpoint
GET https://api.octav.fi/v1/airdrop
Parameters
Solana wallet address to check for airdrops addresses=J8fo6fHGTD4egvuFE4RRQaBipfcHy5F5YVCcZmmZG6gR
Example
cURL
JavaScript
Python
TypeScript
curl "https://api.octav.fi/v1/airdrop?addresses=J8fo6fHGTD4egvuFE4RRQaBipfcHy5F5YVCcZmmZG6gR" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
Returns an array of portfolio objects containing airdrop data. The structure follows the same format as the Portfolio endpoint , but filtered to show only airdrop positions.
Top-Level Fields
The Solana wallet address
Total value of claimable airdrops in USD
Current price conversion rates for major tokens (SOL, ETH, BTC)
Timestamp of last data update (milliseconds since epoch)
Airdrop positions organized by protocol
Each protocol contains an AIRDROP key with:
protocolPositions[]: Array of airdrop positions
totalValue: Total USD value of airdrops from this protocol
unlockAt: Unix timestamp when tokens unlock
Chain-level summary (currently Solana only)
Airdrop Asset Fields
Each airdrop asset includes:
Amount of tokens claimable
Token symbol (e.g., “sns”)
Current token price in USD
Whether the airdrop is currently claimable
Unix timestamp when tokens become available
Link to view token on blockchain explorer
Example Response
[
{
"address" : "J8fo6fHGTD4egvuFE4RRQaBipfcHy5F5YVCcZmmZG6gR" ,
"networth" : "29.9896511359350402985808" ,
"conversionRates" : {
"SOL" : "169.19" ,
"cbBTC" : "115164" ,
"ETH" : "3654.21"
},
"lastUpdated" : "1754497718973" ,
"assetByProtocols" : {
"sns" : {
"name" : "SNS" ,
"key" : "sns" ,
"value" : "29.9896511359350402985808" ,
"chains" : {
"solana" : {
"protocolPositions" : {
"AIRDROP" : {
"name" : "Airdrop" ,
"totalValue" : "29.9896511359350402985808" ,
"unlockAt" : "1747137600" ,
"protocolPositions" : [
{
"name" : "Airdrop" ,
"value" : "29.9896511359350402985808" ,
"unlockAt" : "1747137600" ,
"assets" : [
{
"balance" : "14671.9255" ,
"symbol" : "sns" ,
"name" : "solana name service" ,
"value" : "29.9896511359350402985808" ,
"price" : "0.0020440160451970016" ,
"contract" : "SNS8DJbHc34nKySHVhLGMUUE72ho6igvJaxtq9T3cX3" ,
"chainKey" : "solana" ,
"isClaimable" : true ,
"link" : "https://airdrop.sns.id/" ,
"unlockAt" : "1747137600" ,
"explorerUrl" : "https://solscan.io/token/SNS8DJbHc34nKySHVhLGMUUE72ho6igvJaxtq9T3cX3" ,
"imgSmall" : "https://images.octav.fi/tokens/small/SNS8DJbHc34nKySHVhLGMUUE72ho6igvJaxtq9T3cX3_logo.png" ,
"imgLarge" : "https://images.octav.fi/tokens/small/SNS8DJbHc34nKySHVhLGMUUE72ho6igvJaxtq9T3cX3_logo.png"
}
]
}
]
}
}
}
}
}
},
"chains" : {
"solana" : {
"name" : "Solana" ,
"key" : "solana" ,
"value" : "29.9896511359350402985808"
}
}
}
]
Use Cases
Check All Airdrops
Filter Claimable
Track Value
Upcoming Unlocks
Get all claimable airdrops for an address: async function checkAirdrops ( address ) {
const response = await fetch (
`https://api.octav.fi/v1/airdrop?addresses= ${ address } ` ,
{
headers: { 'Authorization' : `Bearer ${ apiKey } ` }
}
);
const [ data ] = await response . json ();
console . log ( `Total airdrop value: $ ${ parseFloat ( data . networth ). toFixed ( 2 ) } ` );
// Iterate through all protocols
Object . values ( data . assetByProtocols ). forEach ( protocol => {
Object . values ( protocol . chains ). forEach ( chain => {
const airdropData = chain . protocolPositions . AIRDROP ;
if ( airdropData ) {
airdropData . protocolPositions . forEach ( position => {
position . assets . forEach ( asset => {
const unlockDate = new Date ( parseInt ( asset . unlockAt ) * 1000 );
console . log ( `
Token: ${ asset . name } ( ${ asset . symbol } )
Amount: ${ parseFloat ( asset . balance ). toFixed ( 4 ) }
Value: $ ${ parseFloat ( asset . value ). toFixed ( 2 ) }
Claimable: ${ asset . isClaimable ? 'Yes' : 'No' }
Unlock Date: ${ unlockDate . toLocaleDateString () }
Claim Link: ${ asset . link }
` );
});
});
}
});
});
}
Show only currently claimable airdrops: async function getClaimableAirdrops ( address ) {
const response = await fetch (
`https://api.octav.fi/v1/airdrop?addresses= ${ address } ` ,
{
headers: { 'Authorization' : `Bearer ${ apiKey } ` }
}
);
const [ data ] = await response . json ();
const claimable = [];
Object . values ( data . assetByProtocols ). forEach ( protocol => {
Object . values ( protocol . chains ). forEach ( chain => {
const airdropData = chain . protocolPositions . AIRDROP ;
if ( airdropData ) {
airdropData . protocolPositions . forEach ( position => {
position . assets . forEach ( asset => {
if ( asset . isClaimable ) {
claimable . push ({
name: asset . name ,
symbol: asset . symbol ,
amount: asset . balance ,
value: asset . value ,
claimLink: asset . link
});
}
});
});
}
});
});
return claimable ;
}
const claimable = await getClaimableAirdrops ( address );
console . log ( ` ${ claimable . length } airdrops ready to claim` );
Monitor total airdrop value over time: async function trackAirdropValue ( address ) {
const response = await fetch (
`https://api.octav.fi/v1/airdrop?addresses= ${ address } ` ,
{
headers: { 'Authorization' : `Bearer ${ apiKey } ` }
}
);
const [ data ] = await response . json ();
const totalValue = parseFloat ( data . networth );
// Calculate value by protocol
const valueByProtocol = {};
Object . entries ( data . assetByProtocols ). forEach (([ key , protocol ]) => {
valueByProtocol [ protocol . name ] = parseFloat ( protocol . value );
});
return {
totalValue ,
valueByProtocol ,
timestamp: new Date ( parseInt ( data . lastUpdated ))
};
}
const snapshot = await trackAirdropValue ( address );
console . log ( `Total: $ ${ snapshot . totalValue . toFixed ( 2 ) } ` );
console . log ( 'By Protocol:' , snapshot . valueByProtocol );
Find airdrops with upcoming unlock dates: async function getUpcomingUnlocks ( address , daysAhead = 30 ) {
const response = await fetch (
`https://api.octav.fi/v1/airdrop?addresses= ${ address } ` ,
{
headers: { 'Authorization' : `Bearer ${ apiKey } ` }
}
);
const [ data ] = await response . json ();
const now = Date . now () / 1000 ;
const futureDate = now + ( daysAhead * 24 * 60 * 60 );
const upcoming = [];
Object . values ( data . assetByProtocols ). forEach ( protocol => {
Object . values ( protocol . chains ). forEach ( chain => {
const airdropData = chain . protocolPositions . AIRDROP ;
if ( airdropData ) {
airdropData . protocolPositions . forEach ( position => {
position . assets . forEach ( asset => {
const unlockTime = parseInt ( asset . unlockAt );
if ( unlockTime > now && unlockTime <= futureDate ) {
upcoming . push ({
name: asset . name ,
symbol: asset . symbol ,
value: asset . value ,
unlockDate: new Date ( unlockTime * 1000 ),
daysUntilUnlock: Math . ceil (( unlockTime - now ) / ( 24 * 60 * 60 ))
});
}
});
});
}
});
});
return upcoming . sort (( a , b ) => a . unlockDate - b . unlockDate );
}
const upcoming = await getUpcomingUnlocks ( address , 30 );
upcoming . forEach ( airdrop => {
console . log ( ` ${ airdrop . symbol } unlocks in ${ airdrop . daysUntilUnlock } days` );
});
Best Practices
Airdrop eligibility can change frequently:
Check daily for active addresses
Set up alerts for new airdrops
Monitor unlock dates for upcoming claims
Not all addresses will have airdrops: const [ data ] = await response . json ();
if ( ! data . assetByProtocols || Object . keys ( data . assetByProtocols ). length === 0 ) {
console . log ( 'No airdrops found for this address' );
return ;
}
Always verify claim URLs before using:
Check that domains match official project sites
Verify on project’s official social media
Be cautious of phishing attempts
Monitor unlock timestamps: const unlockDate = new Date ( parseInt ( asset . unlockAt ) * 1000 );
const isUnlocked = unlockDate <= new Date ();
Set reminders for upcoming unlocks to claim promptly
Response Structure Notes
Airdrop positions are identified by the AIRDROP key: const airdropPositions = chain . protocolPositions . AIRDROP ;
This key exists within the protocol’s chain data
All time fields use Unix timestamps (seconds since epoch):
unlockAt: When tokens become available
lastUpdated: When data was last synced (milliseconds)
Convert to JavaScript Date:
const date = new Date ( parseInt ( unlockAt ) * 1000 );