Third-Party Integration
How to set up third party triggers and actions
This guide explains how external systems (eCommerce platforms, ticketing systems, payment processors, etc.) can send events to trigger loyalty rewards.
Overview
Third-party systems can integrate with the Loyalty API to trigger rewards for user actions that occur outside the main platform, such as:
Purchases from eCommerce systems
Ticket scans at venues or events
App interactions from mobile applications
Payment confirmations from payment processors
Content consumption from streaming platforms
Physical store visits tracked by POS systems
Authentication
All third-party API calls require authentication using API Keys.
Obtaining API Credentials
Contact Monterosa support to receive:
API Key: Unique identifier for your integration
API Secret: Secret key for authentication
Organisation ID: Your organization's UUID
Making Authenticated Requests
Include these headers in all API requests:
POST /api/audience/internal/actions
Authorization: Bearer YOUR_API_SECRET
X-Monterosa-Org-ID: YOUR_ORG_UUID
Content-Type: application/jsonEvent Ingestion Endpoint
POST /api/audience/internal/actions
Send user actions from your system to trigger loyalty campaigns.
Request Body
{
"userId": "user_123",
"action": "purchase_completed",
"timestamp": "2025-10-06T16:45:00Z",
"data": {
"orderId": "ORD-12345",
"amount": 99.99,
"currency": "USD",
"items": [
{
"sku": "PRODUCT-001",
"quantity": 2,
"price": 49.99
}
]
},
"metadata": {
"source": "shopify",
"storeId": "store_456"
}
}Parameters
userId
string
✅
User's loyalty platform ID
action
string
✅
Event type identifier (see below)
timestamp
string
No
ISO8601 timestamp (defaults to current time)
data
object
No
Event-specific data
metadata
object
No
Additional context information
Response
{
"eventId": "evt_7f9e2c8a-1234-5678-90ab-cdef12345678",
"processed": false,
"message": "Action queued for processing"
}The event is queued for asynchronous processing. Campaign triggers matching this action will fire automatically.
Event Types (Actions)
Define custom action types for your use case. Recommended naming convention: {category}_{verb}
Common Event Types
eCommerce:
purchase_completed- Order completedcart_abandoned- User left items in cartproduct_reviewed- User left a product reviewreferral_used- Referral code was applied
Ticketing:
ticket_purchased- Ticket boughtticket_scanned- Ticket validated at venueevent_attended- User checked in to eventvip_upgrade- User upgraded to VIP
Content:
video_watched- Video completedarticle_read- Article finishedmilestone_reached- Achievement unlockedstreak_maintained- Daily streak continued
Physical:
store_visit- Customer entered storepos_purchase- In-store purchase madeloyalty_card_scan- Card scanned at register
Mapping Users
User ID Matching
The userId field must match the user's ID in the loyalty platform. Options:
Direct ID: Use the loyalty platform's user ID directly
External ID Mapping: Map your system's user ID to loyalty platform ID
Email/Phone Lookup: Use email or phone number (requires user schema configuration)
Identity Mapping Example
If your system uses email addresses but the loyalty platform uses UUIDs:
# First, look up the user
GET /api/audience/[email protected]
# Response: { "userId": "550e8400-e29b-41d4-a716-446655440000", ... }
# Then, send the event
POST /api/audience/internal/actions
{
"userId": "550e8400-e29b-41d4-a716-446655440000",
"action": "purchase_completed",
...
}Configuring Campaign Triggers
Once events are flowing, configure campaigns to respond to them.
Step 1: Create Custom Trigger
Define your custom event type in the campaign system:
{
"key": "purchase_completed",
"name": "Purchase Completed",
"category": "commerce",
"fields": [
{
"key": "amount",
"type": "number",
"description": "Purchase amount"
},
{
"key": "currency",
"type": "string"
}
]
}Step 2: Create Campaign with Trigger
{
"name": "Reward Purchases Over $100",
"triggers": [
{
"type": "purchase_completed",
"conditions": [
{
"field": "amount",
"operator": ">=",
"value": 100
}
]
}
],
"effects": [
{
"type": "add_points",
"config": {
"amount": 500,
"reason": "Purchase reward"
}
},
{
"type": "award_product",
"config": {
"productId": "prod_vip_badge",
"reason": "VIP shopper badge"
}
}
]
}Now when your system sends a purchase_completed event with amount >= 100, the user receives 500 points and a VIP badge.
Integration Examples
E-Commerce (Shopify Webhook)
// Shopify webhook handler
app.post('/webhooks/shopify/order-created', async (req, res) => {
const order = req.body;
// Send to Loyalty API
await fetch('https://api.monterosa.cloud/loyalty/api/audience/internal/actions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LOYALTY_API_SECRET}`,
'X-Monterosa-Org-ID': process.env.LOYALTY_ORG_ID,
'Content-Type': 'application/json'
},
body: JSON.stringify({
userId: order.customer.id,
action: 'purchase_completed',
timestamp: order.created_at,
data: {
orderId: order.id,
amount: parseFloat(order.total_price),
currency: order.currency,
items: order.line_items.map(item => ({
sku: item.sku,
quantity: item.quantity,
price: parseFloat(item.price)
}))
},
metadata: {
source: 'shopify',
orderNumber: order.name
}
})
});
res.status(200).send('OK');
});Ticketing System (Stadium Entry)
# Ticket scanner at stadium gate
import requests
from datetime import datetime
def scan_ticket(ticket_code, scanner_id):
# Validate ticket in your system
ticket = validate_ticket(ticket_code)
if ticket['valid']:
# Send event to Loyalty API
response = requests.post(
'https://api.monterosa.cloud/loyalty/api/audience/internal/actions',
headers={
'Authorization': f'Bearer {LOYALTY_API_SECRET}',
'X-Monterosa-Org-ID': LOYALTY_ORG_ID,
'Content-Type': 'application/json'
},
json={
'userId': ticket['user_id'],
'action': 'ticket_scanned',
'timestamp': datetime.utcnow().isoformat() + 'Z',
'data': {
'ticketId': ticket['id'],
'sectionSeat': ticket['section'],
'eventId': ticket['event_id'],
'scanner': scanner_id
},
'metadata': {
'source': 'gate_scanner',
'gate': scanner_id
}
}
)
return response.json()Mobile App (In-App Purchase)
// iOS App Purchase Handler
func handlePurchaseComplete(transaction: SKPaymentTransaction) {
let purchaseData: [String: Any] = [
"userId": UserDefaults.standard.string(forKey: "loyaltyUserId") ?? "",
"action": "iap_completed",
"data": [
"productId": transaction.payment.productIdentifier,
"transactionId": transaction.transactionIdentifier ?? "",
"quantity": transaction.payment.quantity
],
"metadata": [
"source": "ios_app",
"appVersion": Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
]
]
var request = URLRequest(url: URL(string: "https://api.monterosa.cloud/loyalty/api/audience/internal/actions")!)
request.httpMethod = "POST"
request.setValue("Bearer \(loyaltyAPISecret)", forHTTPHeaderField: "Authorization")
request.setValue(loyaltyOrgID, forHTTPHeaderField: "X-Monterosa-Org-ID")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: purchaseData)
URLSession.shared.dataTask(with: request) { data, response, error in
// Handle response
}.resume()
}Best Practices
Event Naming
Be consistent: Use a naming convention like
{domain}_{action}Be specific:
purchase_completedis better thanpurchaseAvoid duplicates: Use the same event name across all systems
Data Structure
Include context: Send relevant data that campaigns might filter on
Be flat: Avoid deeply nested structures when possible
Use standards: ISO8601 for dates, ISO currency codes, etc.
Error Handling
Implement retries: Network failures can happen
Log failures: Track which events didn't send
Use idempotency: Include unique identifiers to prevent duplicate processing
Performance
Queue events: Don't block user experience waiting for API calls
Batch when possible: If sending many events, batch them
Handle rate limits: Implement exponential backoff
Security
Rotate keys: Periodically rotate API secrets
Use HTTPS: Always use secure connections
Validate inputs: Sanitize user data before sending
Monitoring & Debugging
Check Event Processing
Events are queued and processed asynchronously. To verify processing:
Check campaign triggers: Ensure trigger conditions match your event data
Review transactions: Check if rewards were granted (
GET /v1/transactions)Monitor analytics: View campaign performance metrics
Common Issues
Events not triggering campaigns:
Verify
userIdexists in the loyalty platformCheck trigger conditions match event data fields
Confirm campaign is active and not expired
Authentication failures:
Verify API key and secret are correct
Check organization ID matches
Ensure API key has
actions:writepermission
Missing user IDs:
Implement user identity mapping
Sync user records between systems
Use email/phone lookup if configured
Rate Limits
Standard: 100 requests per second per organization
Burst: Up to 500 requests per second for short periods
Contact us for higher limits
Support
For integration support:
Documentation: https://docs.monterosa.co
API Status: https://status.monterosa.co
Support: [email protected]
Example: Complete Integration Flow
User makes purchase in your eCommerce system
Your system sends event to Loyalty API
POST /api/audience/internal/actions
{
"userId": "user_123",
"action": "purchase_completed",
"data": { "amount": 150, "currency": "USD" }
}Campaign system evaluates triggers
Checks active campaigns
Matches
purchase_completedtriggerValidates conditions (amount >= 100)
Campaign effects execute
Awards 500 points
Awards VIP badge product
Allocates unique discount code from pool
User receives rewards
Transaction created
Balance updated
Product allocated
Code assigned
User can view rewards
GET /api/audience/transactions
# Returns list of transactions including the rewardLast updated

