Skip to main content
Authenticated API

This endpoint requires a valid JWT Bearer token. Accessible via the API gateway at /v1/commerce/*.

Loyalty & Rewards API

Loyalty program management, points earning/redemption, membership tiers, and gamification.

Overview

AttributeValue
Base Path/api/v1/loyalty
AuthenticationBearer Token
Required Rolespos_staff, server, manager, restaurant_manager, marketing, bartender, cashier, host, restaurant_staff, tenant_admin, platform_admin, system_admin, super_admin

Members

List Members

GET /api/v1/loyalty/members

Query Parameters

ParameterTypeDescription
tierstringFilter by tier
statusstringactive, inactive, suspended
searchstringSearch name/email/phone
enrolled_afterdateFilter by enrollment date

Response

{
"members": [
{
"id": "member_001",
"customer_id": "cust_abc",
"member_number": "LOYAL-2024-0001",
"name": "John Smith",
"email": "john@example.com",
"phone": "+15551234567",
"tier": {
"id": "tier_gold",
"name": "Gold",
"color": "#FFD700"
},
"points": {
"available": 2450,
"lifetime": 15680,
"pending": 125
},
"status": "active",
"enrolled_at": "2024-03-15T00:00:00Z",
"last_activity": "2026-01-24T18:30:00Z",
"visits_ytd": 45,
"spend_ytd": 2850.00
}
],
"total": 5420
}

Enroll Member

POST /api/v1/loyalty/members

Request Body

{
"customer_id": "cust_xyz",
"email": "jane@example.com",
"phone": "+15559876543",
"name": "Jane Doe",
"birthday": "1990-05-15",
"preferences": {
"communication": ["email", "sms"],
"favorite_items": []
},
"referral_code": "FRIEND123",
"signup_bonus": true
}

Response

{
"id": "member_002",
"member_number": "LOYAL-2026-0542",
"tier": {
"id": "tier_bronze",
"name": "Bronze"
},
"points": {
"available": 500,
"note": "Signup bonus applied"
},
"welcome_reward": {
"reward_id": "reward_welcome",
"description": "Free appetizer on your next visit",
"expires_at": "2026-02-24T23:59:59Z"
},
"referral_bonus": {
"applied": true,
"referrer_id": "member_045",
"points_awarded": 250
}
}

Get Member

GET /api/v1/loyalty/members/{member_id}

Response

{
"id": "member_001",
"member_number": "LOYAL-2024-0001",
"customer_id": "cust_abc",
"name": "John Smith",
"email": "john@example.com",
"phone": "+15551234567",
"birthday": "1985-08-22",
"tier": {
"id": "tier_gold",
"name": "Gold",
"benefits": [
"2x points on all purchases",
"Free birthday reward",
"Early access to promotions",
"Exclusive member events"
],
"progress_to_next": {
"next_tier": "Platinum",
"current_spend": 2850.00,
"required_spend": 5000.00,
"progress_percent": 57
}
},
"points": {
"available": 2450,
"pending": 125,
"expiring_soon": {
"amount": 500,
"expires_at": "2026-03-31"
},
"lifetime": 15680
},
"rewards": {
"available": [
{
"id": "member_reward_001",
"reward_id": "reward_free_dessert",
"name": "Free Dessert",
"expires_at": "2026-02-28"
}
],
"redeemed_count": 12
},
"activity": {
"visits_total": 125,
"visits_ytd": 45,
"spend_total": 8500.00,
"spend_ytd": 2850.00,
"avg_visit_spend": 68.00,
"last_visit": "2026-01-24",
"visit_frequency": "weekly"
},
"preferences": {
"favorite_items": ["Ribeye Steak", "Caesar Salad"],
"dietary": ["gluten_free"],
"seating": "booth"
},
"status": "active",
"enrolled_at": "2024-03-15T00:00:00Z"
}

Update Member

PUT /api/v1/loyalty/members/{member_id}

Points

Earn Points

Award points to a member.

POST /api/v1/loyalty/members/{member_id}/points/earn

Request Body

{
"order_id": "ord_12345",
"amount": 85.50,
"multiplier": 2.0,
"bonus_points": 50,
"reason": "purchase"
}

Response

{
"transaction_id": "pts_txn_001",
"points_earned": {
"base": 86,
"multiplier_bonus": 86,
"extra_bonus": 50,
"total": 222
},
"new_balance": 2672,
"tier_progress": {
"earned_toward_tier": 85.50,
"progress_percent": 60
}
}

Redeem Points

POST /api/v1/loyalty/members/{member_id}/points/redeem

Request Body

{
"reward_id": "reward_10_off",
"points_cost": 500,
"order_id": "ord_12346"
}

Response

{
"redemption_id": "redeem_001",
"reward": {
"id": "reward_10_off",
"name": "$10 Off",
"type": "discount",
"value": 10.00
},
"points_spent": 500,
"new_balance": 2172,
"coupon_code": "LOYAL-ABC123",
"valid_until": "2026-01-31T23:59:59Z"
}

Adjust Points

Manual point adjustment.

POST /api/v1/loyalty/members/{member_id}/points/adjust

Request Body

{
"amount": 100,
"type": "credit",
"reason": "customer_service_gesture",
"notes": "Compensation for delayed order",
"authorized_by": "manager_001"
}

Get Points History

GET /api/v1/loyalty/members/{member_id}/points/history

Query Parameters

ParameterTypeDescription
typestringearn, redeem, expire, adjust
start_datedatePeriod start
end_datedatePeriod end

Response

{
"transactions": [
{
"id": "pts_txn_001",
"type": "earn",
"amount": 222,
"balance_after": 2672,
"reason": "Purchase - Order #12345",
"timestamp": "2026-01-24T18:30:00Z"
},
{
"id": "pts_txn_002",
"type": "redeem",
"amount": -500,
"balance_after": 2172,
"reason": "Redeemed: $10 Off",
"timestamp": "2026-01-24T18:35:00Z"
}
],
"summary": {
"total_earned": 15680,
"total_redeemed": 13008,
"total_expired": 220
}
}

Rewards Catalog

List Rewards

GET /api/v1/loyalty/rewards

Query Parameters

ParameterTypeDescription
categorystringFilter by category
tierstringFilter by required tier
max_pointsintegerFilter by max point cost
statusstringactive, inactive

Response

{
"rewards": [
{
"id": "reward_free_appetizer",
"name": "Free Appetizer",
"description": "Choose any appetizer from our menu",
"category": "food",
"points_cost": 300,
"value": 12.00,
"image_url": "https://...",
"tier_required": null,
"availability": {
"start_date": null,
"end_date": null,
"days_of_week": ["all"],
"max_redemptions_per_day": null
},
"terms": "Cannot be combined with other offers",
"popularity_rank": 1,
"redemption_count": 1250
},
{
"id": "reward_10_off",
"name": "$10 Off Your Order",
"description": "Save $10 on any order of $30 or more",
"category": "discount",
"points_cost": 500,
"value": 10.00,
"tier_required": null,
"minimum_order": 30.00
},
{
"id": "reward_vip_event",
"name": "VIP Tasting Event",
"description": "Exclusive invite to our seasonal tasting event",
"category": "experience",
"points_cost": 2500,
"tier_required": "gold",
"availability": {
"quantity_remaining": 25
}
}
]
}

Create Reward

POST /api/v1/loyalty/rewards

Request Body

{
"name": "Free Birthday Dessert",
"description": "Celebrate with a free dessert on your birthday",
"category": "food",
"points_cost": 0,
"value": 8.00,
"type": "birthday",
"tier_required": null,
"availability": {
"birthday_month_only": true
},
"auto_issue": true
}

Get Reward

GET /api/v1/loyalty/rewards/{reward_id}

Update Reward

PUT /api/v1/loyalty/rewards/{reward_id}

Tiers

List Tiers

GET /api/v1/loyalty/tiers

Response

{
"tiers": [
{
"id": "tier_bronze",
"name": "Bronze",
"color": "#CD7F32",
"order": 1,
"requirements": {
"type": "signup",
"description": "Default tier for all members"
},
"benefits": [
{"type": "points_multiplier", "value": 1.0, "description": "1 point per $1"},
{"type": "birthday_reward", "value": true}
],
"member_count": 3500
},
{
"id": "tier_silver",
"name": "Silver",
"color": "#C0C0C0",
"order": 2,
"requirements": {
"type": "spend",
"amount": 500,
"period": "year"
},
"benefits": [
{"type": "points_multiplier", "value": 1.5, "description": "1.5x points"},
{"type": "birthday_reward", "value": true},
{"type": "exclusive_offers", "value": true}
],
"member_count": 1200
},
{
"id": "tier_gold",
"name": "Gold",
"color": "#FFD700",
"order": 3,
"requirements": {
"type": "spend",
"amount": 1500,
"period": "year"
},
"benefits": [
{"type": "points_multiplier", "value": 2.0, "description": "2x points"},
{"type": "birthday_reward", "value": true},
{"type": "exclusive_offers", "value": true},
{"type": "priority_seating", "value": true},
{"type": "early_access", "value": true}
],
"member_count": 450
},
{
"id": "tier_platinum",
"name": "Platinum",
"color": "#E5E4E2",
"order": 4,
"requirements": {
"type": "spend",
"amount": 5000,
"period": "year"
},
"benefits": [
{"type": "points_multiplier", "value": 3.0, "description": "3x points"},
{"type": "birthday_reward", "value": true},
{"type": "exclusive_offers", "value": true},
{"type": "priority_seating", "value": true},
{"type": "early_access", "value": true},
{"type": "complimentary_valet", "value": true},
{"type": "dedicated_concierge", "value": true}
],
"member_count": 75
}
]
}

Upgrade Member Tier

POST /api/v1/loyalty/members/{member_id}/tier/upgrade

Request Body

{
"new_tier_id": "tier_gold",
"reason": "promotional_upgrade",
"expires_at": "2026-12-31"
}

Campaigns

List Campaigns

GET /api/v1/loyalty/campaigns

Response

{
"campaigns": [
{
"id": "campaign_double_points",
"name": "Double Points Weekend",
"type": "multiplier",
"status": "active",
"start_date": "2026-01-25",
"end_date": "2026-01-26",
"rules": {
"multiplier": 2.0,
"applies_to": "all_purchases"
},
"target_audience": "all_members",
"performance": {
"members_participated": 450,
"points_awarded": 25000,
"incremental_revenue": 12500.00
}
},
{
"id": "campaign_lapsed",
"name": "Win Back Lapsed Members",
"type": "bonus",
"status": "active",
"rules": {
"bonus_points": 500,
"trigger": "first_visit_after_90_days"
},
"target_audience": {
"filter": "last_visit_over_90_days"
}
}
]
}

Create Campaign

POST /api/v1/loyalty/campaigns

Analytics

Get Program Analytics

GET /api/v1/loyalty/analytics

Query Parameters

ParameterTypeDescription
periodstringmonth, quarter, year

Response

{
"period": "month",
"members": {
"total_active": 5225,
"new_enrollments": 285,
"churn_rate": 0.02,
"by_tier": {
"bronze": 3500,
"silver": 1200,
"gold": 450,
"platinum": 75
}
},
"engagement": {
"active_rate": 0.68,
"avg_visits_per_member": 3.2,
"avg_spend_per_member": 185.00
},
"points": {
"issued": 125000,
"redeemed": 85000,
"expired": 5000,
"liability": 450000
},
"rewards": {
"redemptions": 1250,
"top_rewards": [
{"name": "Free Appetizer", "count": 450},
{"name": "$10 Off", "count": 380}
]
},
"roi": {
"member_spend_vs_non_member": 2.3,
"incremental_revenue": 125000.00,
"program_cost": 35000.00,
"roi_percent": 257
}
}

Webhooks

EventDescription
loyalty.member_enrolledNew member joined
loyalty.points_earnedPoints awarded
loyalty.points_redeemedPoints redeemed
loyalty.tier_changedMember tier changed
loyalty.reward_issuedReward issued to member
loyalty.points_expiringPoints about to expire
loyalty.birthday_upcomingMember birthday approaching

Error Responses

StatusCodeDescription
400insufficient_pointsNot enough points
400reward_unavailableReward not available
404member_not_foundMember ID not found
409already_enrolledCustomer already a member
422tier_requirement_not_metDoesn't meet tier requirements