API Reference
The LoyaltyPro REST API follows standard HTTP conventions. All responses are JSON. Errors follow RFC 7807 Problem Details format.
Base URL
BASH
https://loyalty-engine-production-e5cb.up.railway.app/v1All endpoints are versioned under /v1. Monetary amounts are always in cents — R150.00 = 15000. UUIDs throughout.
Authentication
Pass your API key in X-API-Key, or a JWT in Authorization: Bearer. Test keys (sk_test_*) enable debug hints and request logs. Live keys (sk_live_*) are for production.
BASH
# API Key (server-to-server, POS)
curl "https://loyalty-engine-production-e5cb.up.railway.app/v1/tenants/$TENANT_ID/members" \
-H "X-API-Key: sk_test_YOUR_KEY"
# JWT Bearer (merchant portal)
curl "https://loyalty-engine-production-e5cb.up.railway.app/v1/tenants/$TENANT_ID/members" \
-H "Authorization: Bearer YOUR_JWT"Conventions
Idempotency
POST /transactions/evaluate and POST /transactions/redeem are fully idempotent. Pass the same transactionRef and you receive the original result — never a duplicate award or double-deduction. Safe to retry on network failures.
Error format
All errors return a RFC 7807 Problem Details object:
JSON
{
"type": "https://loyalty-engine.yoyo.co.za/errors/insufficient-points",
"title": "Insufficient Points",
"status": 422,
"detail": "Member only has 300 points; 500 requested.",
"requestId": "req_a1b2c3d4-...",
"context": { "available": 300, "requested": 500 }
}Error codes
Earn at checkout — points & rewards
cURL
curl -X POST "https://loyalty-engine-production-e5cb.up.railway.app/v1/tenants/$TENANT_ID/transactions/evaluate" \
-H "X-API-Key: sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"transactionRef": "receipt_001",
"memberRef": "customer_27821234567",
"amount": 15000
}'Response
200 OK
{
"transactionId": "d2f3a1b4-0e5c-4a8b-9f1d-2c3e4f5a6b7c",
"transactionRef": "receipt_001",
"memberId": "9f4c2e8a-1b2c-3d4e-5f6a-7b8c9d0e1f2a",
"memberCreated": true,
"pointsAwarded": 150,
"pointsBalance": 150,
"campaigns": [
{
"campaignId": "5a7b3c9d-...",
"campaignName": "Spend & Earn",
"pointsEarned": 150,
"rewardIds": []
}
],
"state": "PROCESSED"
}