Skip to main content

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 address
  • userIdentifier (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 succeeded
  • achievements: Array of user achievements
    • achievementType: Type of achievement (see Achievement Types below)
    • currentProgress: Current progress toward the achievement
    • isUnlocked: Whether the achievement has been unlocked
    • unlockedAt: Timestamp when achievement was unlocked (if unlocked)
    • rewardClaimed: Whether the reward has been claimed
    • rewardClaimedAt: 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 address
  • userIdentifier (required): User identifier
  • platform (required): Platform name
  • achievementType (required): Type of achievement (see Achievement Types below)
  • newValue (required): New progress value
  • increment (optional): If true, adds newValue to current progress. If false (default), sets progress to newValue (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 succeeded
  • unlocked: Array of newly unlocked achievements (empty if none)
    • achievementType: Type of achievement unlocked
    • threshold: Threshold that was reached
    • progress: Current progress value
  • currentProgress: Updated progress value
  • isUnlocked: 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 TypeDescriptionDefault Threshold
message_countTotal messages sent1000
voice_hoursTotal hours in voice channels10
streak_daysStreak length achieved7
events_claimedTotal events/claims50
gm_countGM/GN messages sent10
level_reachedUser level reached5
ltz_earnedTotal LTZ earned10000
customCustom achievement type100

Note: Thresholds are configurable per brand through the Partner Portal. Default thresholds are used if not configured.


How Achievements Work

  1. Progress Tracking: Call /achievements/update-progress when users perform relevant actions
  2. Automatic Unlock: When progress reaches the threshold, achievement is automatically unlocked
  3. Unlock Notification: The unlocked array in the response indicates newly unlocked achievements
  4. Reward Claiming: Users can claim rewards for unlocked achievements (handled by your application)
  5. 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

  1. Update Progress Regularly: Call /achievements/update-progress when relevant actions occur
  2. Use Increment for Counts: Use increment: true for counting achievements (messages, events)
  3. Use Set for Max Values: Use increment: false for achievements tracking maximums (streak, level)
  4. Notify on Unlock: Always notify users when achievements are unlocked
  5. Display Progress: Show users their progress toward achievements
  6. 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 parameters
  • 404 Not Found: Invalid endpoint or user not found
  • 500 Internal Server Error: Server error