Achievement Service API Reference
The Achievement Service manages an internal achievement system for gamification across all platform integrations. It tracks user progress toward achievements and unlocks rewards when thresholds are reached.
Base URL
https://services.loyalteez.app
Endpoints
Get User Achievements
Retrieves all achievements for a user, including progress and unlock status.
Endpoint: GET /achievements/:brandId/:userIdentifier
URL Parameters:
brandId(path, required): The brand's wallet addressuserIdentifier(path, required): User identifier (URL-encoded)
Response:
{
"success": true,
"achievements": [
{
"achievementType": "streak_days",
"currentProgress": 7,
"isUnlocked": true,
"unlockedAt": "2024-01-15T10:30:00.000Z",
"rewardClaimed": false,
"rewardClaimedAt": null
},
{
"achievementType": "message_count",
"currentProgress": 500,
"isUnlocked": false,
"unlockedAt": null,
"rewardClaimed": false,
"rewardClaimedAt": null
}
]
}
Response Fields:
success: Whether the operation succeededachievements: Array of user achievementsachievementType: Type of achievement (see Achievement Types below)currentProgress: Current progress toward the achievementisUnlocked: Whether the achievement has been unlockedunlockedAt: Timestamp when achievement was unlocked (if unlocked)rewardClaimed: Whether the reward has been claimedrewardClaimedAt: Timestamp when reward was claimed (if claimed)
Example:
const brandId = encodeURIComponent('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
const userIdentifier = encodeURIComponent('[email protected]');
const response = await fetch(
`https://services.loyalteez.app/achievements/${brandId}/${userIdentifier}`
);
const result = await response.json();
if (result.success) {
const unlocked = result.achievements.filter(a => a.isUnlocked);
const locked = result.achievements.filter(a => !a.isUnlocked);
console.log(`Unlocked: ${unlocked.length}`);
console.log(`In Progress: ${locked.length}`);
}
Update Progress
Updates user progress for a specific achievement type. When progress reaches the threshold, the achievement is automatically unlocked.
Endpoint: POST /achievements/update-progress
Request Body:
{
"brandId": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"userIdentifier": "[email protected]",
"platform": "discord",
"achievementType": "streak_days",
"newValue": 7,
"increment": false
}
Parameters:
brandId(required): The brand's wallet addressuserIdentifier(required): User identifierplatform(required): Platform nameachievementType(required): Type of achievement (see Achievement Types below)newValue(required): New progress valueincrement(optional): Iftrue, addsnewValueto current progress. Iffalse(default), sets progress tonewValue(or max of current and newValue)
Response:
{
"success": true,
"unlocked": [
{
"achievementType": "streak_days",
"threshold": 7,
"progress": 7
}
],
"currentProgress": 7,
"isUnlocked": true
}
Response Fields:
success: Whether the operation succeededunlocked: Array of newly unlocked achievements (empty if none)achievementType: Type of achievement unlockedthreshold: Threshold that was reachedprogress: Current progress value
currentProgress: Updated progress valueisUnlocked: Whether the achievement is now unlocked
Example:
async function updateAchievementProgress(userIdentifier, platform, brandId, achievementType, progress) {
const response = await fetch('https://services.loyalteez.app/achievements/update-progress', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
brandId,
userIdentifier,
platform,
achievementType,
newValue: progress,
increment: true
})
});
const result = await response.json();
if (result.success && result.unlocked.length > 0) {
result.unlocked.forEach(achievement => {
console.log(`🎉 Achievement unlocked: ${achievement.achievementType}!`);
// Notify user, award bonus, etc.
});
}
}
Achievement Types
The service supports the following achievement types:
| Achievement Type | Description | Default Threshold |
|---|---|---|
message_count | Total messages sent | 1000 |
voice_hours | Total hours in voice channels | 10 |
streak_days | Streak length achieved | 7 |
events_claimed | Total events/claims | 50 |
gm_count | GM/GN messages sent | 10 |
level_reached | User level reached | 5 |
ltz_earned | Total LTZ earned | 10000 |
custom | Custom achievement type | 100 |
Note: Thresholds are configurable per brand through the Partner Portal. Default thresholds are used if not configured.
How Achievements Work
- Progress Tracking: Call
/achievements/update-progresswhen users perform relevant actions - Automatic Unlock: When progress reaches the threshold, achievement is automatically unlocked
- Unlock Notification: The
unlockedarray in the response indicates newly unlocked achievements - Reward Claiming: Users can claim rewards for unlocked achievements (handled by your application)
- Progress Reset: Progress does not reset after unlocking (users can track their progress beyond thresholds)
Integration Examples
Discord Bot - Track Message Count
async function trackMessage(userId, brandId) {
const userIdentifier = `discord_${userId}@loyalteez.app`;
// Update message count achievement
const response = await fetch('https://services.loyalteez.app/achievements/update-progress', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
brandId,
userIdentifier,
platform: 'discord',
achievementType: 'message_count',
newValue: 1,
increment: true
})
});
const result = await response.json();
if (result.success && result.unlocked.length > 0) {
// Achievement unlocked!
result.unlocked.forEach(achievement => {
sendAchievementNotification(userId, achievement);
});
}
}
Update Streak Achievement
async function updateStreakAchievement(userIdentifier, platform, brandId, streakDays) {
const response = await fetch('https://services.loyalteez.app/achievements/update-progress', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
brandId,
userIdentifier,
platform,
achievementType: 'streak_days',
newValue: streakDays,
increment: false // Set to current streak (not increment)
})
});
const result = await response.json();
return result;
}
Get User Achievements Display
async function getUserAchievements(userIdentifier, brandId) {
const encodedBrandId = encodeURIComponent(brandId);
const encodedUser = encodeURIComponent(userIdentifier);
const response = await fetch(
`https://services.loyalteez.app/achievements/${encodedBrandId}/${encodedUser}`
);
const result = await response.json();
if (result.success) {
let message = '🏆 Your Achievements:\n\n';
result.achievements.forEach(achievement => {
const status = achievement.isUnlocked ? '✅' : '⏳';
const progress = achievement.currentProgress;
message += `${status} ${achievement.achievementType}: ${progress}\n`;
});
return message;
}
}
Web Application - Achievement Progress Bar
async function getAchievementProgress(userIdentifier, brandId, achievementType) {
const encodedBrandId = encodeURIComponent(brandId);
const encodedUser = encodeURIComponent(userIdentifier);
const response = await fetch(
`https://services.loyalteez.app/achievements/${encodedBrandId}/${encodedUser}`
);
const result = await response.json();
if (result.success) {
const achievement = result.achievements.find(a => a.achievementType === achievementType);
if (achievement) {
const threshold = getThreshold(achievementType); // Get from config
const percentage = Math.min((achievement.currentProgress / threshold) * 100, 100);
return {
progress: achievement.currentProgress,
threshold: threshold,
percentage: percentage,
isUnlocked: achievement.isUnlocked
};
}
}
}
Best Practices
- Update Progress Regularly: Call
/achievements/update-progresswhen relevant actions occur - Use Increment for Counts: Use
increment: truefor counting achievements (messages, events) - Use Set for Max Values: Use
increment: falsefor achievements tracking maximums (streak, level) - Notify on Unlock: Always notify users when achievements are unlocked
- Display Progress: Show users their progress toward achievements
- Handle Errors: Always handle errors gracefully
Error Handling
All endpoints return standard error responses:
{
"success": false,
"error": "Error message"
}
Common Errors:
400 Bad Request: Missing required fields or invalid parameters404 Not Found: Invalid endpoint or user not found500 Internal Server Error: Server error