Analytics
The Analytics API provides insights and metrics about your loyalty program's performance.
Endpoints
Get Analytics
Retrieve analytics and insights for your loyalty program.
Endpoint: GET /analytics
Query Parameters:
startDate
string
No
ISO 8601 date string (default: 30 days ago)
endDate
string
No
ISO 8601 date string (default: now)
metric
string
No
Specific metric to retrieve
Example Request:
curl -X GET "https://api.monterosa.cloud/loyalty/v1/analytics?startDate=2025-09-01&endDate=2025-10-01" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: YOUR_ORG_UUID"Example Response:
{
"success": true,
"data": {
"orgId": "550e8400-e29b-41d4-a716-446655440000",
"period": {
"start": "2025-09-05T17:46:13.830Z",
"end": "2025-10-05T17:46:13.830Z"
},
"metrics": {
"totalTransactions": 1523,
"byType": {
"points": 1024,
"xp": 312,
"coins": 187
},
"totalAmount": {
"points": 102400,
"xp": 31200,
"coins": 18700
},
"averagePerTransaction": {
"points": 100,
"xp": 100,
"coins": 100
},
"uniqueUsers": 456
},
"topCampaigns": [
{
"campaignId": "campaign-001",
"transactions": 823
},
{
"campaignId": "campaign-002",
"transactions": 456
},
{
"campaignId": "campaign-003",
"transactions": 244
}
],
"recentActivity": [
{
"transactionId": "txn_59e6dd71-4ac6-4284-8df7-787d575e60b3",
"userId": "user123",
"type": "points",
"amount": 100,
"createdAt": "2025-10-05T17:33:33.907Z"
}
],
"generatedAt": "2025-10-05T17:46:14.092Z"
}
}Response Fields
Period
The time range for the analytics data:
start- Beginning of the analytics period (ISO 8601)end- End of the analytics period (ISO 8601)
Metrics
Aggregated metrics across all transactions:
totalTransactions
Total number of transactions in the period
byType
Breakdown of transaction counts by type (points, xp, coins)
totalAmount
Sum of all amounts by type
averagePerTransaction
Average transaction amount by type
uniqueUsers
Number of unique users with transactions
Top Campaigns
List of campaigns with the most transaction activity (limited to top 5):
campaignId- Campaign identifiertransactions- Number of transactions for this campaign
Recent Activity
The 10 most recent transactions, including:
transactionId- Transaction identifieruserId- User identifiertype- Transaction typeamount- Transaction amountcreatedAt- Transaction timestamp
Use Cases
Performance Dashboard
Display key metrics on your admin dashboard:
async function loadAnalytics() {
const response = await fetch('/v1/analytics?startDate=2025-09-01');
const { data } = await response.json();
// Display total transactions
document.getElementById('total-txns').textContent =
data.metrics.totalTransactions.toLocaleString();
// Display unique users
document.getElementById('unique-users').textContent =
data.metrics.uniqueUsers.toLocaleString();
// Display points awarded
document.getElementById('points-awarded').textContent =
data.metrics.totalAmount.points.toLocaleString();
}Campaign Performance
Identify your best-performing campaigns:
import requests
response = requests.get(
'https://api.monterosa.cloud/loyalty/v1/analytics',
headers={
'Authorization': f'Bearer {token}',
'X-Monterosa-Org-ID': org_id
}
)
analytics = response.json()['data']
print("Top Campaigns:")
for campaign in analytics['topCampaigns']:
print(f" {campaign['campaignId']}: {campaign['transactions']} transactions")User Engagement Tracking
Monitor user engagement over time:
# Get last 7 days
START_DATE=$(date -u -d '7 days ago' +%Y-%m-%d)
END_DATE=$(date -u +%Y-%m-%d)
curl -s "https://api.monterosa.cloud/loyalty/v1/analytics?startDate=$START_DATE&endDate=$END_DATE" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Monterosa-Org-ID: $ORG_ID" | \
jq '.data.metrics.uniqueUsers'Transaction Type Analysis
Understand which reward types are most popular:
const response = await fetch('/v1/analytics');
const { data } = await response.json();
const typeData = data.metrics.byType;
const total = typeData.points + typeData.xp + typeData.coins;
console.log('Transaction Distribution:');
console.log(` Points: ${(typeData.points / total * 100).toFixed(1)}%`);
console.log(` XP: ${(typeData.xp / total * 100).toFixed(1)}%`);
console.log(` Coins: ${(typeData.coins / total * 100).toFixed(1)}%`);Performance Considerations
Analytics are calculated in real-time from transaction data
Large date ranges may take longer to process
Results are limited to 1000 transactions for performance
Consider caching analytics data for frequently accessed date ranges
Error Responses
400 Bad Request:
{
"success": false,
"error": {
"message": "Invalid date format"
}
}500 Internal Server Error:
{
"success": false,
"error": {
"message": "Failed to get analytics"
}
}Best Practices
Date Ranges: Use reasonable date ranges (1-90 days) for optimal performance
Caching: Cache analytics data for 15-30 minutes to reduce API calls
Pagination: For detailed analysis, use the Transactions API with pagination
Trending: Track metrics over time to identify trends
Alerts: Set up alerts for unusual metric changes
Reporting: Export analytics data regularly for long-term analysis
Recent Activity Endpoint
Get a detailed, multi-source activity feed for your organisation's loyalty program. Perfect for powering admin dashboards, activity timelines, and audit logs.
Get Recent Activity
Retrieve recent activities across all loyalty program components.
Endpoint: GET /v1/activity/recent
Query Parameters:
limit
number
No
Number of activities to return (default: 50, max: 100)
type
string
No
Filter by activity type (see types below)
userId
string
No
Filter activities for a specific user
cursor
string
No
Pagination cursor for fetching older activities
Activity Types:
transaction_created- Points, XP, or coins awarded/deductedcampaign_created- New campaign createdcampaign_activated- Campaign went livesegment_created- New user segment createdproduct_created- New reward product addeduser_tier_upgraded- User moved to a higher tierwebhook_triggered- Webhook delivery sentcode_redeemed- Individual code redeemed by user
Example Request:
curl -X GET "https://api.monterosa.cloud/loyalty/v1/activity/recent?limit=20&type=transaction_created" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: YOUR_ORG_UUID"Example Response:
{
"success": true,
"data": {
"activities": [
{
"activityId": "txn_abc123",
"type": "transaction_created",
"timestamp": "2025-10-06T10:30:00Z",
"data": {
"userId": "user_123",
"transactionType": "award",
"amount": 100,
"reason": "Poll vote",
"campaignId": "campaign_xyz",
"metadata": {}
},
"user": {
"userId": "user_123",
"name": "John Smith",
"email": "[email protected]",
"tier": "gold"
}
},
{
"activityId": "seg_def456",
"type": "segment_created",
"timestamp": "2025-10-06T10:25:00Z",
"data": {
"segmentId": "seg_def456",
"name": "VIP Gold Members",
"type": "dynamic",
"estimatedSize": 1250
},
"user": null
},
{
"activityId": "txn_ghi789",
"type": "user_tier_upgraded",
"timestamp": "2025-10-06T10:20:00Z",
"data": {
"userId": "user_456",
"fromTier": "silver",
"toTier": "gold"
},
"user": {
"userId": "user_456",
"name": "Jane Doe",
"email": "[email protected]",
"tier": "gold"
}
},
{
"activityId": "code_jkl012",
"type": "code_redeemed",
"timestamp": "2025-10-06T10:15:00Z",
"data": {
"code": "WELCOME2025",
"userId": "user_789",
"rewardType": "points",
"rewardValue": 500,
"campaignId": "campaign_abc"
},
"user": {
"userId": "user_789",
"name": "Bob Wilson",
"email": "[email protected]",
"tier": "silver"
}
},
{
"activityId": "webhook_mno345",
"type": "webhook_triggered",
"timestamp": "2025-10-06T10:10:00Z",
"data": {
"eventType": "user.tier_changed",
"url": "https://example.com/webhooks/loyalty",
"status": "success",
"attempts": 1
},
"user": null
}
],
"count": 5,
"nextCursor": "MjAyNS0xMC0wNlQxMDoxMDowMFo=",
"filters": {
"type": "all",
"userId": null,
"limit": 20
}
}
}Activity Object Structure
Each activity contains:
activityId
string
Unique identifier for this activity
type
string
Activity type (see types above)
timestamp
string
ISO 8601 timestamp when activity occurred
data
object
Activity-specific data (varies by type)
user
object|null
Enriched user details if activity has userId
User Enrichment
Activities that involve a user automatically include enriched user data:
{
"user": {
"userId": "user_123",
"name": "John Smith",
"email": "[email protected]",
"tier": "gold"
}
}User details are batch-fetched for performance (up to 100 users per request).
Pagination
Use the nextCursor to fetch older activities:
# First request
curl "https://api.monterosa.cloud/loyalty/v1/activity/recent?limit=50"
# Use nextCursor from response for next page
curl "https://api.monterosa.cloud/loyalty/v1/activity/recent?limit=50&cursor=MjAyNS0xMC0wNlQxMDoxMDowMFo="The cursor is base64-encoded and represents the timestamp of the last activity in the current page.
Filtering Examples
Get only transactions:
curl "https://api.monterosa.cloud/loyalty/v1/activity/recent?type=transaction_created&limit=50"Get activity for specific user:
curl "https://api.monterosa.cloud/loyalty/v1/activity/recent?userId=user_123"Get tier upgrades only:
curl "https://api.monterosa.cloud/loyalty/v1/activity/recent?type=user_tier_upgraded"Use Cases
1. Admin Activity Dashboard
Display real-time activity across your loyalty program:
async function loadRecentActivity() {
const response = await fetch('/v1/activity/recent?limit=20');
const { data } = await response.json();
const timeline = document.getElementById('activity-timeline');
data.activities.forEach(activity => {
const item = document.createElement('div');
item.className = `activity-item ${activity.type}`;
// Format based on activity type
if (activity.type === 'transaction_created') {
item.innerHTML = `
<strong>${activity.user.name}</strong>
earned ${activity.data.amount} ${activity.data.transactionType}
<time>${formatTime(activity.timestamp)}</time>
`;
} else if (activity.type === 'user_tier_upgraded') {
item.innerHTML = `
<strong>${activity.user.name}</strong>
upgraded from ${activity.data.fromTier} to ${activity.data.toTier}
<time>${formatTime(activity.timestamp)}</time>
`;
}
timeline.appendChild(item);
});
}2. User Activity History
Show a user's complete activity history:
async function loadUserActivity(userId) {
let allActivities = [];
let cursor = null;
do {
const url = `/v1/activity/recent?userId=${userId}&limit=100` +
(cursor ? `&cursor=${cursor}` : '');
const response = await fetch(url);
const { data } = await response.json();
allActivities.push(...data.activities);
cursor = data.nextCursor;
} while (cursor);
return allActivities;
}3. Real-time Activity Feed
Create a live-updating activity feed:
class ActivityFeed {
constructor() {
this.latestTimestamp = null;
}
async loadInitial() {
const response = await fetch('/v1/activity/recent?limit=20');
const { data } = await response.json();
this.latestTimestamp = data.activities[0]?.timestamp;
this.render(data.activities);
}
async poll() {
const response = await fetch('/v1/activity/recent?limit=20');
const { data } = await response.json();
// Filter to only new activities
const newActivities = data.activities.filter(
a => a.timestamp > this.latestTimestamp
);
if (newActivities.length > 0) {
this.latestTimestamp = newActivities[0].timestamp;
this.prependActivities(newActivities);
}
}
startPolling(interval = 10000) {
setInterval(() => this.poll(), interval);
}
}4. Activity Type Statistics
Analyze activity patterns:
import requests
from collections import Counter
def analyze_activity_types(org_id, token):
response = requests.get(
'https://api.monterosa.cloud/loyalty/v1/activity/recent?limit=100',
headers={
'Authorization': f'Bearer {token}',
'X-Monterosa-Org-ID': org_id
}
)
activities = response.json()['data']['activities']
type_counts = Counter(a['type'] for a in activities)
print("Activity Type Distribution:")
for activity_type, count in type_counts.most_common():
print(f" {activity_type}: {count}")Performance Considerations
Multi-Source Aggregation: Queries 7 different tables (transactions, campaigns, products, segments, webhooks, codes, users)
Batch User Lookup: User details fetched in batches of 100 for efficiency
Limit Optimization: Keep limit ≤ 50 for fastest response times
Caching: Consider caching results for 30-60 seconds for high-traffic dashboards
Filtering: Use
typeanduserIdfilters to reduce query scope
Error Responses
400 Bad Request:
{
"success": false,
"error": {
"message": "Invalid cursor format"
}
}500 Internal Server Error:
{
"success": false,
"error": {
"message": "Failed to fetch recent activity"
}
}Best Practices
Polling Interval: Poll every 10-30 seconds for real-time feeds
Pagination: Use cursor-based pagination for loading historical data
Type Filtering: Filter by type when you only need specific activities
User Context: Use
userIdfilter for user-specific activity pagesDisplay Formatting: Format timestamps and activity descriptions for readability
Error Handling: Handle missing user data gracefully (user may be deleted)
Last updated

