useLoyalty
Widget

API Reference

Widget methods, events, and internal APIs

This reference documents all widget methods and the underlying API endpoints used by the widget.

Widget Methods

UseLoyaltyWidget.init(config)

Initialize the widget with configuration.

UseLoyaltyWidget.init({
  publicKey: string;
  externalId: string;
  timestamp: number;
  signature: string;
  apiUrl?: string;
  theme?: WidgetTheme;
  language?: WidgetLanguage;
  member?: MemberData;
  onReady?: () => void;
  onError?: (error: Error) => void;
  onWelcomeBonus?: (points: number) => void;
}): void

UseLoyaltyWidget.open()

Open the widget drawer programmatically. Works with both floating and custom display modes.

// Open on button click
document.querySelector('#rewards-btn').addEventListener('click', () => {
  UseLoyaltyWidget.open();
});

// React example
<button onClick={() => window.UseLoyaltyWidget.open()}>
  View Rewards
</button>

UseLoyaltyWidget.close()

Close the widget drawer programmatically.

UseLoyaltyWidget.close();

UseLoyaltyWidget.toggle()

Toggle the widget drawer open/closed.

// Toggle button
document.querySelector('#toggle-btn').addEventListener('click', () => {
  UseLoyaltyWidget.toggle();
});

UseLoyaltyWidget.destroy()

Remove the widget from the page and clean up resources.

UseLoyaltyWidget.destroy();

// React cleanup example
useEffect(() => {
  return () => {
    window.UseLoyaltyWidget?.destroy();
  };
}, []);

Widget API Endpoints

The widget communicates with these API endpoints internally.

Initialize Widget

POST /api/widget/init

Authenticates the member and returns initial widget state.

Request:

{
  "origin": "https://your-site.com"
}

Headers:

X-Widget-Auth: base64({"publicKey", "externalId", "timestamp", "signature", "member"})

Response:

{
  "project": {
    "name": "My Store",
    "widgetSettings": { ... }
  },
  "member": {
    "id": "mem_123",
    "externalId": "user_456",
    "name": "John Doe",
    "email": "john@example.com",
    "points": 1500,
    "totalPointsEarned": 2500,
    "currentStreak": 5,
    "longestStreak": 12
  },
  "activeMultipliers": [
    {
      "name": "Double Points Week",
      "multiplier": 2,
      "endsAt": "2024-01-28T00:00:00Z"
    }
  ],
  "welcomeBonus": 100
}

Get Profile

GET /api/widget/profile

Returns member profile data.

Response:

{
  "id": "mem_123",
  "externalId": "user_456",
  "name": "John Doe",
  "email": "john@example.com",
  "avatarUrl": "https://...",
  "points": 1500,
  "totalPointsEarned": 2500,
  "currentStreak": 5,
  "longestStreak": 12,
  "lastCheckinAt": "2024-01-19T10:00:00Z",
  "memberSince": "2023-06-15T00:00:00Z"
}

Update Profile

PATCH /api/widget/profile

Update member profile information.

Request:

{
  "name": "John Smith",
  "avatarUrl": "https://new-avatar.com/img.jpg"
}

Get Rewards

GET /api/widget/rewards

List available rewards.

Response:

{
  "rewards": [
    {
      "id": "rwd_123",
      "name": "10% Discount",
      "description": "Get 10% off your next order",
      "imageUrl": "https://...",
      "pointsCost": 500,
      "type": "COUPON",
      "stockRemaining": 100,
      "userClaims": 0,
      "maxClaimsPerUser": 1,
      "minLevel": 2,
      "levelRequired": false,
      "canClaim": true,
      "affordableIn": 0
    }
  ]
}

Claim Reward

POST /api/widget/rewards

Redeem a reward with points.

Request:

{
  "rewardId": "rwd_123"
}

Response:

{
  "success": true,
  "claim": {
    "id": "clm_456",
    "reward": { ... },
    "pointsSpent": 500,
    "couponCode": "SAVE10-ABC123"
  },
  "member": {
    "points": 1000
  }
}

Get Badges

GET /api/widget/badges

Get earned and available badges.

Response:

{
  "earned": [
    {
      "id": "bdg_123",
      "name": "Early Adopter",
      "description": "Joined during beta",
      "imageUrl": "https://...",
      "rarity": "RARE",
      "awardedAt": "2024-01-01T00:00:00Z"
    }
  ],
  "available": [
    {
      "id": "bdg_456",
      "name": "Power User",
      "description": "Complete 50 quests",
      "imageUrl": "https://...",
      "rarity": "EPIC"
    }
  ]
}

Get Games

GET /api/widget/games

List available games.

Response:

{
  "games": [
    {
      "id": "game_spin",
      "name": "Spin the Wheel",
      "type": "SPIN_WHEEL",
      "pointsCost": 0,
      "maxPlaysPerUser": null,
      "dailyPlaysLimit": 1,
      "cooldownMinutes": 1440,
      "prizes": [
        { "name": "10 Points", "value": 10, "weight": 50 },
        { "name": "50 Points", "value": 50, "weight": 30 },
        { "name": "100 Points", "value": 100, "weight": 15 },
        { "name": "500 Points", "value": 500, "weight": 5 }
      ]
    },
    {
      "id": "game_checkin",
      "name": "Daily Check-in",
      "type": "DAILY_CHECKIN",
      "pointsCost": 0,
      "streakBonuses": [
        { "day": 7, "bonus": 50 },
        { "day": 30, "bonus": 200 }
      ]
    }
  ]
}

Play Game

POST /api/widget/games/:id/play

Play a game and get result.

Response:

{
  "success": true,
  "result": {
    "prize": {
      "name": "50 Points",
      "value": 50
    },
    "pointsAwarded": 100,
    "basePoints": 50,
    "multiplier": 2,
    "multiplierEventName": "Double Points Week"
  },
  "member": {
    "points": 1600
  }
}

Daily Check-in

GET /api/widget/games/:id/checkin

Get check-in status and streak info.

Response:

{
  "canCheckin": true,
  "currentStreak": 5,
  "longestStreak": 12,
  "lastCheckinAt": "2024-01-19T10:00:00Z",
  "todayReward": 10,
  "streakBonus": null,
  "nextStreakBonus": {
    "day": 7,
    "bonus": 50,
    "daysAway": 2
  }
}
POST /api/widget/games/:id/checkin

Perform daily check-in.

Response:

{
  "success": true,
  "pointsAwarded": 10,
  "streakBonus": 0,
  "newStreak": 6,
  "member": {
    "points": 1610,
    "currentStreak": 6
  }
}

Redeem Promo Code

POST /api/widget/promo-code

Redeem a promotional code.

Request:

{
  "code": "SUMMER2024"
}

Response:

{
  "success": true,
  "pointsAwarded": 100,
  "message": "Promo code redeemed successfully!"
}

Get Referral Data

GET /api/widget/referral

Get referral program data.

Response:

{
  "referralCode": "REF-A7X9K2",
  "shareLink": "https://yourapp.com/ref/REF-A7X9K2",
  "stats": {
    "totalReferrals": 15,
    "pendingReferrals": 3,
    "convertedReferrals": 12,
    "totalPointsEarned": 1200
  },
  "rewards": {
    "referrerReward": 100,
    "refereeReward": 50
  }
}

Generate Referral Code

POST /api/widget/referral/code

Generate or regenerate referral code.

Response:

{
  "referralCode": "REF-B8Y0L3",
  "shareLink": "https://yourapp.com/ref/REF-B8Y0L3"
}

Get Social Share Data

GET /api/widget/social-share

Get social sharing configuration.

Response:

{
  "platforms": ["twitter", "facebook", "linkedin", "whatsapp", "email"],
  "pointsPerShare": 10,
  "maxSharesPerDay": 5,
  "cooldownMinutes": 60,
  "todayShares": 2,
  "canShare": true
}

Track Social Share

POST /api/widget/social-share

Track a social share and award points.

Request:

{
  "platform": "twitter",
  "shareType": "referral"
}

Response:

{
  "success": true,
  "pointsAwarded": 20,
  "multiplier": 2,
  "cooldownEndsAt": "2024-01-20T11:00:00Z"
}

Error Responses

All endpoints return errors in this format:

{
  "error": "Error type",
  "message": "Human readable message"
}
StatusErrorDescription
400Bad RequestInvalid request data
401UnauthorizedInvalid or expired signature
403ForbiddenAction not allowed
404Not FoundResource doesn't exist
409ConflictAlready exists/claimed
429Too Many RequestsRate limited
500Server ErrorInternal error

Authentication Header

All widget requests include an authentication header:

X-Widget-Auth: base64({
  "publicKey": "pk_...",
  "externalId": "user_123",
  "timestamp": 1704067200000,
  "signature": "hmac_signature",
  "member": { ... }
})

The server validates:

  1. Signature matches HMAC-SHA256 of publicKey:externalId:timestamp
  2. Timestamp is within 5 minutes
  3. Public key belongs to an active project

On this page