Rewards Block

Loyalty, Gamification & Engagement API
The Rewards Block provides a complete loyalty and gamification infrastructure for your applications. Build points systems, loyalty tiers, badge achievements, coupon campaigns, referral programs, and reward redemption - all through a simple, unified API.
Why Rewards Block?
Building engagement and loyalty features from scratch requires:
- Complex points accounting with transaction history
- Flexible tier progression algorithms
- Badge unlock conditions and achievement tracking
- Coupon generation with usage limits and expiration
- Referral attribution and multi-level tracking
- Secure reward redemption with inventory management
The Rewards Block handles all of this, letting you focus on creating engaging user experiences.
Core Concepts
| Concept | Description |
|---|---|
| Points | Virtual currency users earn through actions |
| Tiers | Loyalty levels with escalating benefits |
| Badges | Visual achievements for milestones |
| Coupons | Discount codes with rules and limits |
| Referrals | Tracking and rewarding user invitations |
| Rewards | Redeemable items in your reward catalog |
API Endpoint
| Service | URL |
|---|---|
| Rewards | https://rewards.api.us.23blocks.com |
Environment Routing: One URL, one environment. All shared-platform API keys are live keys:
pk_live_*/sk_live_*→ your production tenant. Need a separate staging environment? It is available as a paid add-on on deployments in your own cloud account — see 23blocks in a Box.
Quick Start
npm install @23blocks/sdk
import { create23BlocksClient } from '@23blocks/sdk';
const client = create23BlocksClient({
urls: { rewards: 'https://rewards.api.us.23blocks.com' },
apiKey: 'your-api-key', // Your live API key (pk_live_*)
});
// Award points for a purchase
await client.rewards.awardPoints({
userId: 'user-123',
amount: 150,
action: 'purchase',
metadata: { orderId: 'order-456' }
});
// Get user's points balance
const balance = await client.rewards.getBalance('user-123');
console.log(`User has ${balance.data.attributes.available} points`);
// Redeem a reward
await client.rewards.redeem({
userId: 'user-123',
rewardId: 'reward-789',
pointsCost: 500
});
Points API
Points are the foundation of your loyalty program. Users earn points through actions and redeem them for rewards.
Points Object
{
"data": {
"id": "points-txn-abc123",
"type": "points-transaction",
"attributes": {
"user-id": "user-123",
"amount": 150,
"type": "credit",
"action": "purchase",
"balance-after": 1250,
"description": "Points earned from order #456",
"metadata": {
"order-id": "order-456",
"amount": 75.00
},
"expires-at": "2027-01-01T00:00:00Z",
"created-at": "2026-01-02T10:30:00Z"
}
}
}
Award Points
Award points to a user for completing an action.
POST /v1/rewards/points/award
Request Body:
{
"data": {
"type": "points-award",
"attributes": {
"user-id": "user-123",
"amount": 150,
"action": "purchase",
"description": "Points for order #456",
"metadata": {
"order-id": "order-456"
},
"expires-in-days": 365
}
}
}
Response: 201 Created
{
"data": {
"id": "points-txn-abc123",
"type": "points-transaction",
"attributes": {
"user-id": "user-123",
"amount": 150,
"type": "credit",
"action": "purchase",
"balance-after": 1250,
"expires-at": "2027-01-02T10:30:00Z",
"created-at": "2026-01-02T10:30:00Z"
}
}
}
Deduct Points
Deduct points from a user's balance (for redemptions or adjustments).
POST /v1/rewards/points/deduct
Request Body:
{
"data": {
"type": "points-deduction",
"attributes": {
"user-id": "user-123",
"amount": 500,
"reason": "reward_redemption",
"description": "Redeemed for $5 discount",
"reference-id": "redemption-789"
}
}
}
Get Points Balance
Retrieve a user's current points balance.
GET /v1/rewards/points/balance/{user_id}
Response: 200 OK
{
"data": {
"id": "balance-user-123",
"type": "points-balance",
"attributes": {
"user-id": "user-123",
"total-earned": 5000,
"total-spent": 2500,
"total-expired": 250,
"available": 2250,
"pending": 100,
"expiring-soon": 500,
"expiring-soon-date": "2026-02-01T00:00:00Z",
"lifetime-value": 5000,
"updated-at": "2026-01-02T10:30:00Z"
}
}
}
List Points History
Get a user's points transaction history.
GET /v1/rewards/points/history/{user_id}
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
page[number] | integer | Page number (default: 1) |
page[size] | integer | Items per page (default: 20, max: 100) |
filter[type] | string | Filter by transaction type: credit, debit |
filter[action] | string | Filter by action type |
filter[from] | datetime | Start date for range |
filter[to] | datetime | End date for range |
Response: 200 OK
{
"data": [
{
"id": "points-txn-abc123",
"type": "points-transaction",
"attributes": {
"amount": 150,
"type": "credit",
"action": "purchase",
"balance-after": 1250,
"created-at": "2026-01-02T10:30:00Z"
}
}
],
"meta": {
"total-count": 45,
"page-count": 3
}
}
Configure Points Rules
Set up earning rules for automatic points awards.
POST /v1/rewards/points/rules
Request Body:
{
"data": {
"type": "points-rule",
"attributes": {
"name": "Purchase Points",
"action": "purchase",
"points-formula": "amount * 2",
"description": "Earn 2 points per dollar spent",
"conditions": {
"min-amount": 10,
"max-points": 1000
},
"multipliers": {
"weekend": 1.5,
"holiday": 2.0
},
"active": true
}
}
}
Tiers API
Loyalty tiers reward your most engaged customers with escalating benefits.
Tier Object
{
"data": {
"id": "tier-gold",
"type": "loyalty-tier",
"attributes": {
"name": "Gold",
"slug": "gold",
"level": 2,
"points-required": 5000,
"points-multiplier": 1.5,
"benefits": [
"15% bonus points on all purchases",
"Early access to sales",
"Free shipping on orders over $25"
],
"badge-image-url": "https://cdn.23blocks.com/badges/gold-tier.png",
"color": "#FFD700",
"member-count": 1250,
"created-at": "2025-01-01T00:00:00Z"
}
}
}
List Tiers
Retrieve all loyalty tiers.
GET /v1/rewards/tiers
Response: 200 OK
{
"data": [
{
"id": "tier-bronze",
"type": "loyalty-tier",
"attributes": {
"name": "Bronze",
"level": 0,
"points-required": 0,
"points-multiplier": 1.0
}
},
{
"id": "tier-silver",
"type": "loyalty-tier",
"attributes": {
"name": "Silver",
"level": 1,
"points-required": 1000,
"points-multiplier": 1.25
}
},
{
"id": "tier-gold",
"type": "loyalty-tier",
"attributes": {
"name": "Gold",
"level": 2,
"points-required": 5000,
"points-multiplier": 1.5
}
},
{
"id": "tier-platinum",
"type": "loyalty-tier",
"attributes": {
"name": "Platinum",
"level": 3,
"points-required": 15000,
"points-multiplier": 2.0
}
}
]
}
Create Tier
Create a new loyalty tier.
POST /v1/rewards/tiers
Request Body:
{
"data": {
"type": "loyalty-tier",
"attributes": {
"name": "Diamond",
"slug": "diamond",
"level": 4,
"points-required": 50000,
"points-multiplier": 3.0,
"benefits": [
"Triple points on all purchases",
"Personal account manager",
"Exclusive products access",
"Free express shipping"
],
"color": "#B9F2FF"
}
}
}
Get User Tier
Get a user's current tier and progress.
GET /v1/rewards/tiers/user/{user_id}
Response: 200 OK
{
"data": {
"id": "user-tier-123",
"type": "user-tier-status",
"attributes": {
"user-id": "user-123",
"current-tier": {
"id": "tier-gold",
"name": "Gold",
"level": 2
},
"next-tier": {
"id": "tier-platinum",
"name": "Platinum",
"level": 3,
"points-required": 15000
},
"qualifying-points": 8500,
"points-to-next-tier": 6500,
"progress-percentage": 56.67,
"tier-expires-at": "2026-12-31T23:59:59Z",
"points-to-maintain": 5000,
"tier-since": "2025-06-15T00:00:00Z"
}
}
}
Update User Tier
Manually upgrade or adjust a user's tier.
PATCH /v1/rewards/tiers/user/{user_id}
Request Body:
{
"data": {
"type": "user-tier-update",
"attributes": {
"tier-id": "tier-platinum",
"reason": "vip_promotion",
"expires-at": "2027-01-01T00:00:00Z"
}
}
}
Badges API
Badges are visual achievements that recognize user milestones and behaviors.
Badge Object
{
"data": {
"id": "badge-first-purchase",
"type": "badge",
"attributes": {
"name": "First Purchase",
"slug": "first-purchase",
"description": "Made your first purchase",
"category": "milestones",
"image-url": "https://cdn.23blocks.com/badges/first-purchase.png",
"points-reward": 50,
"rarity": "common",
"unlock-count": 15000,
"conditions": {
"action": "purchase",
"count": 1
},
"created-at": "2025-01-01T00:00:00Z"
}
}
}
List Badges
Retrieve all available badges.
GET /v1/rewards/badges
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
filter[category] | string | Filter by category |
filter[rarity] | string | Filter by rarity: common, uncommon, rare, epic, legendary |
Response: 200 OK
{
"data": [
{
"id": "badge-first-purchase",
"type": "badge",
"attributes": {
"name": "First Purchase",
"category": "milestones",
"rarity": "common",
"points-reward": 50
}
},
{
"id": "badge-streak-7",
"type": "badge",
"attributes": {
"name": "Week Warrior",
"category": "streaks",
"rarity": "uncommon",
"points-reward": 100
}
}
]
}
Create Badge
Create a new badge definition.
POST /v1/rewards/badges
Request Body:
{
"data": {
"type": "badge",
"attributes": {
"name": "Super Shopper",
"slug": "super-shopper",
"description": "Made 50 purchases",
"category": "milestones",
"image-url": "https://cdn.23blocks.com/badges/super-shopper.png",
"points-reward": 500,
"rarity": "rare",
"conditions": {
"action": "purchase",
"count": 50
}
}
}
}
Award Badge
Award a badge to a user.
POST /v1/rewards/badges/award
Request Body:
{
"data": {
"type": "badge-award",
"attributes": {
"user-id": "user-123",
"badge-id": "badge-super-shopper",
"reason": "Completed 50th purchase"
}
}
}
Response: 201 Created
{
"data": {
"id": "user-badge-abc123",
"type": "user-badge",
"attributes": {
"user-id": "user-123",
"badge-id": "badge-super-shopper",
"badge-name": "Super Shopper",
"points-awarded": 500,
"awarded-at": "2026-01-02T10:30:00Z"
}
}
}
Get User Badges
Retrieve badges earned by a user.
GET /v1/rewards/badges/user/{user_id}
Response: 200 OK
{
"data": [
{
"id": "user-badge-001",
"type": "user-badge",
"attributes": {
"badge-id": "badge-first-purchase",
"badge-name": "First Purchase",
"badge-image": "https://cdn.23blocks.com/badges/first-purchase.png",
"points-awarded": 50,
"awarded-at": "2025-06-01T10:00:00Z"
}
},
{
"id": "user-badge-002",
"type": "user-badge",
"attributes": {
"badge-id": "badge-streak-7",
"badge-name": "Week Warrior",
"badge-image": "https://cdn.23blocks.com/badges/week-warrior.png",
"points-awarded": 100,
"awarded-at": "2025-07-15T10:00:00Z"
}
}
],
"meta": {
"total-badges": 2,
"total-points-from-badges": 150
}
}
Get Badge Progress
Check a user's progress toward a specific badge.
GET /v1/rewards/badges/{badge_id}/progress/{user_id}
Response: 200 OK
{
"data": {
"id": "progress-badge-123-user-456",
"type": "badge-progress",
"attributes": {
"badge-id": "badge-super-shopper",
"badge-name": "Super Shopper",
"user-id": "user-456",
"target-count": 50,
"current-count": 32,
"progress-percentage": 64.0,
"earned": false,
"estimated-completion": "2026-04-15T00:00:00Z"
}
}
}
Coupons API
Create and manage discount coupons with flexible rules and usage limits.
Coupon Object
{
"data": {
"id": "coupon-summer25",
"type": "coupon",
"attributes": {
"code": "SUMMER25",
"name": "Summer Sale 25% Off",
"description": "25% off your entire order",
"discount-type": "percentage",
"discount-value": 25,
"min-order-amount": 50.00,
"max-discount-amount": 100.00,
"usage-limit": 1000,
"usage-count": 456,
"per-user-limit": 1,
"starts-at": "2026-06-01T00:00:00Z",
"expires-at": "2026-08-31T23:59:59Z",
"conditions": {
"categories": ["summer-collection"],
"new-customers-only": false
},
"active": true,
"created-at": "2026-05-15T00:00:00Z"
}
}
}
Create Coupon
Create a new coupon.
POST /v1/rewards/coupons
Request Body:
{
"data": {
"type": "coupon",
"attributes": {
"code": "NEWUSER20",
"name": "New User Welcome",
"description": "20% off your first order",
"discount-type": "percentage",
"discount-value": 20,
"min-order-amount": 25.00,
"usage-limit": null,
"per-user-limit": 1,
"expires-at": "2026-12-31T23:59:59Z",
"conditions": {
"new-customers-only": true
}
}
}
}
Discount Types:
| Type | Description | Example |
|---|---|---|
percentage | Percentage off | 25% off |
fixed | Fixed amount off | $10 off |
free_shipping | Free shipping | - |
buy_x_get_y | Buy X get Y free | Buy 2 get 1 free |
List Coupons
Retrieve all coupons.
GET /v1/rewards/coupons
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
filter[active] | boolean | Filter by active status |
filter[expires-after] | datetime | Filter by expiration date |
search | string | Search by code or name |
Get Coupon
Retrieve a specific coupon by ID or code.
GET /v1/rewards/coupons/{id_or_code}
Validate Coupon
Check if a coupon is valid for a specific user and order.
POST /v1/rewards/coupons/validate
Request Body:
{
"data": {
"type": "coupon-validation",
"attributes": {
"code": "SUMMER25",
"user-id": "user-123",
"order-amount": 75.00,
"items": [
{
"product-id": "prod-001",
"category": "summer-collection",
"quantity": 2,
"price": 37.50
}
]
}
}
}
Response: 200 OK
{
"data": {
"type": "coupon-validation-result",
"attributes": {
"valid": true,
"coupon-code": "SUMMER25",
"discount-type": "percentage",
"discount-value": 25,
"discount-amount": 18.75,
"final-amount": 56.25,
"message": "Coupon applied successfully"
}
}
}
Validation Errors:
{
"data": {
"type": "coupon-validation-result",
"attributes": {
"valid": false,
"coupon-code": "SUMMER25",
"error-code": "usage_limit_reached",
"message": "This coupon has reached its usage limit"
}
}
}
Redeem Coupon
Record a coupon usage.
POST /v1/rewards/coupons/redeem
Request Body:
{
"data": {
"type": "coupon-redemption",
"attributes": {
"code": "SUMMER25",
"user-id": "user-123",
"order-id": "order-456",
"discount-amount": 18.75
}
}
}
Generate Unique Codes
Generate a batch of unique coupon codes.
POST /v1/rewards/coupons/generate
Request Body:
{
"data": {
"type": "coupon-generation",
"attributes": {
"campaign-id": "summer-2026",
"count": 1000,
"prefix": "SUM26",
"discount-type": "percentage",
"discount-value": 15,
"per-user-limit": 1,
"expires-at": "2026-08-31T23:59:59Z"
}
}
}
Response: 201 Created
{
"data": {
"type": "coupon-generation-result",
"attributes": {
"campaign-id": "summer-2026",
"codes-generated": 1000,
"sample-codes": [
"SUM26-A7X9K2",
"SUM26-B3M4P8",
"SUM26-C5N7Q1"
],
"download-url": "https://api.23blocks.com/v1/rewards/coupons/download/summer-2026"
}
}
}
Referrals API
Track referrals and reward users for bringing in new customers.
Referral Object
{
"data": {
"id": "referral-abc123",
"type": "referral",
"attributes": {
"referrer-id": "user-123",
"referee-id": "user-456",
"referral-code": "JOHN25",
"status": "completed",
"referrer-reward": {
"type": "points",
"amount": 500,
"status": "paid"
},
"referee-reward": {
"type": "discount",
"value": 25,
"status": "paid"
},
"qualifying-action": "first_purchase",
"qualifying-amount": 75.00,
"created-at": "2026-01-01T10:00:00Z",
"completed-at": "2026-01-02T15:30:00Z"
}
}
}
Get Referral Code
Get or create a user's referral code.
GET /v1/rewards/referrals/code/{user_id}
Response: 200 OK
{
"data": {
"id": "ref-code-123",
"type": "referral-code",
"attributes": {
"user-id": "user-123",
"code": "JOHN25",
"share-url": "https://yourapp.com/invite/JOHN25",
"total-referrals": 12,
"successful-referrals": 8,
"pending-referrals": 2,
"total-rewards-earned": 4000,
"created-at": "2025-01-15T00:00:00Z"
}
}
}
Track Referral
Record when a new user signs up with a referral code.
POST /v1/rewards/referrals/track
Request Body:
{
"data": {
"type": "referral-tracking",
"attributes": {
"referral-code": "JOHN25",
"referee-id": "user-789",
"referee-email": "newuser@example.com"
}
}
}
Complete Referral
Mark a referral as completed when the qualifying action occurs.
POST /v1/rewards/referrals/complete
Request Body:
{
"data": {
"type": "referral-completion",
"attributes": {
"referral-id": "referral-abc123",
"qualifying-action": "first_purchase",
"qualifying-amount": 75.00,
"order-id": "order-456"
}
}
}
List User Referrals
Get all referrals made by a user.
GET /v1/rewards/referrals/user/{user_id}
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
filter[status] | string | Filter by status: pending, completed, expired |
Response: 200 OK
{
"data": [
{
"id": "referral-001",
"type": "referral",
"attributes": {
"referee-email": "friend1@example.com",
"status": "completed",
"reward-amount": 500,
"completed-at": "2026-01-02T15:30:00Z"
}
},
{
"id": "referral-002",
"type": "referral",
"attributes": {
"referee-email": "friend2@example.com",
"status": "pending",
"created-at": "2026-01-05T10:00:00Z"
}
}
],
"meta": {
"total-referrals": 12,
"successful": 8,
"pending": 2,
"expired": 2,
"total-rewards": 4000
}
}
Configure Referral Program
Set up referral program rules.
POST /v1/rewards/referrals/config
Request Body:
{
"data": {
"type": "referral-config",
"attributes": {
"referrer-reward": {
"type": "points",
"amount": 500
},
"referee-reward": {
"type": "percentage_discount",
"value": 25,
"max-discount": 50
},
"qualifying-action": "first_purchase",
"min-qualifying-amount": 25.00,
"expiration-days": 30,
"max-referrals-per-user": null,
"double-sided": true
}
}
}
Rewards Catalog API
Manage redeemable rewards in your catalog.
Reward Object
{
"data": {
"id": "reward-free-shipping",
"type": "reward",
"attributes": {
"name": "Free Shipping",
"slug": "free-shipping",
"description": "Get free shipping on your next order",
"category": "discounts",
"points-cost": 250,
"type": "free_shipping",
"value": null,
"image-url": "https://cdn.23blocks.com/rewards/free-shipping.png",
"inventory": null,
"redemption-limit": 1,
"active": true,
"redemption-count": 5420,
"created-at": "2025-01-01T00:00:00Z"
}
}
}
List Rewards
Retrieve all available rewards.
GET /v1/rewards/catalog
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
filter[category] | string | Filter by category |
filter[max-points] | integer | Filter by maximum points cost |
filter[available] | boolean | Only show in-stock rewards |
sort | string | Sort by: points-cost, -points-cost, popular |
Response: 200 OK
{
"data": [
{
"id": "reward-5-off",
"type": "reward",
"attributes": {
"name": "$5 Off Coupon",
"points-cost": 500,
"category": "discounts",
"type": "fixed_discount",
"value": 5.00
}
},
{
"id": "reward-free-shipping",
"type": "reward",
"attributes": {
"name": "Free Shipping",
"points-cost": 250,
"category": "discounts",
"type": "free_shipping"
}
},
{
"id": "reward-tshirt",
"type": "reward",
"attributes": {
"name": "Branded T-Shirt",
"points-cost": 2500,
"category": "merchandise",
"type": "physical_product",
"inventory": 50
}
}
]
}
Create Reward
Add a new reward to the catalog.
POST /v1/rewards/catalog
Request Body:
{
"data": {
"type": "reward",
"attributes": {
"name": "VIP Event Access",
"slug": "vip-event",
"description": "Exclusive access to our annual VIP event",
"category": "experiences",
"points-cost": 10000,
"type": "experience",
"image-url": "https://cdn.23blocks.com/rewards/vip-event.png",
"inventory": 100,
"redemption-limit": 1,
"available-from": "2026-06-01T00:00:00Z",
"available-until": "2026-09-01T00:00:00Z"
}
}
}
Redeem Reward
Redeem a reward for a user.
POST /v1/rewards/catalog/redeem
Request Body:
{
"data": {
"type": "reward-redemption",
"attributes": {
"user-id": "user-123",
"reward-id": "reward-5-off",
"metadata": {
"size": "L",
"color": "blue"
}
}
}
}
Response: 201 Created
{
"data": {
"id": "redemption-xyz789",
"type": "reward-redemption",
"attributes": {
"user-id": "user-123",
"reward-id": "reward-5-off",
"reward-name": "$5 Off Coupon",
"points-spent": 500,
"status": "fulfilled",
"fulfillment": {
"type": "coupon_code",
"code": "REWARD-XYZ789",
"expires-at": "2026-02-01T23:59:59Z"
},
"created-at": "2026-01-02T10:30:00Z"
}
}
}
Get User Redemptions
List a user's reward redemption history.
GET /v1/rewards/catalog/redemptions/{user_id}
Response: 200 OK
{
"data": [
{
"id": "redemption-001",
"type": "reward-redemption",
"attributes": {
"reward-name": "Free Shipping",
"points-spent": 250,
"status": "used",
"created-at": "2025-12-15T10:00:00Z",
"used-at": "2025-12-18T14:30:00Z"
}
}
],
"meta": {
"total-redemptions": 5,
"total-points-spent": 2750
}
}
Leaderboards API
Create competitive engagement with leaderboards.
Leaderboard Object
{
"data": {
"id": "leaderboard-monthly-points",
"type": "leaderboard",
"attributes": {
"name": "Monthly Top Earners",
"slug": "monthly-top-earners",
"metric": "points-earned",
"period": "monthly",
"reset-day": 1,
"max-entries": 100,
"rewards": [
{ "rank": 1, "prize": "1000 bonus points" },
{ "rank": 2, "prize": "500 bonus points" },
{ "rank": 3, "prize": "250 bonus points" }
],
"active": true
}
}
}
Get Leaderboard
Retrieve leaderboard rankings.
GET /v1/rewards/leaderboards/{leaderboard_id}
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
limit | integer | Number of entries (default: 10, max: 100) |
period | string | Specific period: current, previous, 2026-01 |
Response: 200 OK
{
"data": {
"id": "leaderboard-monthly-points",
"type": "leaderboard",
"attributes": {
"name": "Monthly Top Earners",
"period": "2026-01",
"entries": [
{
"rank": 1,
"user-id": "user-456",
"display-name": "Sarah M.",
"avatar-url": "https://cdn.23blocks.com/avatars/user-456.jpg",
"score": 15000,
"prize": "1000 bonus points"
},
{
"rank": 2,
"user-id": "user-789",
"display-name": "John D.",
"avatar-url": "https://cdn.23blocks.com/avatars/user-789.jpg",
"score": 12500,
"prize": "500 bonus points"
},
{
"rank": 3,
"user-id": "user-123",
"display-name": "Emma L.",
"avatar-url": "https://cdn.23blocks.com/avatars/user-123.jpg",
"score": 10200,
"prize": "250 bonus points"
}
],
"updated-at": "2026-01-02T12:00:00Z"
}
}
}
Get User Rank
Get a specific user's rank on a leaderboard.
GET /v1/rewards/leaderboards/{leaderboard_id}/rank/{user_id}
Response: 200 OK
{
"data": {
"type": "user-leaderboard-rank",
"attributes": {
"user-id": "user-123",
"leaderboard-id": "leaderboard-monthly-points",
"rank": 3,
"score": 10200,
"percentile": 97.5,
"users-above": 2,
"users-below": 78,
"distance-to-next-rank": 2300,
"updated-at": "2026-01-02T12:00:00Z"
}
}
}
Create Leaderboard
Create a new leaderboard.
POST /v1/rewards/leaderboards
Request Body:
{
"data": {
"type": "leaderboard",
"attributes": {
"name": "Top Referrers",
"slug": "top-referrers",
"metric": "referral-count",
"period": "all-time",
"max-entries": 50,
"rewards": [
{ "rank": 1, "prize": "5000 bonus points" }
]
}
}
}
Streaks API
Encourage consistent engagement with streak tracking.
Streak Object
{
"data": {
"id": "streak-user-123-daily-login",
"type": "user-streak",
"attributes": {
"user-id": "user-123",
"streak-type": "daily-login",
"current-streak": 15,
"longest-streak": 45,
"last-action-at": "2026-01-02T08:30:00Z",
"streak-expires-at": "2026-01-03T23:59:59Z",
"milestones-reached": [7, 14],
"next-milestone": 30,
"rewards-earned": 150
}
}
}
Get User Streak
Get a user's streak status.
GET /v1/rewards/streaks/{user_id}/{streak_type}
Response: 200 OK
{
"data": {
"id": "streak-user-123-daily-login",
"type": "user-streak",
"attributes": {
"current-streak": 15,
"longest-streak": 45,
"next-milestone": 30,
"days-to-milestone": 15,
"streak-expires-at": "2026-01-03T23:59:59Z",
"time-remaining": "15:29:32"
}
}
}
Record Streak Action
Record an action that extends a streak.
POST /v1/rewards/streaks/record
Request Body:
{
"data": {
"type": "streak-action",
"attributes": {
"user-id": "user-123",
"streak-type": "daily-login"
}
}
}
Response: 200 OK
{
"data": {
"type": "streak-update",
"attributes": {
"previous-streak": 14,
"current-streak": 15,
"milestone-reached": null,
"bonus-points": 0,
"streak-expires-at": "2026-01-03T23:59:59Z"
}
}
}
Configure Streak
Set up a streak type with milestones and rewards.
POST /v1/rewards/streaks/config
Request Body:
{
"data": {
"type": "streak-config",
"attributes": {
"streak-type": "daily-purchase",
"name": "Daily Purchase Streak",
"period": "daily",
"grace-period-hours": 0,
"milestones": [
{ "days": 3, "points": 25 },
{ "days": 7, "points": 100 },
{ "days": 14, "points": 250 },
{ "days": 30, "points": 1000 }
]
}
}
}
Challenges API
Create time-limited challenges to drive specific behaviors.
Challenge Object
{
"data": {
"id": "challenge-winter-2026",
"type": "challenge",
"attributes": {
"name": "Winter Challenge",
"description": "Complete 5 purchases in January to earn 500 bonus points",
"type": "action_count",
"action": "purchase",
"target": 5,
"reward": {
"type": "points",
"amount": 500
},
"starts-at": "2026-01-01T00:00:00Z",
"ends-at": "2026-01-31T23:59:59Z",
"participants-count": 2500,
"completions-count": 450,
"active": true
}
}
}
List Challenges
Get all active challenges.
GET /v1/rewards/challenges
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
filter[active] | boolean | Show only active challenges |
filter[user-id] | string | Include user's progress |
Join Challenge
Enroll a user in a challenge.
POST /v1/rewards/challenges/{challenge_id}/join
Request Body:
{
"data": {
"type": "challenge-enrollment",
"attributes": {
"user-id": "user-123"
}
}
}
Get Challenge Progress
Get a user's progress in a challenge.
GET /v1/rewards/challenges/{challenge_id}/progress/{user_id}
Response: 200 OK
{
"data": {
"type": "challenge-progress",
"attributes": {
"challenge-id": "challenge-winter-2026",
"user-id": "user-123",
"target": 5,
"current": 3,
"progress-percentage": 60.0,
"completed": false,
"time-remaining": "23 days 14:30:00",
"enrolled-at": "2026-01-02T10:00:00Z"
}
}
}
Webhooks
Subscribe to reward events for real-time updates.
Available Events
| Event | Description |
|---|---|
points.awarded | Points credited to a user |
points.deducted | Points deducted from a user |
points.expired | Points expired |
tier.upgraded | User upgraded to a new tier |
tier.downgraded | User downgraded to a lower tier |
badge.awarded | Badge awarded to a user |
coupon.redeemed | Coupon was used |
coupon.expired | Coupon expired |
referral.tracked | New referral tracked |
referral.completed | Referral completed and rewards issued |
reward.redeemed | Reward redeemed from catalog |
streak.milestone | Streak milestone reached |
streak.broken | Streak was broken |
challenge.completed | Challenge completed |
leaderboard.rank_changed | User's leaderboard rank changed |
Webhook Payload Example
{
"id": "evt_abc123",
"type": "tier.upgraded",
"created_at": "2026-01-02T10:30:00Z",
"data": {
"user_id": "user-123",
"previous_tier": {
"id": "tier-silver",
"name": "Silver",
"level": 1
},
"new_tier": {
"id": "tier-gold",
"name": "Gold",
"level": 2
},
"qualifying_points": 5250
}
}
Register Webhook
POST /v1/rewards/webhooks
Request Body:
{
"data": {
"type": "webhook",
"attributes": {
"url": "https://yourapp.com/webhooks/rewards",
"events": [
"tier.upgraded",
"badge.awarded",
"reward.redeemed"
],
"secret": "whsec_your_secret_key"
}
}
}
SDK Examples
JavaScript/TypeScript
import { create23BlocksClient } from '@23blocks/sdk';
const client = create23BlocksClient({
urls: { rewards: 'https://rewards.api.us.23blocks.com' },
appId: process.env.BLOCKS_APP_ID,
});
// Award points for a purchase
async function handlePurchase(userId: string, orderTotal: number) {
const pointsEarned = Math.floor(orderTotal * 2); // 2 points per dollar
const result = await client.rewards.points.award({
userId,
amount: pointsEarned,
action: 'purchase',
metadata: { orderTotal }
});
// Check for tier upgrade
const tierStatus = await client.rewards.tiers.getUserStatus(userId);
if (tierStatus.data.attributes['tier-upgraded']) {
// Notify user of tier upgrade
}
return result;
}
// Get user's complete rewards profile
async function getRewardsProfile(userId: string) {
const [balance, tier, badges, streaks] = await Promise.all([
client.rewards.points.getBalance(userId),
client.rewards.tiers.getUserStatus(userId),
client.rewards.badges.getUserBadges(userId),
client.rewards.streaks.getAll(userId)
]);
return {
points: balance.data.attributes,
tier: tier.data.attributes,
badges: badges.data,
streaks: streaks.data
};
}
// Apply a referral code
async function applyReferralCode(code: string, newUserId: string) {
try {
await client.rewards.referrals.track({
referralCode: code,
refereeId: newUserId
});
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
}
React Hook Example
import { useRewards } from '@23blocks/react';
function LoyaltyDashboard({ userId }: { userId: string }) {
const {
balance,
tier,
badges,
isLoading,
refetch
} = useRewards(userId);
if (isLoading) return <LoadingSpinner />;
return (
<div className="loyalty-dashboard">
<div className="points-card">
<h2>{balance.available} Points</h2>
<p>Lifetime: {balance.totalEarned} earned</p>
</div>
<div className="tier-card">
<img src={tier.badgeImageUrl} alt={tier.name} />
<h3>{tier.name} Member</h3>
<div className="progress-bar">
<div
className="progress"
style={{ width: `${tier.progressPercentage}%` }}
/>
</div>
<p>{tier.pointsToNextTier} points to {tier.nextTier.name}</p>
</div>
<div className="badges-grid">
{badges.map(badge => (
<div key={badge.id} className="badge">
<img src={badge.imageUrl} alt={badge.name} />
<span>{badge.name}</span>
</div>
))}
</div>
</div>
);
}
Error Codes
| Code | Description |
|---|---|
insufficient_points | User doesn't have enough points |
invalid_coupon | Coupon code is invalid |
coupon_expired | Coupon has expired |
coupon_usage_limit | Coupon usage limit reached |
coupon_already_used | User already used this coupon |
reward_out_of_stock | Reward is not available |
reward_limit_reached | User reached redemption limit |
tier_not_found | Tier doesn't exist |
badge_already_awarded | User already has this badge |
referral_invalid | Invalid referral code |
referral_self | Cannot refer yourself |
streak_not_active | No active streak for this type |
challenge_ended | Challenge has ended |
challenge_not_enrolled | User not enrolled in challenge |
Rate Limits
| Endpoint | Rate Limit |
|---|---|
| Points operations | 100/min per user |
| Badge awards | 50/min per user |
| Coupon validation | 200/min per user |
| Leaderboard reads | 60/min |
| Webhook deliveries | 10,000/hour |
Related Resources
- Auth Block - User authentication and management
- Onboarding Block - User journey tracking
- Sales Block - Payments and subscriptions
- Frontend SDK - Client-side integration
Use This Block with AI Agents
This block ships an official Claude Code plugin from the public 23blocks marketplace (19 plugins, 205 skills). Your agent gets full working knowledge of this API — endpoints, identity registration, and conventions.
# one-time: add the 23blocks marketplace
claude plugin marketplace add https://github.com/23blocks-OS/ai-agents
# install this block's plugin
claude plugin install rewards-block
Configure BLOCKS_API_URL, BLOCKS_API_KEY, and BLOCKS_AUTH_TOKEN. Register identity first: each block is autonomous — register the user with this block's identity endpoint before private calls (only user_unique_id is required; email/phone are optional notification-routing fields).
Full reference: AI Agents & Claude Code Plugins · github.com/23blocks-OS/ai-agents