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
| Attribute | Value |
|---|---|
| Base Path | /api/v1/loyalty |
| Authentication | Bearer Token |
| Required Roles | pos_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
| Parameter | Type | Description |
|---|---|---|
tier | string | Filter by tier |
status | string | active, inactive, suspended |
search | string | Search name/email/phone |
enrolled_after | date | Filter 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
| Parameter | Type | Description |
|---|---|---|
type | string | earn, redeem, expire, adjust |
start_date | date | Period start |
end_date | date | Period 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
| Parameter | Type | Description |
|---|---|---|
category | string | Filter by category |
tier | string | Filter by required tier |
max_points | integer | Filter by max point cost |
status | string | active, 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
| Parameter | Type | Description |
|---|---|---|
period | string | month, 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
| Event | Description |
|---|---|
loyalty.member_enrolled | New member joined |
loyalty.points_earned | Points awarded |
loyalty.points_redeemed | Points redeemed |
loyalty.tier_changed | Member tier changed |
loyalty.reward_issued | Reward issued to member |
loyalty.points_expiring | Points about to expire |
loyalty.birthday_upcoming | Member birthday approaching |
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | insufficient_points | Not enough points |
| 400 | reward_unavailable | Reward not available |
| 404 | member_not_found | Member ID not found |
| 409 | already_enrolled | Customer already a member |
| 422 | tier_requirement_not_met | Doesn't meet tier requirements |
Related Documentation
- Customers API - Customer data
- Marketing API - Promotions
- Gift Cards API - Gift cards