> ## Documentation Index
> Fetch the complete documentation index at: https://core.anylayer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Get Score History

> Get historical ZKScore data over time

## Overview

Retrieve historical ZKScore data to track score changes over time. This endpoint provides time-series data showing how a user's score has evolved, enabling trend analysis and progress tracking.

<Tip>
  Use this endpoint to build score charts, track improvements, and analyze scoring trends.
</Tip>

## Parameters

<ParamField path="identity" type="string" required>
  ZKS ID (e.g., `alice.zks`) or wallet address (e.g., `0x742d35Cc...`)
</ParamField>

<ParamField query="timeframe" type="string">
  Time period to retrieve (default: `30d`)

  * `7d` - Last 7 days
  * `30d` - Last 30 days
  * `90d` - Last 90 days
  * `1y` - Last year
  * `all` - All available history
</ParamField>

<ParamField query="interval" type="string">
  Data point interval (default: `day`)

  * `hour` - Hourly data points
  * `day` - Daily data points
  * `week` - Weekly data points
  * `month` - Monthly data points
</ParamField>

<ParamField query="chainId" type="number">
  Specific chain ID to get history for (optional, defaults to aggregated)
</ParamField>

## Response

<ResponseField name="success" type="boolean">
  Indicates if the request was successful
</ResponseField>

<ResponseField name="zksId" type="string | null">
  The ZKS ID (without .zks suffix), or null if not set
</ResponseField>

<ResponseField name="address" type="string">
  The primary wallet address
</ResponseField>

<ResponseField name="history" type="array">
  Array of historical score data points

  <Expandable title="data point properties">
    <ResponseField name="timestamp" type="string">
      ISO 8601 timestamp
    </ResponseField>

    <ResponseField name="score" type="number">
      Total score at this point in time
    </ResponseField>

    <ResponseField name="rank" type="number">
      Global rank at this point in time
    </ResponseField>

    <ResponseField name="change" type="number">
      Change from previous data point
    </ResponseField>

    <ResponseField name="percentChange" type="number">
      Percentage change from previous point
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="summary" type="object">
  Summary statistics for the period

  <Expandable title="properties">
    <ResponseField name="startScore" type="number">
      Score at start of period
    </ResponseField>

    <ResponseField name="endScore" type="number">
      Score at end of period
    </ResponseField>

    <ResponseField name="totalChange" type="number">
      Total change over period
    </ResponseField>

    <ResponseField name="percentChange" type="number">
      Percentage change over period
    </ResponseField>

    <ResponseField name="highestScore" type="number">
      Highest score in period
    </ResponseField>

    <ResponseField name="lowestScore" type="number">
      Lowest score in period
    </ResponseField>

    <ResponseField name="averageScore" type="number">
      Average score over period
    </ResponseField>
  </Expandable>
</ResponseField>

## Examples

<CodeGroup>
  ```bash cURL (Last 30 Days) theme={null}
  curl "https://api.onzks.com/v1/score/alice.zks/history?timeframe=30d&interval=day" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```bash cURL (Last Year, Weekly) theme={null}
  curl "https://api.onzks.com/v1/score/alice.zks/history?timeframe=1y&interval=week" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  async function getScoreHistory(identity, timeframe = '30d', interval = 'day') {
    const params = new URLSearchParams({
      timeframe,
      interval
    });

    const response = await fetch(
      `https://api.onzks.com/v1/score/${identity}/history?${params}`,
      {
        headers: {
          'Authorization': 'Bearer YOUR_API_KEY'
        }
      }
    );

    const data = await response.json();

    // Display summary
    console.log(`Score History for ${identity}`);
    console.log(`Period: ${timeframe}`);
    console.log(`Start: ${data.summary.startScore}`);
    console.log(`End: ${data.summary.endScore}`);
    console.log(`Change: ${data.summary.totalChange} (${data.summary.percentChange}%)`);

    return data;
  }

  // Usage
  await getScoreHistory('alice.zks', '30d', 'day');
  ```

  ```python Python theme={null}
  import requests
  from datetime import datetime

  def get_score_history(identity, timeframe='30d', interval='day'):
      params = {
          'timeframe': timeframe,
          'interval': interval
      }
      
      response = requests.get(
          f'https://api.onzks.com/v1/score/{identity}/history',
          headers={'Authorization': 'Bearer YOUR_API_KEY'},
          params=params
      )
      
      data = response.json()
      
      # Display summary
      print(f"Score History for {identity}")
      print(f"Period: {timeframe}")
      print(f"Start: {data['summary']['startScore']}")
      print(f"End: {data['summary']['endScore']}")
      print(f"Change: {data['summary']['totalChange']} ({data['summary']['percentChange']}%)")
      
      return data

  # Usage
  get_score_history('alice.zks', '30d', 'day')
  ```
</CodeGroup>

## Response Example

```json theme={null}
{
  "success": true,
  "zksId": "alice",
  "address": "0x742d35cc6635c0532925a3b844d1ff4e1321",
  "timeframe": "30d",
  "interval": "day",
  "history": [
    {
      "timestamp": "2024-01-01T00:00:00Z",
      "score": 9437,
      "rank": 1,
      "change": 0,
      "percentChange": 0
    },
    {
      "timestamp": "2024-01-02T00:00:00Z",
      "score": 9458,
      "rank": 1,
      "change": 21,
      "percentChange": 0.22
    },
    {
      "timestamp": "2024-01-03T00:00:00Z",
      "score": 9492,
      "rank": 1,
      "change": 34,
      "percentChange": 0.36
    },
    // ... more data points
    {
      "timestamp": "2024-01-30T00:00:00Z",
      "score": 9847,
      "rank": 1,
      "change": 42,
      "percentChange": 0.43
    }
  ],
  "summary": {
    "startScore": 9437,
    "endScore": 9847,
    "totalChange": 410,
    "percentChange": 4.34,
    "highestScore": 9850,
    "lowestScore": 9420,
    "averageScore": 9645
  },
  "dataPoints": 30
}
```

## Use Cases

### 1. Score Chart Visualization

Display score history in a line chart:

```javascript theme={null}
async function renderScoreChart(identity) {
  const { history } = await getScoreHistory(identity, '30d', 'day');

  const chartData = {
    labels: history.map(point => new Date(point.timestamp).toLocaleDateString()),
    datasets: [{
      label: 'ZKScore',
      data: history.map(point => point.score),
      borderColor: 'rgb(75, 192, 192)',
      tension: 0.1
    }]
  };

  // Render with Chart.js or similar
  renderChart(chartData);
}
```

### 2. Progress Tracking

Track user progress over time:

```javascript theme={null}
async function trackProgress(identity) {
  const { summary } = await getScoreHistory(identity, '30d');

  const progress = {
    improvement: summary.totalChange,
    percentImprovement: summary.percentChange,
    trend: summary.totalChange > 0 ? 'improving' : 
           summary.totalChange < 0 ? 'declining' : 'stable'
  };

  console.log(`Progress: ${progress.trend}`);
  console.log(`Improvement: ${progress.improvement} points (${progress.percentImprovement}%)`);

  return progress;
}
```

### 3. Trend Analysis

Analyze scoring trends:

```javascript theme={null}
async function analyzeTrends(identity) {
  const { history } = await getScoreHistory(identity, '90d', 'week');

  // Calculate moving average
  const movingAverage = [];
  const window = 4; // 4-week moving average

  for (let i = window - 1; i < history.length; i++) {
    const sum = history.slice(i - window + 1, i + 1)
      .reduce((acc, point) => acc + point.score, 0);
    movingAverage.push(sum / window);
  }

  // Identify trend
  const recentAvg = movingAverage.slice(-4).reduce((a, b) => a + b) / 4;
  const olderAvg = movingAverage.slice(0, 4).reduce((a, b) => a + b) / 4;
  const trend = recentAvg > olderAvg ? 'upward' : 'downward';

  return { movingAverage, trend };
}
```

### 4. Milestone Detection

Detect when user reaches milestones:

```javascript theme={null}
async function detectMilestones(identity) {
  const { history } = await getScoreHistory(identity, 'all');

  const milestones = [
    { score: 1000, name: 'Bronze Tier' },
    { score: 3000, name: 'Silver Tier' },
    { score: 5000, name: 'Gold Tier' },
    { score: 7000, name: 'Platinum Tier' },
    { score: 9000, name: 'Diamond Tier' }
  ];

  const achieved = [];

  milestones.forEach(milestone => {
    const point = history.find(p => p.score >= milestone.score);
    if (point) {
      achieved.push({
        ...milestone,
        achievedAt: point.timestamp,
        score: point.score
      });
    }
  });

  return achieved;
}
```

## Best Practices

### 1. Choose Appropriate Intervals

Match interval to timeframe:

```javascript theme={null}
function getOptimalInterval(timeframe) {
  switch (timeframe) {
    case '7d': return 'hour';
    case '30d': return 'day';
    case '90d': return 'day';
    case '1y': return 'week';
    case 'all': return 'month';
    default: return 'day';
  }
}

// Usage
const interval = getOptimalInterval('30d');
await getScoreHistory(identity, '30d', interval);
```

### 2. Cache Historical Data

History doesn't change frequently:

```javascript theme={null}
const historyCache = new Map();

async function getCachedHistory(identity, timeframe, interval) {
  const cacheKey = `history:${identity}:${timeframe}:${interval}`;
  
  if (historyCache.has(cacheKey)) {
    const cached = historyCache.get(cacheKey);
    // Cache for 1 hour
    if (Date.now() - cached.timestamp < 60 * 60 * 1000) {
      return cached.data;
    }
  }

  const data = await getScoreHistory(identity, timeframe, interval);
  historyCache.set(cacheKey, {
    data,
    timestamp: Date.now()
  });

  return data;
}
```

### 3. Handle Missing Data

Some periods may have no data:

```javascript theme={null}
function fillMissingDataPoints(history, interval) {
  const filled = [];
  let lastScore = history[0]?.score || 0;

  for (let i = 0; i < history.length - 1; i++) {
    filled.push(history[i]);

    const current = new Date(history[i].timestamp);
    const next = new Date(history[i + 1].timestamp);
    const gap = (next - current) / (1000 * 60 * 60 * 24); // days

    // Fill gaps larger than interval
    if (gap > 1) {
      for (let j = 1; j < gap; j++) {
        const interpolated = new Date(current);
        interpolated.setDate(interpolated.getDate() + j);
        
        filled.push({
          timestamp: interpolated.toISOString(),
          score: lastScore,
          rank: history[i].rank,
          change: 0,
          percentChange: 0,
          interpolated: true
        });
      }
    }

    lastScore = history[i].score;
  }

  filled.push(history[history.length - 1]);
  return filled;
}
```

### 4. Compare Multiple Users

Compare score histories:

```javascript theme={null}
async function compareUsers(identities) {
  const histories = await Promise.all(
    identities.map(id => getScoreHistory(id, '30d', 'day'))
  );

  const comparison = {
    users: identities,
    data: histories.map((h, i) => ({
      identity: identities[i],
      currentScore: h.summary.endScore,
      change: h.summary.totalChange,
      percentChange: h.summary.percentChange
    }))
  };

  // Sort by improvement
  comparison.data.sort((a, b) => b.change - a.change);

  return comparison;
}
```

## Visualization Examples

### Line Chart

```javascript theme={null}
function createLineChart(history) {
  return {
    type: 'line',
    data: {
      labels: history.map(p => new Date(p.timestamp).toLocaleDateString()),
      datasets: [{
        label: 'Score',
        data: history.map(p => p.score),
        borderColor: 'rgb(75, 192, 192)',
        fill: false
      }]
    },
    options: {
      responsive: true,
      scales: {
        y: {
          beginAtZero: false
        }
      }
    }
  };
}
```

### Area Chart with Trend

```javascript theme={null}
function createAreaChart(history) {
  return {
    type: 'line',
    data: {
      labels: history.map(p => new Date(p.timestamp).toLocaleDateString()),
      datasets: [{
        label: 'Score',
        data: history.map(p => p.score),
        borderColor: 'rgb(75, 192, 192)',
        backgroundColor: 'rgba(75, 192, 192, 0.2)',
        fill: true
      }]
    }
  };
}
```

## Related Endpoints

* [Get Score](/api-reference/scores/get-score) - Get current ZKScore
* [Get Score Breakdown](/api-reference/scores/get-breakdown) - Detailed breakdown
* [Get Leaderboard](/api-reference/scores/get-leaderboard) - Top scores

## Troubleshooting

### "Insufficient history"

**Cause**: User doesn't have enough historical data.

**Solution**:

* Historical data requires at least 7 days of activity
* Try a shorter timeframe
* Check back after more time has passed

### "Invalid timeframe"

**Cause**: Unsupported timeframe value.

**Solution**:

* Use supported values: `7d`, `30d`, `90d`, `1y`, `all`
* Check for typos

### "Too many data points"

**Cause**: Requested interval too granular for timeframe.

**Solution**:

* Use larger intervals for longer timeframes
* `hour` for 7d max
* `day` for 90d max
* `week` for 1y max

## Performance Tips

1. **Use Appropriate Intervals**: Don't request hourly data for a year
2. **Cache Results**: History doesn't change frequently
3. **Limit Data Points**: Request only what you need to display
4. **Batch Requests**: When comparing multiple users, use Promise.all()

## Rate Limits

Score history 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
