Get Score History
curl --request GET \
--url https://api-mainnet.onzks.com/v1/score/:identity/history \
--header 'Authorization: Bearer <token>'import requests
url = "https://api-mainnet.onzks.com/v1/score/:identity/history"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api-mainnet.onzks.com/v1/score/:identity/history', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-mainnet.onzks.com/v1/score/:identity/history",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-mainnet.onzks.com/v1/score/:identity/history"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-mainnet.onzks.com/v1/score/:identity/history")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-mainnet.onzks.com/v1/score/:identity/history")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"success": true,
"zksId": {},
"address": "<string>",
"history": [
{
"timestamp": "<string>",
"score": 123,
"rank": 123,
"change": 123,
"percentChange": 123
}
],
"summary": {
"startScore": 123,
"endScore": 123,
"totalChange": 123,
"percentChange": 123,
"highestScore": 123,
"lowestScore": 123,
"averageScore": 123
}
}Scores
Get Score History
Get historical ZKScore data over time
GET
/
v1
/
score
/
:identity
/
history
Get Score History
curl --request GET \
--url https://api-mainnet.onzks.com/v1/score/:identity/history \
--header 'Authorization: Bearer <token>'import requests
url = "https://api-mainnet.onzks.com/v1/score/:identity/history"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api-mainnet.onzks.com/v1/score/:identity/history', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-mainnet.onzks.com/v1/score/:identity/history",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-mainnet.onzks.com/v1/score/:identity/history"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-mainnet.onzks.com/v1/score/:identity/history")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-mainnet.onzks.com/v1/score/:identity/history")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"success": true,
"zksId": {},
"address": "<string>",
"history": [
{
"timestamp": "<string>",
"score": 123,
"rank": 123,
"change": 123,
"percentChange": 123
}
],
"summary": {
"startScore": 123,
"endScore": 123,
"totalChange": 123,
"percentChange": 123,
"highestScore": 123,
"lowestScore": 123,
"averageScore": 123
}
}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.Use this endpoint to build score charts, track improvements, and analyze scoring trends.
Parameters
string
required
ZKS ID (e.g.,
alice.zks) or wallet address (e.g., 0x742d35Cc...)string
Time period to retrieve (default:
30d)7d- Last 7 days30d- Last 30 days90d- Last 90 days1y- Last yearall- All available history
string
Data point interval (default:
day)hour- Hourly data pointsday- Daily data pointsweek- Weekly data pointsmonth- Monthly data points
number
Specific chain ID to get history for (optional, defaults to aggregated)
Response
boolean
Indicates if the request was successful
string | null
The ZKS ID (without .zks suffix), or null if not set
string
The primary wallet address
array
object
Examples
curl "https://api.onzks.com/v1/score/alice.zks/history?timeframe=30d&interval=day" \
-H "Authorization: Bearer YOUR_API_KEY"
curl "https://api.onzks.com/v1/score/alice.zks/history?timeframe=1y&interval=week" \
-H "Authorization: Bearer YOUR_API_KEY"
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');
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')
Response Example
{
"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: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: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: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: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: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: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: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: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
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
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 - Get current ZKScore
- Get Score Breakdown - Detailed breakdown
- 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
hourfor 7d maxdayfor 90d maxweekfor 1y max
Performance Tips
- Use Appropriate Intervals: Don’t request hourly data for a year
- Cache Results: History doesn’t change frequently
- Limit Data Points: Request only what you need to display
- 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