Server SDK
Rewards
Let members redeem their points for real-world and digital rewards
The Rewards API lets members spend their points on items from your reward catalog — discount codes, physical goods, digital downloads, raffle entries, or custom rewards.
List Rewards
Fetch all active rewards available for redemption.
GET /api/v1/rewardsQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Results per page (max 100) |
offset | number | 0 | Pagination offset |
cursor | string | — | Cursor for cursor-based pagination |
SDK
const { data: rewards, hasMore, nextCursor } = await useLoyalty.rewards.list({ limit: 20 });Response
{
"data": [
{
"id": "reward_discount_10",
"name": "10% Off Coupon",
"description": "Get 10% off your next order",
"type": "COUPON",
"pointsCost": 500,
"stock": 100,
"maxClaimsPerUser": 3,
"minLevel": null,
"imageUrl": "https://cdn.example.com/rewards/coupon.png",
"expiresAt": null,
"isActive": true
}
],
"total": 12,
"hasMore": false
}Reward Types
| Type | Description |
|---|---|
COUPON | Generates a discount code (Shopify / WooCommerce) |
PHYSICAL | Physical item — triggers fulfillment |
DIGITAL | Digital download or access code |
RAFFLE | Entry into a raffle draw |
CUSTOM | Any custom reward type |
Get Reward
Fetch a single reward by ID.
GET /api/v1/rewards/:rewardIdSDK
const reward = await useLoyalty.rewards.get('reward_discount_10');Redeem a Reward
Spend a member's points to claim a reward.
POST /api/v1/rewards/:rewardId/redeemRequest Body
{
"externalId": "user_123"
}SDK
const result = await useLoyalty.rewards.redeem('user_123', 'reward_discount_10');Response
{
"redemptionId": "rdm_abc123",
"reward": { "id": "reward_discount_10", "name": "10% Off Coupon", "type": "COUPON" },
"pointsSpent": 500,
"newBalance": 1100,
"couponCode": "JOHN-10OFF-X7K2"
}| Field | Description |
|---|---|
couponCode | Populated for COUPON type rewards; null for others |
pointsSpent | Points deducted from member's balance |
newBalance | Member's balance after redemption |
For COUPON rewards, the code is auto-generated and synced to your Shopify or WooCommerce store. Pass it directly to the user.
Get Member Redemptions
List all rewards a member has redeemed.
GET /api/v1/members/:externalId/reward-redemptionsSDK
const { data: redemptions } = await useLoyalty.rewards.getRedemptions('user_123', {
limit: 10,
});Response
{
"data": [
{
"id": "rdm_abc123",
"rewardId": "reward_discount_10",
"reward": { "name": "10% Off Coupon", "type": "COUPON" },
"memberId": "clx123abc",
"pointsSpent": 500,
"couponCode": "JOHN-10OFF-X7K2",
"createdAt": "2024-01-20T11:00:00Z"
}
],
"total": 1,
"hasMore": false
}Code Examples
Reward Catalog Page
// Fetch rewards with member's balance to show affordability
async function getRewardCatalog(userId: string) {
const [{ data: rewards }, balance] = await Promise.all([
useLoyalty.rewards.list({ limit: 50 }),
useLoyalty.members.getPoints(userId),
]);
return rewards.map(reward => ({
...reward,
canAfford: balance.points >= reward.pointsCost,
pointsNeeded: Math.max(0, reward.pointsCost - balance.points),
}));
}Handle Redemption Errors
import { UseLoyaltyError } from '@useloyalty/sdk';
async function redeemReward(userId: string, rewardId: string) {
try {
return await useLoyalty.rewards.redeem(userId, rewardId);
} catch (err) {
if (err instanceof UseLoyaltyError) {
if (err.code === 'INSUFFICIENT_POINTS') {
throw new Error('Not enough points for this reward');
}
if (err.code === 'REWARD_OUT_OF_STOCK') {
throw new Error('This reward is no longer available');
}
if (err.code === 'REWARD_ALREADY_CLAIMED') {
throw new Error('You have already claimed the maximum for this reward');
}
}
throw err;
}
}Show Coupon After Redemption
function RewardRedeemButton({ reward, userId }: { reward: Reward; userId: string }) {
const [couponCode, setCouponCode] = useState<string | null>(null);
async function handleRedeem() {
const result = await fetch('/api/rewards/redeem', {
method: 'POST',
body: JSON.stringify({ userId, rewardId: reward.id }),
}).then(r => r.json());
if (result.couponCode) {
setCouponCode(result.couponCode);
}
}
if (couponCode) {
return <code>{couponCode}</code>;
}
return (
<button onClick={handleRedeem}>
Redeem for {reward.pointsCost} pts
</button>
);
}