Meet Platform
Technical reference for the Meet platform. This covers the APIs and integration points for developers building custom content or integrations.
For guidance on creating Meet projects in the CMS, see Using Meet.
Overview
Meet is a timeline-based platform for team-focused, competitive learning experiences. It features:
- Real-time scoring — Points are tracked and persisted to a database
- Team registration — Participants create teams with names and avatars
- Live leaderboard — Scores update in real-time across all participants
- Admin controls — Manage teams, view data, and control the experience
PostMessage API
Games and screens communicate with the Meet platform using the PostMessage API. This handles scoring, progression, and data exchange.
Sending messages
From within an iframe (game or screen), send messages to Meet:
window.parent.postMessage({
message: "messageType",
// ... additional data
}, "*")
Message types
updateScore
Updates the team's score.
window.parent.postMessage({
message: "updateScore",
value: 50, // Points to add (can be negative)
choice: "option_a", // Optional: identifier for the choice
type: "NORMAL" // "NORMAL" or "BONUS"
}, "*")
Payload sent to backend:
{
"points": 50,
"choice": "option_a",
"type": "NORMAL",
"level": "current_level_id",
"activity": "activity_name",
"timeline": "current_timeline_id"
}
finish / finished
Marks the current activity as completed.
window.parent.postMessage({ message: "finish" }, "*")
restartLevel
Resets all points for the current level.
window.parent.postMessage({ message: "restartLevel" }, "*")
restartTimeline
Resets all points for the entire timeline.
window.parent.postMessage({ message: "restartTimeline" }, "*")
Requesting data
Request data from Meet and receive a response message.
getTeamData
window.parent.postMessage({ message: "getTeamData" }, "*")
Response:
{
message: "teamData",
data: {
avatarId: "avatar-123",
avatarImage: "/avatars/dragon.png",
avatarName: "Dragon",
teamInitials: "DRG",
teamName: "Dragon Warriors",
score: 450,
points: [/* point records */]
}
}
getLevelData
window.parent.postMessage({ message: "getLevelData" }, "*")
Response:
{
message: "levelData",
data: {
levelId: "level-2",
timelineId: "timeline-1",
totalPoints: 150,
normalPoints: 100,
bonusPoints: 50
}
}
getTimelineData
window.parent.postMessage({ message: "getTimelineData" }, "*")
Response:
{
message: "timelineData",
data: {
timelineId: "timeline-1",
totalPoints: 450,
normalPoints: 350,
bonusPoints: 100
}
}
Listening for responses
window.addEventListener("message", (event) => {
const data = event.data
switch (data.message) {
case "teamData":
console.log("Team:", data.data.teamName)
break
case "levelData":
console.log("Level points:", data.data.totalPoints)
break
case "timelineData":
console.log("Timeline points:", data.data.totalPoints)
break
}
})
Teams API
REST API for accessing team data. Requires admin authentication.
Get all teams
GET /api/admin-api/teams
Returns all teams sorted by score (highest first).
Query parameters:
| Parameter | Type | Description |
|---|---|---|
group | string | Filter by avatar name (case-insensitive partial match) |
Example:
// All teams
const response = await fetch("/api/admin-api/teams")
// Filter by avatar name
const response = await fetch("/api/admin-api/teams?group=dragon")
Response:
{
"teams": [
{
"id": "team-123",
"teamName": "Dragon Warriors",
"teamInitials": "DRG",
"avatarId": "avatar-1",
"avatarImage": "/avatars/dragon.png",
"avatarName": "Dragon",
"score": 450,
"points": [
{
"id": "point-1",
"points": 50,
"level": "level-2",
"timeline": "timeline-1",
"activity": "quiz-1",
"teamId": "team-123",
"choice": "option_a",
"createdAt": "2024-01-15T10:30:00Z",
"type": "NORMAL"
}
]
}
]
}
Get teams by level
GET /api/admin-api/teams/level?level=level-2
Returns team data for a specific level.
Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
level | string | Yes | The level ID to filter by |
Custom admin screens
Add custom screens to the admin dashboard for specialised functionality.
Configuration
Add to your project config:
{
"admin": [
{
"path": "/admin/custom-leaderboard/index.html",
"name": "Custom Leaderboard",
"id": "custom-leaderboard",
"param": "leaderboard"
}
]
}
Properties
| Property | Type | Description |
|---|---|---|
path | string | File path to the custom screen HTML |
name | string | Display name in the admin menu |
id | string | Unique identifier |
param | string | URL parameter for routing |
Access
Custom screens are accessible at /admin/custom/:param
Example screen
<!DOCTYPE html>
<html>
<head>
<title>Custom Leaderboard</title>
</head>
<body>
<div id="leaderboard"></div>
<script>
async function loadTeams() {
const response = await fetch("/api/admin-api/teams")
const data = await response.json()
document.getElementById("leaderboard").innerHTML = data.teams
.map((team, i) => `
<div class="team">
<span>${i + 1}.</span>
<span>${team.teamName}</span>
<span>${team.score} pts</span>
</div>
`)
.join("")
}
loadTeams()
</script>
</body>
</html>
Admin routes
Built-in admin routes:
| Route | Description |
|---|---|
/avt-admin | Main admin dashboard |
/avt-admin/leaderboard | Live leaderboard view |
/avt-admin/signup | Team registration management |
/avt-admin/users | User management |
/avt-admin/custom/:id | Custom admin screens |
