Loyalty
The RSA loyalty system tracks points on an immutable transaction ledger — no UPDATE or DELETE operations are ever performed on loyalty transactions.
Point Operations
| Operation | API | Endpoint |
|---|---|---|
| Earn points (POS) | POS API | POST /pos/api/v1/loyalty/earn |
| Redeem points (POS) | POS API | POST /pos/api/v1/loyalty/redeem |
| Redeem points (self-serve) | Shopper API | POST /api/v1/loyalty/redeem |
| View balance | Shopper API | GET /api/v1/loyalty/balance |
| View transactions | Shopper API | GET /api/v1/loyalty/transactions |
| View balance (POS) | POS API | GET /pos/api/v1/members/{id}/balance |
Earn Flow (POS)
When a basket is finalized, call the loyalty earn endpoint:
/pos/api/v1/loyalty/earn{
"memberId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"basketId": "basket-uuid",
"referenceId": "pos-txn-id-001",
"points": 125,
"storeId": "store-uuid"
}
referenceId is the idempotency key — resubmitting the same referenceId returns the original transaction without double-crediting points.
Redeem Flow (Shopper)
Members redeem points via the Shopper API in their app:
/api/v1/loyalty/redeem{
"points": 500,
"referenceId": "app-redemption-uuid"
}
Redemptions are validated against the member's current balance. Insufficient balance returns 422 Unprocessable Entity.
Balance
GET /api/v1/loyalty/balance
Authorization: Bearer SHOPPER_JWT
{
"points": 1250,
"tier": "Silver",
"nextTierPoints": 2500,
"tierExpiresAt": "2026-12-31T00:00:00Z"
}
Immutability
The loyalty ledger is append-only. Corrections are made via reversal transactions, not updates. This provides a full audit trail for compliance and dispute resolution.
Campaigns
Campaign enrollment can award bonus points on completion. See Offers for campaign-offer relationships.