Skip to main content
GET
https://api-mainnet.onzks.com
/
v1
/
score
/
:identity
/
breakdown
Get Score Breakdown
curl --request GET \
  --url https://api-mainnet.onzks.com/v1/score/:identity/breakdown \
  --header 'Authorization: Bearer <token>'
{
  "success": true,
  "zksId": {},
  "address": "<string>",
  "breakdown": {
    "totalScore": 123,
    "categories": {
      "activity": {},
      "volume": {},
      "age": {},
      "diversity": {},
      "governance": {},
      "social": {},
      "risk": {},
      "loyalty": {}
    },
    "weights": {},
    "percentiles": {},
    "historicalComparison": {}
  }
}

Overview

Retrieve a detailed breakdown of a user’s ZKScore across all 8 scoring categories. This endpoint provides granular insights into how the total score is calculated, including individual category scores, weights, and historical comparisons.
The breakdown helps users understand which areas contribute most to their score and where they can improve.

Parameters

identity
string
required
ZKS ID (e.g., alice.zks) or wallet address (e.g., 0x742d35Cc...)
chainId
number
Specific chain ID to get breakdown for (optional, defaults to aggregated across all chains)
includeHistory
boolean
Include historical comparison data (default: false)

Response

success
boolean
Indicates if the request was successful
zksId
string | null
The ZKS ID (without .zks suffix), or null if not set
address
string
The primary wallet address
breakdown
object

Examples

curl https://api.onzks.com/v1/score/alice.zks/breakdown \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "success": true,
  "zksId": "alice",
  "address": "0x742d35cc6635c0532925a3b844d1ff4e1321",
  "breakdown": {
    "totalScore": 9847,
    "categories": {
      "activity": {
        "score": 1200,
        "max": 1500,
        "percentage": 80.0,
        "description": "Transaction frequency and consistency",
        "metrics": {
          "dailyTransactions": 15.3,
          "consistency": 0.92,
          "activeMonths": 18
        }
      },
      "volume": {
        "score": 1800,
        "max": 2000,
        "percentage": 90.0,
        "description": "Total transaction volume",
        "metrics": {
          "totalVolume": "2847392.50",
          "averageTransaction": "1847.25",
          "largestTransaction": "125000.00"
        }
      },
      "age": {
        "score": 950,
        "max": 1000,
        "percentage": 95.0,
        "description": "Wallet age and longevity",
        "metrics": {
          "ageInDays": 547,
          "firstTransaction": "2023-01-15T10:30:00Z",
          "maturityLevel": "veteran"
        }
      },
      "diversity": {
        "score": 1400,
        "max": 1500,
        "percentage": 93.3,
        "description": "Protocol and chain diversity",
        "metrics": {
          "uniqueProtocols": 28,
          "uniqueChains": 5,
          "categorySpread": 0.87
        }
      },
      "governance": {
        "score": 1100,
        "max": 1200,
        "percentage": 91.7,
        "description": "DAO participation and voting",
        "metrics": {
          "proposalsVoted": 47,
          "daosParticipated": 12,
          "votingPower": "125000"
        }
      },
      "social": {
        "score": 897,
        "max": 1000,
        "percentage": 89.7,
        "description": "Social reputation and connections",
        "metrics": {
          "attestationsReceived": 23,
          "trustedConnections": 156,
          "reputationScore": 4.8
        }
      },
      "risk": {
        "score": 750,
        "max": 800,
        "percentage": 93.8,
        "description": "Risk management and security",
        "metrics": {
          "securityScore": 0.95,
          "riskIncidents": 0,
          "safetyPractices": 8
        }
      },
      "loyalty": {
        "score": 1750,
        "max": 2000,
        "percentage": 87.5,
        "description": "Long-term protocol engagement",
        "metrics": {
          "longestStreak": 127,
          "averageHoldTime": 89,
          "returnRate": 0.92
        }
      }
    },
    "weights": {
      "activity": 0.15,
      "volume": 0.20,
      "age": 0.10,
      "diversity": 0.15,
      "governance": 0.12,
      "social": 0.10,
      "risk": 0.08,
      "loyalty": 0.20
    },
    "percentiles": {
      "activity": 92.5,
      "volume": 95.8,
      "age": 88.3,
      "diversity": 94.2,
      "governance": 91.7,
      "social": 87.9,
      "risk": 96.1,
      "loyalty": 93.4
    },
    "historicalComparison": {
      "period": "30d",
      "changes": {
        "activity": +50,
        "volume": +120,
        "age": +10,
        "diversity": +35,
        "governance": +80,
        "social": +15,
        "risk": +5,
        "loyalty": +95
      },
      "totalChange": +410,
      "percentChange": 4.3
    }
  },
  "lastUpdated": "2024-01-20T14:30:00Z"
}

Category Details

1. Activity Score (Max: 1500)

Measures transaction frequency and consistency:
  • Daily/weekly transaction patterns
  • Consistency over time
  • Active months/years
  • Transaction regularity

2. Volume Score (Max: 2000)

Measures total transaction volume:
  • Cumulative transaction value
  • Average transaction size
  • Largest transactions
  • Volume growth rate

3. Age Score (Max: 1000)

Measures wallet longevity:
  • Days since first transaction
  • Maturity level (new/intermediate/veteran)
  • Historical presence
  • Continuous activity

4. Diversity Score (Max: 1500)

Measures protocol and chain diversity:
  • Number of unique protocols used
  • Number of chains interacted with
  • Category spread (DeFi, NFT, Gaming, etc.)
  • Exploration behavior

5. Governance Score (Max: 1200)

Measures DAO participation:
  • Proposals voted on
  • DAOs participated in
  • Voting power held
  • Governance token holdings

6. Social Score (Max: 1000)

Measures social reputation:
  • Attestations received
  • Trusted connections
  • Community reputation
  • Social verifications

7. Risk Score (Max: 800)

Measures risk management:
  • Security practices
  • Risk incidents avoided
  • Safety measures implemented
  • Smart contract interactions

8. Loyalty Score (Max: 2000)

Measures long-term engagement:
  • Longest activity streak
  • Average hold time for assets
  • Return rate to protocols
  • Consistent participation

Use Cases

1. Score Visualization

Display breakdown in a dashboard:
async function displayScoreBreakdown(identity) {
  const { breakdown } = await getScoreBreakdown(identity);

  // Create chart data
  const chartData = Object.entries(breakdown.categories).map(([name, data]) => ({
    category: name,
    score: data.score,
    max: data.max,
    percentage: data.percentage
  }));

  // Render chart
  renderChart(chartData);

  // Show top categories
  const topCategories = chartData
    .sort((a, b) => b.percentage - a.percentage)
    .slice(0, 3);

  console.log('Your strongest areas:');
  topCategories.forEach(cat => {
    console.log(`  ${cat.category}: ${cat.percentage}%`);
  });
}

2. Improvement Recommendations

Suggest areas for improvement:
async function getImprovementSuggestions(identity) {
  const { breakdown } = await getScoreBreakdown(identity);

  const suggestions = [];

  Object.entries(breakdown.categories).forEach(([category, data]) => {
    if (data.percentage < 70) {
      suggestions.push({
        category,
        currentScore: data.score,
        maxScore: data.max,
        improvement: data.max - data.score,
        priority: 'high'
      });
    } else if (data.percentage < 85) {
      suggestions.push({
        category,
        currentScore: data.score,
        maxScore: data.max,
        improvement: data.max - data.score,
        priority: 'medium'
      });
    }
  });

  // Sort by potential improvement
  suggestions.sort((a, b) => b.improvement - a.improvement);

  return suggestions;
}

3. Progress Tracking

Track score changes over time:
async function trackProgress(identity) {
  const { breakdown } = await getScoreBreakdown(identity, true);

  if (breakdown.historicalComparison) {
    const { changes, percentChange } = breakdown.historicalComparison;

    console.log(`Overall change: ${percentChange > 0 ? '+' : ''}${percentChange}%`);
    console.log('\nCategory changes:');

    Object.entries(changes).forEach(([category, change]) => {
      const emoji = change > 0 ? '📈' : change < 0 ? '📉' : '➡️';
      console.log(`  ${emoji} ${category}: ${change > 0 ? '+' : ''}${change}`);
    });
  }
}

4. Comparative Analysis

Compare with network averages:
async function compareWithNetwork(identity) {
  const { breakdown } = await getScoreBreakdown(identity);

  console.log('Your percentile rankings:');
  Object.entries(breakdown.percentiles).forEach(([category, percentile]) => {
    const status = percentile >= 90 ? '🌟 Excellent' :
                   percentile >= 75 ? '✅ Above Average' :
                   percentile >= 50 ? '➡️ Average' :
                   '📊 Below Average';

    console.log(`  ${category}: ${percentile}% - ${status}`);
  });
}

Best Practices

1. Cache Breakdown Data

Breakdown data changes infrequently:
const breakdownCache = new Map();

async function getCachedBreakdown(identity) {
  const cacheKey = `breakdown:${identity}`;
  
  if (breakdownCache.has(cacheKey)) {
    const cached = breakdownCache.get(cacheKey);
    if (Date.now() - cached.timestamp < 15 * 60 * 1000) { // 15 minutes
      return cached.data;
    }
  }

  const data = await getScoreBreakdown(identity);
  breakdownCache.set(cacheKey, {
    data,
    timestamp: Date.now()
  });

  return data;
}

2. Visualize Category Performance

Use charts for better understanding:
function createRadarChart(breakdown) {
  const categories = Object.entries(breakdown.categories).map(([name, data]) => ({
    category: name,
    value: data.percentage
  }));

  // Render radar chart showing all 8 categories
  return {
    type: 'radar',
    data: categories,
    options: {
      scale: { min: 0, max: 100 }
    }
  };
}

3. Highlight Strengths and Weaknesses

function analyzeBreakdown(breakdown) {
  const categories = Object.entries(breakdown.categories);

  const strengths = categories
    .filter(([_, data]) => data.percentage >= 85)
    .map(([name, data]) => ({ name, percentage: data.percentage }));

  const weaknesses = categories
    .filter(([_, data]) => data.percentage < 70)
    .map(([name, data]) => ({ name, percentage: data.percentage }));

  return { strengths, weaknesses };
}
async function getHistoricalTrends(identity, periods = 6) {
  const trends = [];

  for (let i = 0; i < periods; i++) {
    const data = await getScoreBreakdown(identity, true);
    trends.push({
      date: new Date(),
      totalScore: data.breakdown.totalScore,
      categories: data.breakdown.categories
    });

    // Wait before next request
    await new Promise(resolve => setTimeout(resolve, 1000));
  }

  return trends;
}

Troubleshooting

”Identity not found”

Cause: The identity doesn’t exist or hasn’t been activated. Solution:
  • Verify the identity exists
  • Ensure the identity is activated
  • Check for typos in the ZKS ID

”Insufficient data”

Cause: Not enough transaction history to calculate breakdown. Solution:
  • User needs more on-chain activity
  • Some categories may show 0 if no relevant activity
  • Breakdown becomes more accurate over time

”Historical data unavailable”

Cause: Historical comparison data not yet available. Solution:
  • Historical data requires at least 30 days of activity
  • Try again after more time has passed
  • Use includeHistory=false if not needed

Performance Tips

  1. Cache Results: Breakdown data changes slowly, cache for 15+ minutes
  2. Request Only When Needed: Don’t fetch on every page load
  3. Use Pagination: For displaying multiple users, batch requests
  4. Optimize Rendering: Render charts efficiently with libraries like Chart.js

Rate Limits

Score breakdown requests are subject to rate limits:
  • Free tier: 30 requests per minute
  • Starter tier: 150 requests per minute
  • Professional tier: 600 requests per minute
  • Enterprise tier: Custom limits