Campaigns
Create and manage loyalty campaigns including multi-step challenges, rewards, badges, streaks, and competitions with segment targeting
Campaigns are the core mechanism for engaging users through loyalty mechanics. They define how users earn rewards, complete challenges, unlock badges, maintain streaks, and participate in competitions.
Overview
Campaign Types:
Challenge: Multi-step objectives users complete for rewards
Reward: Instant rewards for specific actions
Badge: Achievements unlocked by completing criteria
Streak: Consecutive action tracking with rewards
Competition: Time-bound contests with leaderboards
Campaign Modes:
always-on: Continuous campaigns with no end date
time-bound: Campaigns that run between specific dates
Key Features:
Multi-step challenge configuration
Segment targeting with include/exclude criteria
Simple mode (triggers + effects) and Advanced mode (complex rules)
Priority-based execution
Draft, active, paused, completed, and archived statuses
Endpoints
List Campaigns
GET /v1/campaignsRetrieve a paginated list of campaigns for your organization.
Query Parameters:
status
string
No
Filter by status: draft, active, paused, completed, archived
type
string
No
Filter by type: Challenge, Reward, Badge, Streak, Competition
mode
string
No
Filter by mode: always-on, time-bound, recurring
limit
number
No
Number of results (default: 50, max: 100)
cursor
string
No
Pagination cursor from previous response
Example Request:
curl -X GET "https://api.monterosa.cloud/loyalty/v1/campaigns?status=active&limit=10" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id"Example Response:
{
"success": true,
"data": {
"campaigns": [
{
"campaignId": "camp_123e4567-e89b-12d3-a456-426614174000",
"orgId": "00000000-0000-0000-0000-000000000001",
"name": "Daily Check-in Reward",
"description": "Earn 10 points for checking in daily",
"type": "Reward",
"mode": "always-on",
"status": "active",
"simplifiedMode": true,
"triggers": [{
"eventType": "user.checkin",
"conditions": {}
}],
"effects": [{
"type": "add_points",
"config": { "amount": 10 }
}],
"createdAt": "2025-10-01T10:00:00.000Z",
"updatedAt": "2025-10-01T10:00:00.000Z"
}
],
"cursor": "eyJsYXN0S2V5IjoiY2FtcF8xMjM0In0="
},
"timestamp": "2025-10-05T12:00:00.000Z"
}Create Campaign
POST /v1/campaignsCreate a new loyalty campaign.
Request Body:
name
string
Yes
Campaign name
description
string
No
Campaign description
type
string
Yes
Campaign type: Challenge, Reward, Badge, Streak, Competition
mode
string
Yes
Campaign mode: always-on, time-bound, recurring
startDate
string
Conditional
ISO 8601 date (required for time-bound mode)
endDate
string
No
ISO 8601 date (optional for time-bound mode)
triggers
array
Conditional
Array of trigger objects (required for simple mode)
effects
array
Conditional
Array of effect objects (required for simple mode)
conditions
object
No
Condition logic object
priority
number
No
Campaign priority (1-10, default: 5)
segmentIds
array
No
Array of segment IDs to target
metadata
object
No
Custom metadata
Simple Mode Example:
curl -X POST https://api.monterosa.cloud/loyalty/v1/campaigns \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id" \
-H "Content-Type: application/json" \
-d '{
"name": "Vote Reward",
"description": "Earn 5 points for each vote",
"type": "Reward",
"mode": "always-on",
"triggers": [{
"eventType": "user.vote",
"conditions": {}
}],
"effects": [{
"type": "add_points",
"config": { "amount": 5 }
}]
}'Advanced Mode Example:
Advanced mode campaigns don't include triggers or effects in the campaign creation. Instead, you create the campaign first (just the container), then create separate rules via the Rules API.
# Step 1: Create the campaign container
CAMPAIGN_ID=$(curl -X POST https://api.monterosa.cloud/loyalty/v1/campaigns \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id" \
-H "Content-Type: application/json" \
-d '{
"name": "Advanced Engagement Campaign",
"description": "Complex multi-rule campaign",
"type": "Challenge",
"mode": "time-bound",
"startDate": "2025-10-01T00:00:00.000Z",
"endDate": "2025-10-31T23:59:59.000Z",
"status": "draft"
}' | jq -r '.data.campaignId')
# Step 2: Create Rule 1 - Poll votes worth 10 points
curl -X POST https://api.monterosa.cloud/loyalty/v1/rules \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id" \
-H "Content-Type: application/json" \
-d '{
"campaignId": "'"$CAMPAIGN_ID"'",
"name": "Poll Vote Rule",
"trigger": "poll_vote",
"priority": 100,
"conditions": [],
"effects": [
{
"type": "award_points",
"amount": 10
}
]
}'
# Step 3: Create Rule 2 - Quiz completions with score requirement
curl -X POST https://api.monterosa.cloud/loyalty/v1/rules \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id" \
-H "Content-Type: application/json" \
-d '{
"campaignId": "'"$CAMPAIGN_ID"'",
"name": "Quiz Master Rule",
"trigger": "quiz_completed",
"priority": 90,
"conditions": [
{
"field": "score",
"operator": ">=",
"value": 80
}
],
"effects": [
{
"type": "award_points",
"amount": 50
},
{
"type": "award_badge",
"badgeId": "quiz_master"
}
]
}'Why Use Advanced Mode?
Multiple triggers in one campaign
Complex conditional logic per rule
Different priority levels for rules
Need to add/modify rules independently after campaign creation
See the Rules API for more details on creating rules.
Response:
{
"success": true,
"data": {
"campaignId": "camp_123e4567-e89b-12d3-a456-426614174000",
"orgId": "00000000-0000-0000-0000-000000000001",
"name": "Vote Reward",
"description": "Earn 5 points for each vote",
"type": "Reward",
"mode": "always-on",
"status": "draft",
"simplifiedMode": true,
"triggers": [{
"eventType": "user.vote",
"conditions": {}
}],
"effects": [{
"type": "add_points",
"config": { "amount": 5 }
}],
"priority": 5,
"createdAt": "2025-10-05T12:00:00.000Z",
"updatedAt": "2025-10-05T12:00:00.000Z"
},
"timestamp": "2025-10-05T12:00:00.000Z"
}Get Campaign
GET /v1/campaigns/{campaignId}Retrieve a specific campaign by ID.
Path Parameters:
campaignId
string
Yes
Campaign ID
Example Request:
curl -X GET https://api.monterosa.cloud/loyalty/v1/campaigns/camp_123e4567-e89b-12d3-a456-426614174000 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id"Response: Same structure as Create Campaign response.
Update Campaign
PUT /v1/campaigns/{campaignId}Update an existing campaign. Only provided fields will be updated.
Path Parameters:
campaignId
string
Yes
Campaign ID
Request Body: Any fields from the Create Campaign request (except type which cannot be changed).
Example Request:
curl -X PUT https://api.monterosa.cloud/loyalty/v1/campaigns/camp_123e4567-e89b-12d3-a456-426614174000 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id" \
-H "Content-Type: application/json" \
-d '{
"status": "active",
"description": "Updated description"
}'Response: Updated campaign object.
Get Expanded Campaign
GET /v1/campaigns/{campaignId}/expandedRetrieve a campaign with all related entities expanded (rules, segments, rewards, etc.). This provides a complete view of the campaign configuration.
Path Parameters:
campaignId
string
Yes
Campaign ID
Example Request:
curl -X GET https://api.monterosa.cloud/loyalty/v1/campaigns/camp_123e4567-e89b-12d3-a456-426614174000/expanded \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id"Example Response:
{
"success": true,
"data": {
"campaignId": "camp_123e4567-e89b-12d3-a456-426614174000",
"name": "Daily Check-in Reward",
"type": "Reward",
"status": "active",
"mode": "always-on",
"rules": [
{
"ruleId": "rule_abc123",
"name": "Check-in Rule",
"trigger": "user.checkin",
"priority": 10,
"conditions": [],
"effects": [
{
"type": "award_points",
"amount": 10
}
]
}
],
"segments": [
{
"segmentId": "seg_xyz789",
"name": "Active Users",
"type": "dynamic",
"criteria": [
{
"field": "tier",
"operator": "in",
"value": ["silver", "gold", "platinum"]
}
]
}
],
"rewards": [
{
"rewardId": "rew_def456",
"name": "Check-in Points",
"rewardType": "points",
"config": {
"amount": 10
}
}
],
"createdAt": "2025-10-01T10:00:00.000Z",
"updatedAt": "2025-10-05T14:30:00.000Z"
}
}Get Campaign Progress
GET /v1/campaigns/{campaignId}/progressRetrieve user progress for a campaign. For multi-step challenges, this shows completed steps and overall completion status. Can optionally filter by userId.
Path Parameters:
campaignId
string
Yes
Campaign ID
Query Parameters:
userId
string
No
Filter progress for a specific user
limit
number
No
Number of results (default: 50)
cursor
string
No
Pagination cursor
Example Request (Specific User):
curl -X GET "https://api.monterosa.cloud/loyalty/v1/campaigns/camp_123e4567-e89b-12d3-a456-426614174000/progress?userId=user_123" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id"Example Response (Challenge Progress):
{
"success": true,
"data": {
"userId": "user_123",
"campaignId": "camp_123e4567-e89b-12d3-a456-426614174000",
"progress": {
"completedSteps": [
{
"stepId": "step_1",
"name": "Watch First Video",
"completedAt": "2025-10-05T10:00:00.000Z"
},
{
"stepId": "step_2",
"name": "Complete Profile",
"completedAt": "2025-10-06T14:30:00.000Z"
}
],
"totalSteps": 5,
"requiredSteps": 3,
"completedCount": 2,
"isCompleted": false,
"completionPercentage": 66.67,
"startedAt": "2025-10-05T10:00:00.000Z",
"expiresAt": "2025-10-12T10:00:00.000Z"
}
}
}Example Request (All Users):
curl -X GET "https://api.monterosa.cloud/loyalty/v1/campaigns/camp_123e4567-e89b-12d3-a456-426614174000/progress?limit=100" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id"Example Response (Multiple Users):
{
"success": true,
"data": {
"campaignId": "camp_123e4567-e89b-12d3-a456-426614174000",
"progress": [
{
"userId": "user_123",
"completedCount": 2,
"totalSteps": 5,
"isCompleted": false,
"completionPercentage": 40.0
},
{
"userId": "user_456",
"completedCount": 5,
"totalSteps": 5,
"isCompleted": true,
"completionPercentage": 100.0,
"completedAt": "2025-10-07T16:20:00.000Z"
}
],
"count": 2,
"cursor": null
}
}Delete Campaign
DELETE /v1/campaigns/{campaignId}Archive a campaign (soft delete). The campaign will be marked as archived but not permanently deleted.
Path Parameters:
campaignId
string
Yes
Campaign ID
Example Request:
curl -X DELETE https://api.monterosa.cloud/loyalty/v1/campaigns/camp_123e4567-e89b-12d3-a456-426614174000 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id"Response:
HTTP/1.1 204 No ContentClone Campaign
POST /v1/campaigns/{campaignId}/cloneClone an existing campaign with optional modifications. Perfect for creating variations of successful campaigns or A/B testing.
Path Parameters:
campaignId
string
Yes
Source campaign ID to clone
Request Body (all optional):
{
"name": "Black Friday Campaign (Copy)",
"description": "Cloned from summer campaign",
"status": "draft",
"type": "Reward",
"mode": "time-bound",
"startDate": "2025-11-24T00:00:00Z",
"endDate": "2025-11-25T23:59:59Z",
"segmentId": "seg_new_segment",
"rules": [],
"metadata": {
"variant": "B",
"testGroup": "holiday_2025"
}
}Field Overrides:
name
New campaign name (default: "{original} (Copy)")
description
New description
status
Initial status (default: "draft" for safety)
type
Campaign type override
mode
Campaign mode override
startDate
New start date (time-bound campaigns)
endDate
New end date (time-bound campaigns)
segmentId
Different target segment
rules
Override rules entirely (otherwise clones with new IDs)
metadata
Additional metadata (merged with original)
Example Request:
curl -X POST https://api.monterosa.cloud/loyalty/v1/campaigns/camp_abc123/clone \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Monterosa-Org-ID: your-org-id" \
-H "Content-Type: application/json" \
-d '{
"name": "Weekend Bonus Campaign (Test)",
"status": "draft",
"startDate": "2025-11-01T00:00:00Z",
"endDate": "2025-11-03T23:59:59Z",
"metadata": {
"variant": "weekend_test",
"rewardMultiplier": 1.5
}
}'Response (201 Created):
{
"success": true,
"data": {
"campaignId": "camp_new_789xyz",
"orgId": "org_123",
"name": "Weekend Bonus Campaign (Test)",
"description": "Original campaign description",
"type": "Reward",
"status": "draft",
"mode": "time-bound",
"startDate": "2025-11-01T00:00:00Z",
"endDate": "2025-11-03T23:59:59Z",
"rules": [
{
"id": "rule_generated_new_id",
"name": "Poll Vote Reward",
"trigger": "poll_vote",
"priority": 10,
"conditions": [],
"effects": [
{
"type": "award_points",
"amount": 50,
"reason": "Poll participation"
}
]
}
],
"metadata": {
"variant": "weekend_test",
"rewardMultiplier": 1.5,
"clonedFrom": "camp_abc123",
"clonedAt": "2025-10-07T10:30:00Z",
"clonedBy": "[email protected]"
},
"createdAt": "2025-10-07T10:30:00Z",
"updatedAt": "2025-10-07T10:30:00Z",
"createdBy": "[email protected]",
"sourceId": "camp_abc123"
}
}Use Cases:
A/B Testing: Clone campaign with different reward amounts
{ "name": "Poll Campaign (Variant B)", "metadata": { "variant": "B", "rewardAmount": 100 } }Seasonal Campaigns: Clone successful campaign for new season
{ "name": "Summer Campaign 2026", "startDate": "2026-06-01T00:00:00Z", "endDate": "2026-08-31T23:59:59Z" }Segment Testing: Test same campaign on different segments
{ "name": "VIP User Campaign", "segmentId": "seg_vip_users" }Quick Duplication: Rapid campaign creation
# Clone with just a new name, keep everything else curl -X POST .../campaigns/camp_abc123/clone \ -d '{"name": "Campaign Copy"}'
Notes:
Cloned campaigns default to
draftstatus to prevent accidental activationRule IDs are automatically regenerated to avoid conflicts
Source campaign metadata includes
clonedFrom,clonedAt, andclonedByAll timestamps (
createdAt,updatedAt) are resetOriginal campaign remains unchanged
Campaign Lifecycle
Draft: Campaign is created but not active
Active: Campaign is running and processing events
Paused: Campaign is temporarily stopped
Completed: Campaign has reached its end date
Archived: Campaign is soft-deleted
Multi-Step Challenges
Multi-step challenges allow users to complete a series of tasks in any order or sequential order. Perfect for onboarding flows, engagement campaigns, and complex objectives.
Challenge Configuration
Add challengeConfig to create a multi-step challenge:
{
"name": "Welcome Challenge",
"description": "Complete 3 out of 5 onboarding tasks",
"type": "Challenge",
"mode": "always-on",
"challengeConfig": {
"completionLogic": "any",
"requiredSteps": 3,
"timeLimit": { "duration": 7, "unit": "days" },
"steps": [
{
"name": "Watch First Video",
"description": "Watch any video to completion",
"order": 1,
"trigger": {
"triggerType": "user.video_watched",
"conditions": { "watchPercentage": { "min": 90 } }
},
"effects": [{ "type": "add_points", "config": { "amount": 10 } }]
},
{
"name": "Complete Profile",
"trigger": { "triggerType": "user.profile_completed", "conditions": {} },
"effects": [{ "type": "add_points", "config": { "amount": 20 } }]
}
],
"completionRewards": [
{ "type": "add_badge", "config": { "badgeId": "badge_onboarding_complete" } },
{ "type": "add_points", "config": { "amount": 100 } }
]
}
}Completion Logic:
"all": User must complete ALL steps"any": User must complete N steps (specified byrequiredSteps)
Challenge Tracking (GET /v1/campaigns/{campaignId}/progress/{userId}):
{
"userId": "user123",
"campaignId": "camp_welcome",
"progress": {
"completedSteps": [
{ "stepId": "step_1", "name": "Watch First Video", "completedAt": "2025-10-05T10:00:00Z" }
],
"totalSteps": 5,
"requiredSteps": 3,
"completedCount": 1,
"isCompleted": false,
"completionPercentage": 33.33,
"expiresAt": "2025-10-12T10:00:00Z"
}
}Segment Targeting
Campaigns can target specific user segments using include and exclude criteria. This enables precise audience targeting for rewards, benefits, and quizzes.
Basic Targeting
Single Segment:
{
"name": "VIP Exclusive Reward",
"type": "Reward",
"segmentIds": ["seg_vip_gold_members"],
"triggers": [{ "eventType": "user.video_watched", "conditions": {} }],
"effects": [{ "type": "add_points", "config": { "amount": 50 } }]
}Multiple Segments (OR logic):
{
"name": "Premium Members Reward",
"segmentIds": ["seg_gold_tier", "seg_platinum_tier"],
"triggers": [...]
}Advanced Targeting with Exclusions
Campaigns respect segment include/exclude criteria. First create a segment with exclusions:
curl -X POST https://api.monterosa.cloud/loyalty/v1/segments \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "VIP Non-Test Users",
"type": "dynamic",
"criteria": [
{ "field": "tier", "operator": "in", "value": ["gold", "platinum"] }
],
"excludeCriteria": [
{ "field": "customFields.testAccount", "operator": "equals", "value": true },
{ "field": "badges", "operator": "contains", "value": ["banned"] }
]
}'Then reference it in your campaign:
{
"name": "VIP Bonus Campaign",
"segmentIds": ["seg_vip_non_test_users"],
"triggers": [{ "eventType": "user.video_watched", "conditions": {} }],
"effects": [{ "type": "add_points", "config": { "amount": 100 } }]
}Use Cases
1. Quiz Eligibility (First-Time Participants)
Only allow users who haven't completed the quiz before:
Segment (seg_quiz_first_timers):
{
"criteria": [
{ "field": "tier", "operator": "not_equals", "value": "bronze" }
],
"excludeCriteria": [
{ "field": "customFields.completedQuiz", "operator": "equals", "value": true },
{ "field": "badges", "operator": "contains", "value": ["quiz_master"] }
]
}Campaign:
{
"name": "Weekly Sports Quiz",
"type": "Challenge",
"mode": "time-bound",
"startDate": "2025-10-07T00:00:00Z",
"endDate": "2025-10-07T23:59:59Z",
"segmentIds": ["seg_quiz_first_timers"],
"challengeConfig": {
"completionLogic": "all",
"steps": [
{ "name": "Question 1", "trigger": { "triggerType": "user.quiz_answered", "conditions": { "questionId": "q1" } } },
{ "name": "Question 2", "trigger": { "triggerType": "user.quiz_answered", "conditions": { "questionId": "q2" } } }
],
"completionRewards": [
{ "type": "add_points", "config": { "amount": 50 } },
{ "type": "add_badge", "config": { "badgeId": "quiz_participant" } }
]
}
}2. Premium Benefits (Paid Members Only)
Segment (seg_premium_members):
{
"criteria": [
{ "field": "tier", "operator": "in", "value": ["gold", "platinum"] },
{ "field": "customFields.subscriptionActive", "operator": "equals", "value": true }
],
"excludeCriteria": [
{ "field": "customFields.freeTrialUser", "operator": "equals", "value": true }
]
}Campaign:
{
"name": "Premium Early Access",
"type": "Reward",
"segmentIds": ["seg_premium_members"],
"triggers": [{ "eventType": "user.video_watched", "conditions": { "videoType": "premium_content" } }],
"effects": [
{ "type": "add_points", "config": { "amount": 25 } },
{ "type": "unlock_benefit", "config": { "benefitId": "early_access_2025" } }
]
}3. Re-engagement Campaign (Inactive Users)
Segment (seg_inactive_users):
{
"criteria": [
{ "field": "tier", "operator": "in", "value": ["silver", "gold"] },
{ "field": "updatedAt", "operator": "<", "value": "2025-09-01T00:00:00Z" }
],
"excludeCriteria": [
{ "field": "badges", "operator": "contains", "value": ["recently_active"] }
]
}Campaign:
{
"name": "Welcome Back Bonus",
"segmentIds": ["seg_inactive_users"],
"triggers": [{ "eventType": "user.app_opened", "conditions": {} }],
"effects": [
{ "type": "add_points", "config": { "amount": 100, "reason": "Welcome back!" } },
{ "type": "add_coins", "config": { "amount": 50 } }
]
}4. Daily Check-in Streak
{
"name": "Daily Login Streak",
"type": "Streak",
"triggers": [{ "eventType": "user.daily_checkin", "conditions": {} }],
"effects": [
{ "type": "add_points", "config": { "amount": 10 } },
{ "type": "increment_streak", "config": { "streakType": "daily_login" } }
],
"metadata": {
"streakRewards": [
{ "day": 7, "points": 100, "badge": "week_warrior" },
{ "day": 30, "points": 500, "badge": "month_master" }
]
}
}5. Competition with Leaderboard
{
"name": "October Engagement Challenge",
"type": "Competition",
"mode": "time-bound",
"startDate": "2025-10-01T00:00:00Z",
"endDate": "2025-10-31T23:59:59Z",
"triggers": [
{ "eventType": "user.vote", "conditions": {} },
{ "eventType": "user.trivia_answered", "conditions": {} }
],
"effects": [{ "type": "add_competition_score", "config": { "scoreField": "october_engagement" } }],
"metadata": {
"leaderboardId": "october_2025",
"prizes": [
{ "rank": 1, "points": 1000, "badge": "first_place_october" },
{ "rank": 2, "points": 500, "badge": "second_place_october" }
]
}
}Validation Rules
Campaign names must be unique within an organization
time-boundcampaigns must have astartDateandendDateSimple mode campaigns must have at least one trigger and one effect
Advanced mode campaigns cannot have
triggersoreffectsat the campaign levelCampaign type cannot be changed after creation
Multi-step challenges can have 1-10 steps
completionLogic: "any"requiresrequiredStepsparameterTime limits support
daysorhoursunits
API Limits
Campaigns per organization
500
Steps per challenge
10
Segments per campaign
5
Effects per trigger
10
Error Codes
CAMPAIGN_NOT_FOUND
404
Campaign does not exist
INVALID_CAMPAIGN_TYPE
400
Invalid campaign type
MISSING_START_DATE
400
Start date required for time-bound campaigns
MISSING_END_DATE
400
End date required for time-bound campaigns
MISSING_TRIGGERS
400
At least one trigger required for simple mode
MISSING_EFFECTS
400
At least one effect required for simple mode
DUPLICATE_NAME
409
Campaign name already exists
INVALID_CHALLENGE_CONFIG
400
Invalid multi-step challenge configuration
TOO_MANY_STEPS
400
Challenge cannot have more than 10 steps
Related APIs
Segments API - Create and manage user segments with include/exclude criteria
Rules API - Advanced rule configuration for campaigns
Audience API - Search and filter users for targeting
Support
Documentation: https://products.monterosa.co/mic/reference Support: [email protected]
Last updated

