Phoenix Gamification
Wallets

Querying Wallets

This guide explains how users can check their wallet balances, view transaction history, and see their loyalty tier status.

This guide explains how users can check their wallet balances, view transaction history, and see their loyalty tier status.

Overview

The Query API provides endpoints for:

  • Getting all currency balances for a user
  • Getting a specific currency balance
  • Viewing transaction history
  • Checking loyalty tier status

All endpoints require authentication. See Getting Started for authentication setup.

Get User Balances

Get all currency balances for a user.

Endpoint:

GET /v1/wallet/balances?user_id={user_id}

Example Request:

GET /v1/wallet/balances?user_id=user_123

Response:

{
  "tenant_id": "your_tenant",
  "user_id": "user_123",
  "balances": [
    {
      "currency_id": "gold_coins",
      "currency_name": "Gold Coins",
      "currency_symbol": "🪙",
      "available": 1500,
      "lifetime_earned": 5000
    },
    {
      "currency_id": "gems",
      "currency_name": "Premium Gems",
      "currency_symbol": "💎",
      "available": 25,
      "lifetime_earned": 100
    },
    {
      "currency_id": "xp",
      "currency_name": "Experience Points",
      "currency_symbol": "✨",
      "available": 12500,
      "lifetime_earned": 12500
    }
  ]
}

Get Single Currency Balance

Get balance for a specific currency.

Endpoint:

GET /v1/wallet/balances/{currency_id}?user_id={user_id}

Example Request:

GET /v1/wallet/balances/gold_coins?user_id=user_123

Response:

{
  "currency_id": "gold_coins",
  "currency_name": "Gold Coins",
  "currency_symbol": "🪙",
  "available": 1500,
  "lifetime_earned": 5000
}

Get Transaction History

Get transaction history for a user.

Endpoint:

GET /v1/wallet/transactions?user_id={user_id}

Query Parameters:

ParameterTypeDescription
user_idstringRequired. User ID
currency_idstringFilter by currency (optional)
limitintegerPage size (default: 50, max: 100)
offsetintegerPage offset (default: 0)

Example Request:

GET /v1/wallet/transactions?user_id=user_123&currency_id=gold_coins&limit=20&offset=0

Response:

{
  "transactions": [
    {
      "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
      "currency_id": "gold_coins",
      "amount": 100,
      "balance_after": 1500,
      "source_type": "streak_milestone",
      "source_ref": "streak_abc",
      "description": "7-day login streak milestone",
      "created_at": "2026-01-26T10:30:00Z"
    },
    {
      "id": "b2c3d4e5-6789-01ab-cdef-2345678901bc",
      "currency_id": "gold_coins",
      "amount": -50,
      "balance_after": 1400,
      "source_type": "wheel_spin",
      "source_ref": "wheel_xyz",
      "description": "Spin cost for Daily Wheel",
      "created_at": "2026-01-25T15:45:00Z"
    },
    {
      "id": "c3d4e5f6-7890-12ab-cdef-3456789012cd",
      "currency_id": "gold_coins",
      "amount": 200,
      "balance_after": 1450,
      "source_type": "earning_rule",
      "source_ref": "daily_login_bonus",
      "description": "Daily login bonus",
      "created_at": "2026-01-25T08:00:00Z"
    }
  ],
  "total": 3
}

Transaction Amounts:

  • Positive amounts = currency earned
  • Negative amounts = currency spent

Get User Tier

Get the user's current loyalty tier and progress to the next tier.

Endpoint:

GET /v1/wallet/tier?user_id={user_id}

Example Request:

GET /v1/wallet/tier?user_id=user_123

Response:

{
  "tier_id": "tier-gold",
  "tier_name": "Gold",
  "tier_level": 3,
  "lifetime_points": 5000,
  "next_tier_name": "Platinum",
  "next_tier_points": 10000,
  "points_to_next": 5000
}

Note: Returns null if no tier system is configured or the user hasn't earned any points yet.

JavaScript Example

class WalletClient {
  constructor(apiUrl, jwt) {
    this.apiUrl = apiUrl;
    this.jwt = jwt;
  }

  async getBalances(userId) {
    const response = await fetch(
      `${this.apiUrl}/v1/wallet/balances?user_id=${userId}`,
      {
        headers: {
          'Authorization': `Bearer ${this.jwt}`,
          'Content-Type': 'application/json'
        }
      }
    );
    
    if (!response.ok) {
      throw new Error('Failed to fetch balances');
    }
    
    return response.json();
  }

  async getBalance( userId, currencyId) {
    const response = await fetch(
      `${this.apiUrl}/v1/wallet/balances/${currencyId}?user_id=${userId}`,
      {
        headers: {
          'Authorization': `Bearer ${this.jwt}`,
          'Content-Type': 'application/json'
        }
      }
    );
    
    return response.json();
  }

  async getTransactions( userId, options = {}) {
    const params = new URLSearchParams({
      user_id: userId,
      ...options
    });
    
    const response = await fetch(
      `${this.apiUrl}/v1/wallet/transactions?${params}`,
      {
        headers: {
          'Authorization': `Bearer ${this.jwt}`,
          'Content-Type': 'application/json'
        }
      }
    );
    
    return response.json();
  }

  async getTier( userId) {
    const response = await fetch(
      `${this.apiUrl}/v1/wallet/tier?user_id=${userId}`,
      {
        headers: {
          'Authorization': `Bearer ${this.jwt}`,
          'Content-Type': 'application/json'
        }
      }
    );
    
    return response.json();
  }
}

// Example usage
const wallet = new WalletClient('https://query.phoenix.example.com', userJwt);

// Get user's balances
const { balances } = await wallet.getBalances( 'user_123');
console.log(`Gold Coins: ${balances.find(b => b.currency_id === 'gold_coins')?.available || 0}`);

// Get specific currency balance
const coinsBalance = await wallet.getBalance( 'user_123', 'gold_coins');
console.log(`Available: ${coinsBalance.available}, Lifetime: ${coinsBalance.lifetime_earned}`);

// Get transaction history
const { transactions } = await wallet.getTransactions( 'user_123', {
  currency_id: 'gold_coins',
  limit: 20
});
transactions.forEach(t => {
  const sign = t.amount > 0 ? '+' : '';
  console.log(`${sign}${t.amount} ${t.currency_id}: ${t.description}`);
});

// Get tier info
const tier = await wallet.getTier( 'user_123');
if (tier) {
  console.log(`Current tier: ${tier.tier_name} (${tier.points_to_next} points to ${tier.next_tier_name})`);
} else {
  console.log('No tier system configured');
}

Source Types

Transactions include a source_type field indicating where the currency came from or went to:

Earning Sources:

  • earning_rule - Automatic earning rule
  • streak_milestone - Streak milestone reward
  • leaderboard_reward - Leaderboard window completion
  • achievement_completed - Achievement completion
  • wheel_spin - Spin wheel prize
  • reward_purchase - Reward catalog purchase (if reward grants currency)
  • manual_grant - Admin manual grant
  • promotion - Promotional grant

Spending Sources:

  • wheel_spin - Spin wheel cost
  • reward_purchase - Reward catalog purchase
  • manual_deduct - Admin manual deduction

Best Practices

  1. Cache Balances: Cache balance data to reduce API calls
  2. Show Lifetime Stats: Display lifetime earned to show user progress
  3. Transaction Pagination: Use limit/offset for large transaction lists
  4. Filter by Currency: Use currency_id filter when showing specific currency history
  5. Tier Progress: Display tier progress to encourage engagement
  6. Real-time Updates: Poll balances after transactions for immediate feedback

Next Steps

On this page