Best Practices - Gamification
Best Practices
Rule design — use groupBy wisely. groupBy: "kuserId" accumulates across all entries. groupBy: "kuserId,entryId" accumulates per entry per user — use this for "watch X minutes per session" rules where you want per-session caps.
Set maxPoints caps. Without maxPoints, users can accumulate unlimited points from a single rule. Use caps to prevent gaming: "maxPoints": "100" per session for viewership, "maxPoints": "50" for chat.
Sub-rule ordering. Sub-rules execute before the root rule evaluates. Use block_root_rule_if_exhausted to cap total accumulation, and block_root_rule_while_in_progress for prerequisite logic.
Status lifecycle. Create game objects as scheduled, enable rules, then update to enabled when the event starts. Use scheduledGameObject for automated transitions.
Event scoping. Scope rules to specific events or content using virtualEventId and categories conditions. Without scoping, rules apply to all partner content.
Certificate PDF design. Test the PDF template with a real certificate before the event. The background image URL must be publicly accessible. Text overlay positions (x, y) are in pixels from the top-left corner.
Participation policies. Always exclude internal staff from leaderboards and lead scoring via byEmailDomain with policy do_not_save. Speakers can participate but should be hidden via do_not_display.
External events. Use delta mode for incremental score additions (booth visits, check-ins). Use upsert mode when the external system provides final scores (exam results, external quiz platforms).
Common Integration Patterns
Virtual Conference Engagement Program
Set up a complete gamification program for a multi-day virtual conference.
# 1. Create leaderboard (scheduled)
LEADERBOARD=$(curl -s -X POST "$KALTURA_SCM_URL/leaderboard/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"objectType": "Leaderboard",
"name": "Conference 2025",
"status": "scheduled",
"startDate": "2025-06-01T09:00:00Z",
"endDate": "2025-06-03T18:00:00Z",
"participationPolicy": {
"userDefaultPolicy": "display",
"policies": [
{"policy": "do_not_save", "matchCriteria": "byEmailDomain", "values": ["internal.com"]}
]
},
"subLeaderboards": [{"name": "By Country", "filterPaths": ["country"], "id": 0}],
"virtualEventIds": ["$VIRTUAL_EVENT_ID"]
}' | jq -r '.id')
# 2. Create rules
# Viewership: 10 pts per 60 sec watched, max 100 per session
curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leaderboard",
"gameObjectId": "'$LEADERBOARD'",
"name": "Watch sessions",
"conditions": [{"fact": "eventType", "operator": "equal", "value": "viewPeriod"}],
"type": "sum",
"mode": "distribute_points",
"metric": "playTime",
"groupBy": "kuserId,entryId",
"goal": "60",
"points": "10",
"maxPoints": "100"
}'
# Polls: 25 pts per poll answered
curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leaderboard",
"gameObjectId": "'$LEADERBOARD'",
"name": "Answer polls",
"conditions": [{"fact": "eventType", "operator": "equal", "value": "pollAnswered"}],
"type": "count",
"mode": "distribute_points",
"metric": "pollId",
"groupBy": "kuserId",
"goal": "1",
"points": "25",
"maxPoints": "unlimited"
}'
# Chat: 5 pts per message, max 50
curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leaderboard",
"gameObjectId": "'$LEADERBOARD'",
"name": "Chat messages",
"conditions": [{"fact": "eventType", "operator": "equal", "value": "comment"}],
"type": "count",
"mode": "distribute_points",
"metric": "comment",
"groupBy": "kuserId",
"goal": "1",
"points": "5",
"maxPoints": "50"
}'
# 3. Create badges
curl -s -X POST "$KALTURA_SCM_URL/badge/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"name": "Power Attendee",
"description": "Watch 10 sessions",
"virtualEventIds": ["$VIRTUAL_EVENT_ID"],
"participationPolicy": {"userDefaultPolicy": "display", "policies": []},
"rules": [{
"name": "Watch 10 unique sessions",
"conditions": [{"fact": "eventType", "operator": "equal", "value": "viewPeriod"}],
"type": "countUnique",
"metric": "entryId",
"groupBy": "kuserId",
"goal": "10",
"points": "1",
"maxPoints": "1"
}]
}'
# 4. Enable leaderboard when event starts
curl -s -X POST "$KALTURA_SCM_URL/leaderboard/update" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{"id": "'$LEADERBOARD'", "status": "enabled"}'
Partner Training Certification
Set up tiered certification with PDF certificates.
# 1. Create certificate with PDF template
CERT=$(curl -s -X POST "$KALTURA_SCM_URL/certificate/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"name": "Partner Certified Developer",
"description": "Complete all training modules",
"status": "disabled",
"certificateEligibility": "once",
"certifiedCreditsThreshold": 3,
"host": "https://training.example.com",
"participationPolicy": {"userDefaultPolicy": "display", "policies": []},
"outputFileConfiguration": {
"outputFileElements": [
{"url": "https://cfvod.kaltura.com/p/'$PARTNER_ID'/thumbnail/entry_id/'$BG_ENTRY'/width/1397/height/1080"},
{"textElementType": "userFullName", "fontSize": 30, "y": 440},
{"textElementType": "certificationDate", "fontSize": 18, "x": 695, "y": 636},
{"textElementType": "credits", "fontSize": 23, "x": 1060, "y": 699}
]
}
}' | jq -r '.id')
# 2. Create viewership rule for the certificate
RULE=$(curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "certificate",
"gameObjectId": "'$CERT'",
"name": "Watch training module",
"conditions": [{"fact": "eventType", "operator": "equal", "value": "viewPeriod"}],
"type": "sum",
"mode": "distribute_points",
"metric": "playTime",
"groupBy": "kuserId,entryId",
"goal": "60",
"points": "1",
"maxPoints": "unlimited",
"reportFormat": "default"
}' | jq -r '.id')
# 3. Enable certificate with credits mapping
curl -s -X POST "$KALTURA_SCM_URL/certificate/update" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"id": "'$CERT'",
"status": "enabled",
"creditsMapping": "credits,'$RULE'\n10.0,1\n11.5,2"
}'
Post-Event Lead Scoring
Score attendees and export hot leads to CRM.
# 1. Create lead scoring profile
LEAD=$(curl -s -X POST "$KALTURA_SCM_URL/leadScoring/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"name": "Event Lead Scoring",
"status": "scheduled",
"startDate": "2025-06-01T00:00:00Z",
"endDate": "2025-06-03T23:59:59Z",
"participationPolicy": {
"userDefaultPolicy": "display",
"policies": [{"policy": "do_not_save", "matchCriteria": "byEmailDomain", "values": ["internal.com"]}]
},
"scoreGroups": [
{"name": "Top", "range": [1000, 99999]},
{"name": "Mid", "range": [500, 999]},
{"name": "Low", "range": [0, 499]}
],
"virtualEventIds": ["$VIRTUAL_EVENT_ID"]
}' | jq -r '.id')
# 2. Create rules across engagement categories
# Registration
curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leadScoring",
"gameObjectId": "'$LEAD'",
"name": "Registration",
"conditions": [{"fact": "eventType", "operator": "equal", "value": "registered"}],
"type": "count",
"mode": "distribute_points",
"metric": "kuserId",
"groupBy": "kuserId",
"goal": "1",
"points": "50",
"maxPoints": "50"
}'
# Viewership
curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leadScoring",
"gameObjectId": "'$LEAD'",
"name": "Session viewership",
"conditions": [{"fact": "eventType", "operator": "equal", "value": "viewPeriod"}],
"type": "sum",
"mode": "distribute_points",
"metric": "playTime",
"groupBy": "kuserId,entryId",
"goal": "60",
"points": "10",
"maxPoints": "unlimited"
}'
# 3. After event — generate lead scoring report
curl -s -X POST "$KALTURA_SCM_URL/report/generate" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{"reportType": "userLeadScoring", "gameObjectId": "'$LEAD'"}'
# 4. List user lead scores
curl -s -X POST "$KALTURA_SCM_URL/userLeadScoring/list" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{"gameObjectId": "'$LEAD'", "pager": {"pageSize": 100, "pageIndex": 1}}'
Flash Challenges with Scheduled Transitions
Create time-limited challenges that auto-enable and auto-disable.
# Create challenge leaderboard
CHALLENGE=$(curl -s -X POST "$KALTURA_SCM_URL/leaderboard/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"objectType": "Leaderboard",
"name": "Keynote Flash Challenge",
"status": "scheduled",
"startDate": "2025-06-01T14:00:00Z",
"endDate": "2025-06-01T15:00:00Z",
"participationPolicy": {"userDefaultPolicy": "display", "policies": []},
"virtualEventIds": ["$VIRTUAL_EVENT_ID"]
}' | jq -r '.id')
# Double points for this challenge
curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leaderboard",
"gameObjectId": "'$CHALLENGE'",
"name": "Speed polls (double points)",
"conditions": [{"fact": "eventType", "operator": "equal", "value": "pollAnswered"}],
"type": "count",
"mode": "distribute_points",
"metric": "pollId",
"groupBy": "kuserId",
"goal": "1",
"points": "50",
"maxPoints": "unlimited"
}'
# Schedule auto-enable at challenge start
curl -s -X POST "$KALTURA_SCM_URL/scheduledGameObject/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leaderboard",
"gameObjectId": "'$CHALLENGE'",
"scheduledAction": "enable",
"scheduledDate": "2025-06-01T14:00:00Z"
}'
# Schedule auto-disable at challenge end
curl -s -X POST "$KALTURA_SCM_URL/scheduledGameObject/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leaderboard",
"gameObjectId": "'$CHALLENGE'",
"scheduledAction": "disable",
"scheduledDate": "2025-06-01T15:00:00Z"
}'
CPE / Continuing Education Credits
Track Continuing Professional Education (CPE) credits per session for accreditation bodies (medical, legal, accounting). Each session awards credits based on verified watch time, and a branded PDF certificate is generated for submission to the accreditation authority.
Workflow:
- Create a certificate with
externalId(accreditation program ID),certificateEligibility: "perEntry"(one certificate per session per user), andcertifiedCreditsThreshold(minimum credits for certification) - Create a
sumrule onviewPeriodscoped to a session category via acategoriescondition, so only content in that category contributes credits - Configure
creditsMappingto map watch-time thresholds to credit values (e.g., 60 minutes = 1.0 credit, 90 minutes = 1.5 credits) - Set participation policies to exclude speakers from earning credits
- Generate per-entry certificates for submission to the accreditation body
# 1. Create CPE certificate with per-entry eligibility
CERT=$(curl -s -X POST "$KALTURA_SCM_URL/certificate/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"name": "CPE Credit Certificate",
"description": "Continuing Professional Education — 1 credit per qualifying session",
"status": "disabled",
"externalId": "NASBA-PROG-2025-4821",
"certificateEligibility": "perEntry",
"certifiedCreditsThreshold": 1,
"host": "https://training.events.kaltura.com",
"participationPolicy": {
"userDefaultPolicy": "display",
"policies": [
{"policy": "do_not_save", "matchCriteria": "byGroup", "values": ["speakers"]}
]
},
"outputFileConfiguration": {
"outputFileElements": [
{"url": "https://cfvod.kaltura.com/p/'$PARTNER_ID'/thumbnail/entry_id/'$BG_ENTRY_ID'/width/1397/height/1080"},
{"textElementType": "userFullName", "fontSize": 30, "y": 440},
{"textElementType": "entryName", "fontSize": 30, "y": 570},
{"textElementType": "credits", "fontSize": 23, "x": 1060, "y": 699},
{"textElementType": "certificationDate", "fontSize": 18, "x": 695, "y": 636}
]
}
}' | jq -r '.id')
# 2. Create viewership rule scoped to accredited sessions category
RULE=$(curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "certificate",
"gameObjectId": "'$CERT'",
"name": "CPE session watch time",
"conditions": [
{"fact": "eventType", "operator": "equal", "value": "viewPeriod"},
{"fact": "categories", "operator": "in", "value": "'$CATEGORY_ID'"}
],
"type": "sum",
"mode": "distribute_points",
"metric": "playTime",
"groupBy": "kuserId,entryId",
"goal": "60",
"points": "1",
"maxPoints": "unlimited",
"reportFormat": "in_minutes"
}' | jq -r '.id')
# 3. Enable certificate with credits mapping (watch-time to CPE credit tiers)
curl -s -X POST "$KALTURA_SCM_URL/certificate/update" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"id": "'$CERT'",
"status": "enabled",
"creditsMapping": "credits,'$RULE'\n1.0,1\n1.5,2\n2.0,3"
}'
# 4. Generate per-entry certificate report for accreditation submission
curl -s -X POST "$KALTURA_SCM_URL/report/generate" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{"reportType": "entryCertificate", "gameObjectId": "'$CERT'"}'
The categories condition in the rule ensures only sessions within the accredited category contribute watch time. The certificateEligibility: "perEntry" setting generates a separate certificate per session, so each CPE credit maps to a specific session for audit purposes.
See also: Events Platform for virtual event and session category setup, Custom Metadata for attaching accreditation metadata to entries.
External Score Import (Hybrid Events)
Hybrid events combine in-person and digital activities on a single leaderboard. Booth visits, physical check-ins, and external quiz platforms produce scores outside the Kaltura analytics pipeline. Import those scores via CSV so they appear alongside digital engagement on the same leaderboard.
Workflow:
- Create an
externaltype rule (metric:"score") on the leaderboard so it accepts imported events - Prepare a CSV file with
userId,score, andeventTypecolumns - Upload via
event/sendExternalEventsFromCSVwithdeltamode (add to existing) orupsertmode (replace existing) - Verify imported scores in
userScore/list
# 1. Create external rule on the leaderboard
curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leaderboard",
"gameObjectId": "'$LEADERBOARD_ID'",
"name": "Booth visits and physical activities",
"conditions": [{"fact": "eventType", "operator": "equal", "value": "boothVisit"}],
"type": "external",
"mode": "distribute_points",
"metric": "score",
"groupBy": "kuserId",
"goal": "1",
"points": "score",
"maxPoints": "unlimited"
}'
# 2. Import scores — delta mode (add to existing scores)
# CSV columns: userId, score, eventType
curl -s -X POST "$KALTURA_SCM_URL/event/sendExternalEventsFromCSV" \
-H "Authorization: Bearer $KALTURA_KS" \
-F "eventAction=delta" \
-F "csvFile=@-;filename=scores.csv" <<'CSVEOF'
userId,score,eventType
user1@example.com,50,boothVisit
user2@example.com,75,boothVisit
user3@example.com,100,boothVisit
CSVEOF
# 3. Import scores — upsert mode (replace existing scores)
# Use upsert when the external system provides final scores (e.g., quiz retake)
curl -s -X POST "$KALTURA_SCM_URL/event/sendExternalEventsFromCSV" \
-H "Authorization: Bearer $KALTURA_KS" \
-F "eventAction=upsert" \
-F "csvFile=@-;filename=quiz_finals.csv" <<'CSVEOF'
userId,score,eventType
user1@example.com,90,boothVisit
user2@example.com,85,boothVisit
CSVEOF
Use delta for incremental activities where each occurrence adds points (booth scans, check-ins). Use upsert when the external system provides a corrected or final score that should replace the previous value (exam retakes, final quiz grades).
See also: Section 11 (External Events & CSV Import) for CSV format details, Analytics Reports for verifying imported data in analytics.
Sponsor Engagement Tracking & ROI Reports
Event sponsors need measurable engagement data to justify renewal. Organize sponsor content by category, track booth page visits via analytics events, score engagement on a per-sponsor leaderboard, and generate per-sponsor reports.
Workflow:
- Create a category per sponsor using the Categories & Entitlements API
- Create leaderboard rules with
categoriesconditions scoping to each sponsor's category - Track booth page engagement via
analytics.trackEvent(eventType 10003 for page loads) - Pull per-sponsor analytics via
report.getTablewithcategoriesIdsInfilter - Generate per-sponsor gamification reports
# 1. Create leaderboard rule scoped to sponsor category
curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leaderboard",
"gameObjectId": "'$LEADERBOARD_ID'",
"name": "Sponsor booth engagement",
"conditions": [
{"fact": "eventType", "operator": "equal", "value": "viewPeriod"},
{"fact": "categories", "operator": "in", "value": "'$SPONSOR_CATEGORY_ID'"}
],
"type": "sum",
"mode": "distribute_points",
"metric": "playTime",
"groupBy": "kuserId,entryId",
"goal": "30",
"points": "15",
"maxPoints": "150"
}'
# 2. Track sponsor booth page visit via analytics.trackEvent (API v3)
curl -s -X POST "$KALTURA_SERVICE_URL/service/analytics/action/trackEvent" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "event[objectType]=KalturaStatsEvent" \
-d "event[eventType]=10003" \
-d "event[entryId]=$SPONSOR_ENTRY_ID" \
-d "event[partnerId]=$KALTURA_PARTNER_ID"
# 3. Pull per-sponsor engagement data via report.getTable (API v3)
curl -s -X POST "$KALTURA_SERVICE_URL/service/report/action/getTable" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "reportType=38" \
-d "reportInputFilter[objectType]=KalturaReportInputFilter" \
-d "reportInputFilter[fromDate]=$FROM_TIMESTAMP" \
-d "reportInputFilter[toDate]=$TO_TIMESTAMP" \
-d "reportInputFilter[categoriesIdsIn]=$SPONSOR_CATEGORY_ID" \
-d "pager[objectType]=KalturaFilterPager" \
-d "pager[pageSize]=100" \
-d "pager[pageIndex]=1"
# 4. Generate per-sponsor gamification report
curl -s -X POST "$KALTURA_SCM_URL/report/generate" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{"reportType": "userScore", "gameObjectId": "'$LEADERBOARD_ID'"}'
The categories condition on the rule ensures only content within the sponsor's category contributes engagement points. Combine the gamification userScore report with the API v3 report.getTable data (reportType 38 = Top Content) to build a comprehensive sponsor ROI package showing both engagement scores and detailed viewing analytics.
See also: Categories & Entitlements for sponsor category setup, Events Collection for analytics event tracking, Analytics Reports for report.getTable usage, Events Platform for virtual event structure.
Employee Onboarding Gamification
Make employee onboarding engaging with module-based scoring, milestone badges, and a branded completion certificate. HR managers track cohort progress and generate records for compliance.
Workflow:
- Create a leaderboard with a 90-day cohort window (startDate/endDate)
- Create
sumrules per onboarding module category (company culture, IT security, benefits) - Create milestone badges with inline rules ("Day 1 Done", "Security Certified", "Fully Onboarded")
- Create a completion certificate with HR-branded PDF template
- Managers query
userScore/listfor cohort progress andreport/generatefor HR records
# 1. Create 90-day onboarding leaderboard
ONBOARD_LB=$(curl -s -X POST "$KALTURA_SCM_URL/leaderboard/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"objectType": "Leaderboard",
"name": "Q2 Onboarding Cohort",
"description": "New hire onboarding progress — 90-day window",
"status": "scheduled",
"startDate": "2025-04-01T00:00:00Z",
"endDate": "2025-06-30T23:59:59Z",
"participationPolicy": {"userDefaultPolicy": "display", "policies": []},
"virtualEventIds": ["$VIRTUAL_EVENT_ID"]
}' | jq -r '.id')
# 2. Create module completion rule (scoped to IT Security category)
curl -s -X POST "$KALTURA_SCM_URL/rule/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectType": "leaderboard",
"gameObjectId": "'$ONBOARD_LB'",
"name": "IT Security module completion",
"conditions": [
{"fact": "eventType", "operator": "equal", "value": "viewPeriod"},
{"fact": "categories", "operator": "in", "value": "'$IT_SECURITY_CATEGORY_ID'"}
],
"type": "sum",
"mode": "distribute_points",
"metric": "playTime",
"groupBy": "kuserId,entryId",
"goal": "60",
"points": "20",
"maxPoints": "100"
}'
# 3. Create "Security Certified" milestone badge
curl -s -X POST "$KALTURA_SCM_URL/badge/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"name": "Security Certified",
"description": "Complete all IT security training modules and pass the quiz",
"virtualEventIds": ["$VIRTUAL_EVENT_ID"],
"iconUrl": "https://example.com/badges/security-certified.png",
"participationPolicy": {"userDefaultPolicy": "display", "policies": []},
"rules": [
{
"name": "Watch all IT security sessions",
"conditions": [
{"fact": "eventType", "operator": "equal", "value": "viewPeriod"},
{"fact": "categories", "operator": "in", "value": "'$IT_SECURITY_CATEGORY_ID'"}
],
"type": "countUnique",
"metric": "entryId",
"groupBy": "kuserId",
"goal": "5",
"points": "1",
"maxPoints": "1"
},
{
"name": "Pass IT security quiz",
"conditions": [
{"fact": "eventType", "operator": "equal", "value": "quizSubmitted"},
{"fact": "categories", "operator": "in", "value": "'$IT_SECURITY_CATEGORY_ID'"}
],
"type": "count",
"metric": "kuserId",
"groupBy": "kuserId",
"goal": "1",
"points": "1",
"maxPoints": "1"
}
]
}'
# 4. Create HR-branded onboarding completion certificate
ONBOARD_CERT=$(curl -s -X POST "$KALTURA_SCM_URL/certificate/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"name": "Onboarding Complete",
"description": "New hire onboarding program — all modules completed",
"status": "enabled",
"certificateEligibility": "once",
"certifiedCreditsThreshold": 3,
"host": "https://onboarding.internal.example.com",
"participationPolicy": {"userDefaultPolicy": "display", "policies": []},
"outputFileConfiguration": {
"outputFileElements": [
{"url": "https://cfvod.kaltura.com/p/'$PARTNER_ID'/thumbnail/entry_id/'$HR_BG_ENTRY_ID'/width/1397/height/1080"},
{"textElementType": "userFullName", "fontSize": 30, "y": 440},
{"textElementType": "certificationDate", "fontSize": 18, "x": 695, "y": 636}
]
}
}' | jq -r '.id')
# 5. Generate onboarding completion report for HR records
curl -s -X POST "$KALTURA_SCM_URL/report/generate" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{"reportType": "userCertificate", "gameObjectId": "'$ONBOARD_CERT'"}'
The 90-day window on the leaderboard defines the cohort period. Each onboarding module maps to a category, so rules can target specific modules. The badge requires both watching all sessions (countUnique on entryId) and passing the quiz (count on quizSubmitted), ensuring comprehensive completion before awarding the milestone.
See also: Categories & Entitlements for organizing onboarding modules by category, User Management for managing new hire user accounts and group assignments.
Customer Education Academy with Badges
Reduce support tickets by building a customer education portal with visible achievement badges. Each product area has a badge requiring both content consumption and quiz completion. Track customer progress and export completion data to CRM.
Workflow:
- Organize courses by product area categories (Admin Console, API Development, Analytics)
- Create badges per module with inline rules —
countUniqueonentryIdfor content completion,countonquizSubmittedfor knowledge verification - Create a "Certified Administrator" certificate for customers completing all modules
- Query
userBadge/listfor per-customer progress - Generate badge completion reports for CRM integration
# 1. Create "API Expert" badge with content + quiz requirements
curl -s -X POST "$KALTURA_SCM_URL/badge/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"name": "API Expert",
"description": "Complete all API training courses and pass the certification quiz",
"virtualEventIds": ["$VIRTUAL_EVENT_ID"],
"iconUrl": "https://example.com/badges/api-expert.png",
"participationPolicy": {"userDefaultPolicy": "display", "policies": []},
"rules": [
{
"name": "Complete API training courses",
"conditions": [
{"fact": "eventType", "operator": "equal", "value": "viewPeriod"},
{"fact": "categories", "operator": "in", "value": "'$API_TRAINING_CATEGORY_ID'"}
],
"type": "countUnique",
"metric": "entryId",
"groupBy": "kuserId",
"goal": "8",
"points": "1",
"maxPoints": "1"
},
{
"name": "Pass API certification quiz",
"conditions": [
{"fact": "eventType", "operator": "equal", "value": "quizSubmitted"},
{"fact": "categories", "operator": "in", "value": "'$API_TRAINING_CATEGORY_ID'"}
],
"type": "count",
"metric": "kuserId",
"groupBy": "kuserId",
"goal": "1",
"points": "1",
"maxPoints": "1"
}
]
}'
# 2. Query per-customer badge progress
curl -s -X POST "$KALTURA_SCM_URL/userBadge/list" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectId": "'$BADGE_ID'",
"pager": {"pageSize": 100, "pageIndex": 1}
}'
# 3. Generate badge completion report for CRM export
curl -s -X POST "$KALTURA_SCM_URL/report/generate" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{"reportType": "userBadge", "gameObjectId": "'$BADGE_ID'"}'
Each badge requires both content consumption (countUnique ensures the customer watched distinct courses, not the same one repeatedly) and quiz completion (count on quizSubmitted). The userBadge/list response includes per-rule rulesData with progress and completed fields, so your application can render a progress bar per badge. Export the userBadge report to your CRM to trigger follow-up workflows when customers achieve certifications.
See also: Categories & Entitlements for product area category structure, eSearch for searching entries and users by badge-related metadata.
Team-Based Competitions
Run department-level or regional competitions alongside individual rankings. Sub-leaderboards automatically aggregate individual scores by a user profile property (company, country, department), so team standings update in real time without separate team-level scoring logic.
Workflow:
- Create a leaderboard with
subLeaderboardsusingfilterPathsreferencing user profile properties (e.g.,["company"]for department grouping) - Individual scores auto-aggregate within their team segment
- Create a team-level badge to recognize the top-performing department
- Query sub-leaderboard rankings via
userScore/listwithgameObjectType: "leaderboard"
# 1. Create leaderboard with department-based sub-leaderboards
TEAM_LB=$(curl -s -X POST "$KALTURA_SCM_URL/leaderboard/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"objectType": "Leaderboard",
"name": "Sales Kickoff Competition",
"description": "Individual and department rankings for SKO 2025",
"status": "scheduled",
"startDate": "2025-06-01T09:00:00Z",
"endDate": "2025-06-03T18:00:00Z",
"participationPolicy": {
"userDefaultPolicy": "display",
"policies": [
{"policy": "do_not_display", "matchCriteria": "byGroup", "values": ["executives"]}
]
},
"subLeaderboards": [
{"name": "By Department", "filterPaths": ["company"], "id": 0}
],
"virtualEventIds": ["$VIRTUAL_EVENT_ID"]
}' | jq -r '.id')
# 2. Create "Top Department" team badge
curl -s -X POST "$KALTURA_SCM_URL/badge/create" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"name": "Top Department",
"description": "Awarded to every member of the highest-scoring department",
"virtualEventIds": ["$VIRTUAL_EVENT_ID"],
"iconUrl": "https://example.com/badges/top-department.png",
"participationPolicy": {"userDefaultPolicy": "display", "policies": []},
"rules": [
{
"name": "Department total engagement",
"conditions": [{"fact": "eventType", "operator": "equal", "value": "viewPeriod"}],
"type": "sum",
"metric": "playTime",
"groupBy": "kuserId",
"goal": "300",
"points": "1",
"maxPoints": "1"
}
]
}'
# 3. Query team standings (sub-leaderboard rankings)
curl -s -X POST "$KALTURA_SCM_URL/userScore/list" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"gameObjectId": "'$TEAM_LB'",
"gameObjectType": "leaderboard",
"pager": {"pageSize": 50, "pageIndex": 1}
}'
The filterPaths: ["company"] setting on the sub-leaderboard groups users by the company property from their User Profile. Individual scores accumulate normally, and the sub-leaderboard aggregates them per team automatically. Use do_not_display for executives so they participate (their scores count toward the department total) but do not appear in individual rankings.
See also: User Profile for user properties that power
filterPathsgrouping, Events Platform for virtual event scoping.