PlaycademyPlaycademy

@playcademy/sdk

API reference for the Playcademy SDK

@playcademy/sdk

Official TypeScript SDK for the Playcademy platform

The Playcademy SDK provides a comprehensive, type-safe interface for building games on the Playcademy platform. It handles authentication, game sessions, user data, inventory management, and all platform APIs through a unified client interface.

Overview

The SDK serves as the primary interface between your game and the Playcademy platform, providing:

  • Automatic Environment Detection: Seamlessly works in development and production
  • Type-Safe API Access: Full TypeScript support with comprehensive type definitions
  • Session Management: Automatic game session handling and state persistence
  • Event System: Real-time notifications for inventory changes, level ups, and more
  • Developer Tools: Built-in support for game development and testing workflows

Public vs Internal SDK

The Playcademy SDK is split into two entry points:

Public SDK (@playcademy/sdk)

For game developers building games on the Playcademy platform. Includes 8 essential namespaces:

  • Core: identity, runtime, backend, users
  • Economy: credits
  • Gameplay: scores
  • Multiplayer: realtime
  • Integrations: timeback
import { PlaycademyClient } from '@playcademy/sdk'

const client = await PlaycademyClient.init()
await client.timeback.endActivity({
    /* ... */
})
await client.users.inventory.add('gold-coin', 100)

Internal SDK (@playcademy/sdk/internal)

For CLI, platform, and admin tools. Includes all 21 namespaces (8 public + 13 internal):

Additional internal namespaces:

  • Platform Auth: auth (email/password login, API keys)
  • Administration: admin (game management, items, currencies)
  • Developer Tools: dev (publish games, uploads)
  • Game Directory: games (fetch, list, sessions)
  • Overworld Features: character, achievements, leaderboard, levels, shop, maps, sprites, notifications
  • Analytics: telemetry
import { PlaycademyClient } from '@playcademy/sdk/internal'

const client = new PlaycademyClient({ baseUrl: 'https://hub.playcademy.net' })
await client.auth.login({ email: 'dev@example.com', password: '***' })
const games = await client.games.list()
await client.admin.games.pauseGame('game-123')

Note: The internal SDK is for trusted code only (CLI, platform internals). Game developers should use the public SDK.

Key Benefits

  • Zero Configuration: Automatic initialization with environment detection
  • Production Ready: Battle-tested API patterns with robust error handling
  • Real-Time Communication: Open game-scoped WebSocket channels for multiplayer features.
  • Event System: Subscribe to platform events like inventory changes and level ups
  • Comprehensive Coverage: Access to all Playcademy platform features
  • Development Experience: Integrated with sandbox environment for local development

Use Cases

  • Game Development: Primary SDK for building games on Playcademy
  • Web Applications: Frontend applications interacting with the platform
  • Developer Tools: Scripts and utilities for game management
  • Server Integration: Backend services integrating with Playcademy APIs
  • Testing & Automation: Automated testing of platform integrations

Connection Monitoring

The SDK automatically monitors network connectivity and provides hooks for games to handle disconnects gracefully:

  • Automatic Detection: Multi-signal approach detects offline, slow, and degraded connections
  • Game Handlers: Implement custom disconnect behavior (e.g., return to lobby, pause game)
  • Platform Integration: Built-in helpers for displaying connection alerts
  • Zero Config: Works out of the box, customizable when needed

See the SDK Browser documentation for detailed connection monitoring documentation and examples.

Installation

Install the SDK using your preferred package manager:

# Using Bun (recommended)
bun add @playcademy/sdk

# Using npm
npm install @playcademy/sdk

# Using yarn
yarn add @playcademy/sdk

# Using pnpm
pnpm add @playcademy/sdk

Quick Start

For most game development scenarios, use automatic initialization:

import { PlaycademyClient } from '@playcademy/sdk'

async function initializeGame() {
    try {
        // Automatic initialization - detects environment and configures appropriately
        const client = await PlaycademyClient.init({
            // Optional: Handle connection issues gracefully
            onDisconnect: ({ state, displayAlert }) => {
                if (state === 'offline') {
                    displayAlert?.('Connection lost. Reconnecting...', { type: 'warning' })
                    // Return to safe state (e.g., lobby)
                }
            },
        })

        // Get current user
        const user = await client.users.me()
        console.log('Welcome,', user.name)

        // The client is ready for all platform operations
        return client
    } catch (error) {
        console.error('Failed to initialize Playcademy SDK:', error)
        throw error
    }
}

Environment Detection

The SDK automatically detects and configures for different environments:

  • Development: Connects to local sandbox (started by @playcademy/vite-plugin)
  • Production: Receives configuration from Playcademy platform loader
  • Testing: Falls back to mock configuration for automated testing

Core Features

Game Session Management

// Automatic session management when gameId is available
const client = await PlaycademyClient.init()

// Save transient game state (position, health, temporary data)
await client.games.saveState({
    currentLevel: 'forest_glade',
    playerPosition: { x: 100, y: 200 },
    health: 85,
    activePowerUps: ['speed_boost'],
})

// Load previously saved state
const gameState = await client.games.loadState()
console.log('Loaded state:', gameState)

// Exit game (automatically ends session if managed)
await client.runtime.exit()

User & Inventory Management

// Get user information
const user = await client.users.me()

// Inventory operations (accepts UUIDs or slugs)
const inventory = await client.users.inventory.get()
await client.users.inventory.add('magic-sword', 1)
await client.users.inventory.remove('health-potion', 1)

// Check item quantities and ownership
const goldCount = await client.users.inventory.quantity('gold-coin')
const hasKey = await client.users.inventory.has('dungeon-key')
const hasEnoughGold = await client.users.inventory.has('gold-coin', 100)

Credits & Currency

// Platform currency management
const balance = await client.credits.balance()
await client.credits.add(100)
await client.credits.spend(50)

// Check affordability
if ((await client.credits.balance()) >= 100) {
    await client.credits.spend(100)
    console.log('Purchase successful!')
}

Experience & Levels

// Level management
const userLevel = await client.levels.get()
const progress = await client.levels.progress()
console.log(`Level ${userLevel.currentLevel}, ${progress.xpToNextLevel} XP to next level`)

// Note: XP is now managed entirely through TimeBack integration.
// XP updates come from TimeBack webhooks only.

TimeBack Integration

Access user role and enrollments, and track learning activities:

// Access TimeBack role and enrollments
const role = client.timeback.role // 'student' | 'parent' | 'teacher' | 'administrator'
const enrollments = client.timeback.enrollments // [{ subject, grade, courseId }]

// Check if user is enrolled in a specific grade
const grade3Enrollment = enrollments.find(e => e.grade === 3)
if (grade3Enrollment) {
    // Show grade 3 content
}

// Start tracking an activity (only activityId required!)
client.timeback.startActivity({
    activityId: 'math-quiz-level-1',
})
// Auto-derived: activityName "Math Quiz Level 1"
// Auto-filled by backend: appName, subject, sensorUrl

// ... player completes activity ...

// End activity and submit results (XP calculated automatically)
await client.timeback.endActivity({
    correctQuestions: 8,
    totalQuestions: 10,
})
// XP calculation: base (1 min = 1 XP) × accuracy multiplier
// 100%: 1.25x | 80-99%: 1.0x | 65-79%: 0.5x | <65%: 0x

Real-time Authentication

Get authentication tokens for WebSocket connections used by the platform's multiplayer system.

// Get a realtime token for WebSocket authentication
const { token } = await client.realtime.token.get()

// Token is used internally by the platform's multiplayer WebSocket client
// for presence tracking, player positions, and real-time game features

API Reference

Core Modules

Authentication (client.auth)

  • logout(): Logs out user and clears authentication token

Users (client.users)

  • me(): Get current user information
  • Inventory (client.users.inventory):
    • get(): Get user's inventory
    • add(identifier, quantity): Add items to inventory
    • remove(identifier, quantity): Remove items from inventory
    • quantity(identifier): Get item quantity
    • has(identifier, minQuantity?): Check item ownership

Games (client.games)

  • list(): Get all available games
  • fetch(gameIdOrSlug): Get specific game details
  • saveState(state): Save transient game state
  • loadState(): Load saved game state
  • startSession(gameId?): Start game session
  • endSession(sessionId, gameId?): End game session

Credits (client.credits)

  • balance(): Get current credits balance
  • add(amount): Add credits to user
  • spend(amount): Spend user credits

Levels (client.levels)

  • get(): Get current user level information
  • progress(): Get level progress and XP to next level
  • addXP(amount): Add experience points
  • Config (client.levels.config):
    • list(): Get all level configurations
    • get(level): Get specific level configuration

Maps (client.maps)

  • elements(mapId): Get map elements and points of interest

Runtime (client.runtime)

  • getGameToken(gameId, options?): Get game-specific authentication token
  • exit(): Signal platform to exit game view

Real-time (client.realtime)

  • token.get(): Retrieves a JWT for WebSocket authentication (used by the platform's multiplayer system).

TimeBack (client.timeback)

  • role: The user's TimeBack role ('student', 'parent', 'teacher', or 'administrator')
  • enrollments: Array of course enrollments with subject, grade, and courseId
  • startActivity(metadata): Start tracking an activity (stores start time and metadata)
    • metadata.activityId: Unique activity identifier (required)
    • metadata.activityName: Human-readable activity name
    • metadata.subject: Subject area (Math, Reading, Science, etc.)
    • metadata.appName: Application name
    • metadata.sensorUrl: Sensor URL for tracking
  • endActivity(scoreData): End activity and submit results
    • scoreData.correctQuestions: Number of correct answers
    • scoreData.totalQuestions: Total number of questions
  • XP Query (client.timeback.xp):
    • today(options?): Get today's XP (supports timezone parameter)
    • total(): Get total accumulated XP
    • history(options?): Get XP history with optional date filtering
    • summary(options?): Get both today's and total XP in one call

Leaderboard (client.leaderboard) - Game-specific

  • fetch(options?): Get leaderboard for a specific game
    • options.timeframe: Filter by time period ('all_time', 'monthly', 'weekly', 'daily')
    • options.gameId: Game ID to fetch leaderboard for (required)
    • options.limit: Number of entries to return (default: 10)
    • options.offset: Pagination offset (default: 0)

Scores (client.scores) - Platform-wide

  • submit(gameId, score, metadata?): Submit a score for any game
  • getUserScores(userId, options?): Get all scores for a user
    • options.gameId: Filter by specific game (optional)
    • options.limit: Number of scores to return (default: 50)

Developer Tools

Developer Authentication (client.dev.auth)

  • applyForDeveloper(): Apply for developer status
  • getDeveloperStatus(): Check current developer status

Game Management (client.dev.games)

  • upsert(slug, metadata, gameFile): Create or update game
  • update(gameId, updates): Update game properties
  • delete(gameId): Delete game

API Keys (client.dev.keys)

  • createKey(gameId, name): Create API key for server authentication
  • listKeys(): List all API keys
  • revokeKey(keyId): Revoke API key

Item Management (client.dev.items)

  • list(gameId): List all items for a game
  • get(gameId, slug): Get specific item
  • create(gameId, slug, data): Create new game item
  • update(gameId, itemId, updates): Update existing item
  • delete(gameId, itemId): Delete item

Event System

The SDK provides real-time event notifications for important platform changes:

Available Events

// Authentication changes
client.on('authChange', payload => {
    console.log('Authentication changed:', payload.token)
})

// Connection state changes
client.on('connectionChange', ({ state, reason }) => {
    console.log(`Connection: ${state} - ${reason}`)
})

// Inventory changes
client.on('inventoryChange', payload => {
    console.log(`Item ${payload.itemId}: ${payload.delta} (total: ${payload.newTotal})`)
})

// Experience gained
client.on('xpGained', payload => {
    console.log(`Gained ${payload.amount} XP (total: ${payload.totalXP})`)
})

// Level up notifications
client.on('levelUp', payload => {
    console.log(`Level up! ${payload.oldLevel} → ${payload.newLevel}`)
    console.log('Credits awarded:', payload.creditsAwarded)
})

Disconnect Handling

For convenience, use the onDisconnect method to handle only offline/degraded states:

const cleanup = client.onDisconnect(({ state, reason, displayAlert }) => {
    console.log(`Disconnect detected: ${state}`)
    displayAlert?.(`Connection ${state}: ${reason}`, { type: 'warning' })
})

// Later: cleanup() to unregister

Event-Driven UI Updates

// Update UI in response to platform events
client.on('inventoryChange', payload => {
    updateInventoryDisplay(payload.itemId, payload.newTotal)
})

client.on('levelUp', payload => {
    showLevelUpAnimation(payload.newLevel)
    showCreditsAwarded(payload.creditsAwarded)
})

client.on('xpGained', payload => {
    updateXPBar(payload.totalXP, payload.leveledUp)
})

Advanced Usage

Manual Initialization

For server-side applications or custom environments:

import { PlaycademyClient } from '@playcademy/sdk'

import type { LoginResponse } from '@playcademy/sdk'

// Step 1: Authenticate
const loginData: LoginResponse = await PlaycademyClient.login(
    'https://api.playcademy.com',
    'user@example.com',
    'password',
)

// Step 2: Initialize client
const client = new PlaycademyClient({
    baseUrl: 'https://api.playcademy.com',
    token: loginData.token,
    gameId: 'your-game-id', // Optional: enables automatic session management
})

Custom Configuration

const client = new PlaycademyClient({
    baseUrl: 'https://api.playcademy.com',
    token: 'your-auth-token',
    gameId: 'your-game-id',
    // Additional options
    timeout: 10000, // Request timeout in milliseconds
    retries: 3, // Number of retry attempts
})

Error Handling

import { PlaycademyError } from '@playcademy/sdk'

try {
    const user = await client.users.me()
    // Handle success
} catch (error) {
    if (error instanceof PlaycademyError) {
        console.error('Playcademy API Error:', error.message)
        console.error('Status Code:', error.statusCode)
        console.error('Error Code:', error.code)
    } else {
        console.error('Unexpected error:', error)
    }
}

Development Environment

Integration with Playcademy Vite Plugin

When using the official Playcademy Vite templates, the development environment is automatically configured:

// In your game's main file
import { PlaycademyClient } from '@playcademy/sdk'

// The vite plugin automatically starts the sandbox
const client = await PlaycademyClient.init()
// SDK automatically connects to local sandbox at http://localhost:4321

Manual Sandbox Setup

If not using the Vite plugin, start the sandbox manually:

# Start sandbox server (will also start realtime server on port 4322)
bunx @playcademy/sandbox --port 4321 --verbose

# In your application
const client = new PlaycademyClient({
    baseUrl: 'http://localhost:4321/api',
    realtimeUrl: 'ws://localhost:4322',
    token: 'dev-token' // Sandbox provides mock authentication
})

Best Practices

Initialization & Setup

  • Always use automatic initialization for game development with PlaycademyClient.init()
  • Handle initialization errors gracefully with proper try-catch blocks
  • Store the client instance for reuse throughout your application lifecycle

State Management

  • Use games.saveState() for transient data (current level, position, temporary status)
  • Use users.inventory for persistent items and resources that carry between sessions
  • Save state periodically, not on every frame or minor change
  • Load state once at game start, then manage locally

Performance Optimization

  • Cache frequently accessed data like user information and inventory
  • Batch inventory operations when possible instead of individual API calls
  • Use event listeners to update UI reactively rather than polling
  • Implement proper loading states for better user experience

Error Handling

  • Wrap all SDK calls in appropriate try-catch blocks
  • Provide fallback behavior for network errors and API failures
  • Show meaningful error messages to users when operations fail
  • Implement retry logic for non-critical operations

Development Workflow

  • Use the sandbox environment for all local development
  • Test both online and offline scenarios to ensure robust error handling
  • Enable verbose logging during development for debugging
  • Validate API responses and handle edge cases appropriately

Testing

Unit Testing

// Mock the SDK for unit tests
import { jest } from '@jest/globals'

// Mock the entire SDK module
jest.mock('@playcademy/sdk', () => ({
    PlaycademyClient: {
        init: jest.fn().mockResolvedValue({
            users: {
                me: jest.fn().mockResolvedValue({ id: 'test-user', name: 'Test User' }),
                inventory: {
                    get: jest.fn().mockResolvedValue([]),
                    add: jest.fn().mockResolvedValue(undefined),
                },
            },
        }),
    },
}))

Integration Testing

// Test with real sandbox
import { PlaycademyClient } from '@playcademy/sdk'

describe('Playcademy Integration', () => {
    let client: PlaycademyClient

    beforeAll(async () => {
        // Initialize with sandbox
        client = new PlaycademyClient({
            baseUrl: 'http://localhost:4321/api',
            token: 'test-token',
        })
    })

    test('should fetch user data', async () => {
        const user = await client.users.me()
        expect(user).toBeDefined()
        expect(user.name).toEqual(expect.any(String))
    })
})

Troubleshooting

Common Issues

SDK Initialization Timeout

Error: PLAYCADEMY_INIT not received within 5000ms
  • Ensure you're running in the correct environment (development with sandbox, or production with platform)
  • Check that the Vite plugin is properly configured
  • Verify the sandbox is running on the expected port

Authentication Errors

Error: Unauthorized (401)
  • Check that your authentication token is valid
  • Ensure you have the necessary permissions for the operation
  • Try re-authenticating with PlaycademyClient.login()

Network Connection Issues

Error: Failed to fetch
  • Verify the API endpoint is accessible
  • Check network connectivity
  • Ensure CORS is properly configured for cross-origin requests

Debugging

Use these debugging techniques for troubleshooting SDK issues:

// Check initialization process
try {
    const client = await PlaycademyClient.init()
    console.log('SDK initialized successfully')
} catch (error) {
    console.error('SDK initialization failed:', error)
}

// Monitor network requests in browser dev tools (Network tab)
// Check console for SDK error messages
// Verify API responses and error details

Contributing

The SDK is a critical component of the Playcademy platform ecosystem. When contributing:

  1. Maintain Type Safety: Ensure all new APIs are fully typed
  2. Update Documentation: Keep this README and JSDoc comments current
  3. Add Tests: Include both unit and integration tests for new features
  4. Follow Patterns: Use consistent patterns with existing SDK methods
  5. Handle Errors: Implement proper error handling and user feedback

For general contribution guidelines, see the monorepo CONTRIBUTING.md.

Enumerations

MessageEvents

Defined in: messaging.ts:51

Enumeration of all message types used in the Playcademy messaging system.

Message Flow Patterns:

Parent → Game (Overworld → Game):

  • INIT: Provides game with authentication token and configuration
  • TOKEN_REFRESH: Updates game's authentication token before expiry
  • PAUSE/RESUME: Controls game execution state
  • FORCE_EXIT: Immediately terminates the game
  • OVERLAY: Shows/hides UI overlays over the game

Game → Parent (Game → Overworld):

  • READY: Game has loaded and is ready to receive messages
  • EXIT: Game requests to be closed (user clicked exit, game ended, etc.)
  • TELEMETRY: Game reports performance metrics (FPS, memory usage, etc.)

Enumeration Members

AUTH_CALLBACK
AUTH_CALLBACK: "PLAYCADEMY_AUTH_CALLBACK";

Defined in: messaging.ts:180

OAuth callback data from popup/new-tab windows. Sent from popup window back to parent after OAuth completes. Payload:

  • code: string (OAuth authorization code)
  • state: string (OAuth state for CSRF protection)
  • error: string | null (OAuth error if any)
AUTH_STATE_CHANGE
AUTH_STATE_CHANGE: "PLAYCADEMY_AUTH_STATE_CHANGE";

Defined in: messaging.ts:170

Notifies about authentication state changes. Can be sent in both directions depending on auth flow. Payload:

  • authenticated: boolean
  • user: UserInfo | null
  • error: Error | null
CONNECTION_STATE
CONNECTION_STATE: "PLAYCADEMY_CONNECTION_STATE";

Defined in: messaging.ts:110

Broadcasts connection state changes to games. Sent by platform when network connectivity changes. Payload:

  • state: 'online' | 'offline' | 'degraded'
  • reason: string
DISPLAY_ALERT
DISPLAY_ALERT: "PLAYCADEMY_DISPLAY_ALERT";

Defined in: messaging.ts:156

Game requests platform to display an alert. Sent when connection issues are detected or other important events occur. Payload:

  • message: string
  • options: { type?: 'info' | 'warning' | 'error', duration?: number }
EXIT
EXIT: "PLAYCADEMY_EXIT";

Defined in: messaging.ts:128

Game requests to be closed/exited. Sent when user clicks exit button or game naturally ends. Payload: void

FORCE_EXIT
FORCE_EXIT: "PLAYCADEMY_FORCE_EXIT";

Defined in: messaging.ts:94

Forces immediate game termination (emergency exit). Game should clean up resources and exit immediately. Payload: void

INIT
INIT: "PLAYCADEMY_INIT";

Defined in: messaging.ts:64

Initializes the game with authentication context and configuration. Sent immediately after game iframe loads. Payload:

  • baseUrl: string
  • token: string
  • gameId: string
KEY_EVENT
KEY_EVENT: "PLAYCADEMY_KEY_EVENT";

Defined in: messaging.ts:147

Game reports key events to parent. Sent when certain keys are pressed within the game iframe. Payload:

  • key: string
  • code?: string
  • type: 'keydown' | 'keyup'
OVERLAY
OVERLAY: "PLAYCADEMY_OVERLAY";

Defined in: messaging.ts:101

Shows or hides UI overlays over the game. Game may need to pause or adjust rendering accordingly. Payload: boolean (true = show overlay, false = hide overlay)

PAUSE
PAUSE: "PLAYCADEMY_PAUSE";

Defined in: messaging.ts:80

Pauses game execution (e.g., when user switches tabs). Game should pause timers, animations, and user input. Payload: void

READY
READY: "PLAYCADEMY_READY";

Defined in: messaging.ts:121

Game has finished loading and is ready to receive messages. Sent once after game initialization is complete. Payload: void

RESUME
RESUME: "PLAYCADEMY_RESUME";

Defined in: messaging.ts:87

Resumes game execution after being paused. Game should restore timers, animations, and user input. Payload: void

TELEMETRY
TELEMETRY: "PLAYCADEMY_TELEMETRY";

Defined in: messaging.ts:137

Game reports performance telemetry data. Sent periodically for monitoring and analytics. Payload:

  • fps: number
  • mem: number
TOKEN_REFRESH
TOKEN_REFRESH: "PLAYCADEMY_TOKEN_REFRESH";

Defined in: messaging.ts:73

Updates the game's authentication token before it expires. Sent periodically to maintain valid authentication. Payload:

  • token: string
  • exp: number

Classes

ApiError

Defined in: core/errors.ts:86

API error thrown when a request fails.

Contains structured error information from the API response:

  • status - HTTP status code (e.g., 404)
  • code - API error code (e.g., "NOT_FOUND")
  • message - Human-readable error message
  • details - Optional additional error context

Example

try {
  await client.games.get('nonexistent')
} catch (error) {
  if (error instanceof ApiError) {
    console.log(error.status)   // 404
    console.log(error.code)     // "NOT_FOUND"
    console.log(error.message)  // "Game not found"
    console.log(error.details)  // { identifier: "nonexistent" }
  }
}

Extends

  • Error

Constructors

Constructor
new ApiError(
   status, 
   code, 
   message, 
   details?, 
   rawBody?): ApiError;

Defined in: core/errors.ts:107

Parameters
status

number

HTTP status code

code

string

API error code

message

string

Human-readable error message

details?

unknown

Additional error context

rawBody?

unknown

Raw response body

Returns

ApiError

Overrides
Error.constructor

Properties

code
readonly code: string;

Defined in: core/errors.ts:91

API error code (e.g., "NOT_FOUND", "VALIDATION_FAILED"). Use this for programmatic error handling.

details
readonly details: unknown;

Defined in: core/errors.ts:97

Additional error context from the API. Structure varies by error type (e.g., validation errors include field details).

rawBody
readonly rawBody: unknown;

Defined in: core/errors.ts:103

Internal

Raw response body for debugging.

status
readonly status: number;

Defined in: core/errors.ts:105

Methods

is()
is(code): boolean;

Defined in: core/errors.ts:167

Check if this is a specific error type.

Parameters
code

string

Returns

boolean

Example
if (error.is('NOT_FOUND')) {
  // Handle not found
} else if (error.is('VALIDATION_FAILED')) {
  // Handle validation error
}
isClientError()
isClientError(): boolean;

Defined in: core/errors.ts:174

Check if this is a client error (4xx).

Returns

boolean

isRetryable()
isRetryable(): boolean;

Defined in: core/errors.ts:189

Check if this error is retryable. Server errors and rate limits are typically retryable.

Returns

boolean

isServerError()
isServerError(): boolean;

Defined in: core/errors.ts:181

Check if this is a server error (5xx).

Returns

boolean

fromResponse()
static fromResponse(
   status, 
   statusText, 
   body): ApiError;

Defined in: core/errors.ts:134

Internal

Create an ApiError from an HTTP response. Parses the structured error response from the API.

Parameters
status

number

statusText

string

body

unknown

Returns

ApiError


ConnectionManager

Defined in: core/connection/manager.ts:48

Manages connection monitoring for the Playcademy client.

The ConnectionManager serves as an integration layer between the low-level ConnectionMonitor and the PlaycademyClient. It handles:

  • Event wiring and coordination
  • Disconnect callbacks with context
  • Platform-level alert integration
  • Request success/failure tracking

This class is used internally by PlaycademyClient and typically not instantiated directly by game developers.

See

Constructors

Constructor
new ConnectionManager(config): ConnectionManager;

Defined in: core/connection/manager.ts:75

Creates a new ConnectionManager instance.

Parameters
config

ConnectionManagerConfig

Configuration options for the manager

Returns

ConnectionManager

Example
const manager = new ConnectionManager({
  baseUrl: 'https://api.playcademy.com',
  authContext: { isInIframe: false },
  onDisconnect: (context) => {
    console.log(`Disconnected: ${context.state}`)
  },
  onConnectionChange: (state, reason) => {
    console.log(`Connection changed: ${state}`)
  }
})

Methods

checkNow()
checkNow(): Promise<ConnectionState>;

Defined in: core/connection/manager.ts:124

Manually triggers a connection check immediately.

Forces a heartbeat ping to verify the current connection status. Useful when you need to check connectivity before a critical operation.

In iframe mode, this returns the last known state from platform.

Returns

Promise<ConnectionState>

Promise resolving to the current connection state

Example
const state = await manager.checkNow()
if (state === 'online') {
  await performCriticalOperation()
}
getState()
getState(): ConnectionState;

Defined in: core/connection/manager.ts:102

Gets the current connection state.

Returns

ConnectionState

The current connection state ('online', 'offline', or 'degraded')

Example
const state = manager.getState()
if (state === 'offline') {
  console.log('No connection')
}
onDisconnect()
onDisconnect(callback): () => void;

Defined in: core/connection/manager.ts:185

Registers a callback to be called when connection issues are detected.

The callback only fires for 'offline' and 'degraded' states, not when recovering to 'online'. This provides a clean API for games to handle disconnect scenarios without being notified of every state change.

Works in both iframe and standalone modes transparently.

Parameters
callback

DisconnectHandler

Function to call when connection degrades

Returns

Cleanup function to unregister the callback

(): void;
Returns

void

Example
const cleanup = manager.onDisconnect(({ state, reason, displayAlert }) => {
  if (state === 'offline') {
    displayAlert?.('Connection lost. Saving your progress...', { type: 'error' })
    saveGameState()
  }
})

// Later: cleanup() to unregister
reportRequestFailure()
reportRequestFailure(error): void;

Defined in: core/connection/manager.ts:157

Reports a failed API request to the connection monitor.

Only network errors are tracked (not 4xx/5xx HTTP responses). After consecutive failures exceed the threshold, the state transitions to 'degraded' or 'offline'.

Typically called automatically by the SDK's request wrapper. No-op in iframe mode (platform handles monitoring).

Parameters
error

unknown

The error from the failed request

Returns

void

reportRequestSuccess()
reportRequestSuccess(): void;

Defined in: core/connection/manager.ts:141

Reports a successful API request to the connection monitor.

This resets the consecutive failure counter and transitions from 'degraded' to 'online' state if applicable.

Typically called automatically by the SDK's request wrapper. No-op in iframe mode (platform handles monitoring).

Returns

void

stop()
stop(): void;

Defined in: core/connection/manager.ts:201

Stops connection monitoring and performs cleanup.

Removes event listeners and clears heartbeat intervals. Should be called when the client is being destroyed.

Returns

void


ConnectionMonitor

Defined in: core/connection/monitor.ts:45

Monitors network connectivity using multiple signals and notifies callbacks of state changes.

The ConnectionMonitor uses a multi-signal approach to detect connection issues:

  1. navigator.onLine events - Instant detection of hard disconnects
  2. Heartbeat pings - Periodic checks to detect slow/degraded connections
  3. Request failure tracking - Piggybacks on actual API calls

This comprehensive approach ensures reliable detection across different network failure modes common in school WiFi environments (hard disconnect, slow connection, intermittent failures).

Example

const monitor = new ConnectionMonitor({
  baseUrl: 'https://api.playcademy.com',
  heartbeatInterval: 10000,  // Check every 10s
  failureThreshold: 2         // Trigger after 2 failures
})

monitor.onChange((state, reason) => {
  console.log(`Connection: ${state} - ${reason}`)
})

monitor.start()

See

ConnectionManagerConfig for configuration options

Constructors

Constructor
new ConnectionMonitor(config): ConnectionMonitor;

Defined in: core/connection/monitor.ts:67

Creates a new ConnectionMonitor instance.

The monitor starts in a stopped state. Call start() to begin monitoring.

Parameters
config

ConnectionMonitorConfig

Configuration options

Returns

ConnectionMonitor

Methods

checkNow()
checkNow(): Promise<ConnectionState>;

Defined in: core/connection/monitor.ts:179

Manually triggers an immediate connection check.

Forces a heartbeat ping to verify connectivity right now, bypassing the normal interval. Useful before critical operations.

Returns

Promise<ConnectionState>

Promise resolving to the current connection state after the check

Example
const state = await monitor.checkNow()
if (state !== 'online') {
  alert('Please check your internet connection')
}
getState()
getState(): ConnectionState;

Defined in: core/connection/monitor.ts:159

Gets the current connection state.

Returns

ConnectionState

The current state ('online', 'offline', or 'degraded')

onChange()
onChange(callback): () => void;

Defined in: core/connection/monitor.ts:148

Registers a callback to be notified of all connection state changes.

The callback fires for all state transitions: online → offline, offline → degraded, degraded → online, etc.

Parameters
callback

ConnectionChangeCallback

Function called with (state, reason) when connection changes

Returns

Cleanup function to unregister the callback

(): void;
Returns

void

Example
const cleanup = monitor.onChange((state, reason) => {
  console.log(`Connection: ${state}`)
  if (state === 'offline') {
    showReconnectingUI()
  }
})

// Later: cleanup() to unregister
reportRequestFailure()
reportRequestFailure(error): void;

Defined in: core/connection/monitor.ts:207

Reports a request failure for tracking.

This should be called from your request wrapper whenever an API call fails. Only network errors are tracked (TypeError, fetch failures) - HTTP error responses (4xx, 5xx) are ignored.

After consecutive failures exceed the threshold, the monitor transitions to 'degraded' or 'offline' state.

Parameters
error

unknown

The error from the failed request

Returns

void

Example
try {
  await fetch('/api/data')
} catch (error) {
  monitor.reportRequestFailure(error)
  throw error
}
reportRequestSuccess()
reportRequestSuccess(): void;

Defined in: core/connection/monitor.ts:243

Reports a successful request.

This should be called from your request wrapper whenever an API call succeeds. Resets the consecutive failure counter and transitions from 'degraded' to 'online' if the connection has recovered.

Returns

void

Example
try {
  const result = await fetch('/api/data')
  monitor.reportRequestSuccess()
  return result
} catch (error) {
  monitor.reportRequestFailure(error)
  throw error
}
start()
start(): void;

Defined in: core/connection/monitor.ts:86

Starts monitoring the connection state.

Sets up event listeners and begins heartbeat checks based on configuration. Idempotent - safe to call multiple times.

Returns

void

stop()
stop(): void;

Defined in: core/connection/monitor.ts:109

Stops monitoring the connection state and cleans up resources.

Removes event listeners and clears heartbeat intervals. Idempotent - safe to call multiple times.

Returns

void


PlaycademyClient

Defined in: clients/public.ts:17

Playcademy SDK client for game developers. Provides namespaced access to platform features for games running inside Cademy.

Extends

  • PlaycademyBaseClient

Constructors

Constructor
new PlaycademyClient(config?): PlaycademyClient;

Defined in: clients/base.ts:61

Parameters
config?

Partial<ClientConfig>

Returns

PlaycademyClient

Inherited from
PlaycademyBaseClient.constructor

Properties

authContext?
protected optional authContext: {
  isInIframe: boolean;
};

Defined in: clients/base.ts:41

isInIframe
isInIframe: boolean;
Inherited from
PlaycademyBaseClient.authContext
authStrategy
protected authStrategy: AuthStrategy;

Defined in: clients/base.ts:36

Inherited from
PlaycademyBaseClient.authStrategy
backend
backend: {
  delete: Promise<T>;
  download: Promise<Response>;
  get: Promise<T>;
  patch: Promise<T>;
  post: Promise<T>;
  put: Promise<T>;
  request: Promise<T>;
  url: string;
};

Defined in: clients/public.ts:77

Make requests to your game's custom backend API routes.

  • get(path), post(path, body), put(), delete() - HTTP methods
  • Routes are relative to your game's deployment (e.g., '/hello' → your-game.playcademy.gg/api/hello)
delete()
delete<T>(path, headers?): Promise<T>;

Makes a DELETE request to your game's backend.

Type Parameters
T

T = unknown

Parameters
path

string

The API route path (e.g., '/cache' or 'cache/clear')

headers?

Record<string, string>

Optional additional headers

Returns

Promise<T>

Promise resolving to the response data

Example
await client.backend.delete('/cache/clear')
download()
download(
   path, 
   method, 
   body?, 
headers?): Promise<Response>;

Downloads a file or binary data from your game's backend. Returns the raw Response object, allowing you to access blobs, streams, or other binary data.

Parameters
path

string

The API route path (e.g., '/files/download' or 'files/download')

method

Method = 'GET'

HTTP method (defaults to GET)

body?

unknown

Optional request body

headers?

Record<string, string>

Optional additional headers

Returns

Promise<Response>

Promise resolving to the raw fetch Response

Example
// Download a file
const response = await client.backend.download('/files?key=my-file.pdf')
const blob = await response.blob()
const url = URL.createObjectURL(blob)

// Download with POST and custom headers
const response = await client.backend.download('/files/export', 'POST',
    { format: 'pdf' },
    { 'Accept': 'application/pdf' }
)
get()
get<T>(path, headers?): Promise<T>;

Makes a GET request to your game's backend.

Type Parameters
T

T = unknown

Parameters
path

string

The API route path (e.g., '/hello' or 'hello')

headers?

Record<string, string>

Optional additional headers

Returns

Promise<T>

Promise resolving to the response data

Example
const data = await client.backend.get('/hello')
console.log(data.message)
patch()
patch<T>(
   path, 
   body?, 
headers?): Promise<T>;

Makes a PATCH request to your game's backend.

Type Parameters
T

T = unknown

Parameters
path

string

The API route path (e.g., '/profile' or 'profile')

body?

unknown

The request body data

headers?

Record<string, string>

Optional additional headers

Returns

Promise<T>

Promise resolving to the response data

Example
const result = await client.backend.patch('/profile', {
    displayName: 'NewName'
})
post()
post<T>(
   path, 
   body?, 
headers?): Promise<T>;

Makes a POST request to your game's backend.

Type Parameters
T

T = unknown

Parameters
path

string

The API route path (e.g., '/save' or 'save')

body?

unknown

The request body data

headers?

Record<string, string>

Optional additional headers

Returns

Promise<T>

Promise resolving to the response data

Example
const result = await client.backend.post('/save', {
    level: 5,
    score: 1000
})
put()
put<T>(
   path, 
   body?, 
headers?): Promise<T>;

Makes a PUT request to your game's backend.

Type Parameters
T

T = unknown

Parameters
path

string

The API route path (e.g., '/settings' or 'settings')

body?

unknown

The request body data

headers?

Record<string, string>

Optional additional headers

Returns

Promise<T>

Promise resolving to the response data

Example
const result = await client.backend.put('/settings', {
    volume: 0.8
})
request()
request<T>(
   path, 
   method, 
   body?, 
headers?): Promise<T>;

Makes a custom HTTP request to your game's backend. Use this for non-standard HTTP methods or advanced configurations.

Type Parameters
T

T = unknown

Parameters
path

string

The API route path (e.g., '/custom' or 'custom')

method

Method

HTTP method (GET, POST, PUT, DELETE, PATCH, etc.)

body?

unknown

Optional request body

headers?

Record<string, string>

Optional additional headers

Returns

Promise<T>

Promise resolving to the response data

Example
const result = await client.backend.request('/custom', 'OPTIONS')
url()
url(pathOrStrings, ...values): string;

Builds a complete URL to your game's backend route. Useful for embedding backend URLs in HTML elements (img, video, audio, anchor tags).

Supports both regular function call and tagged template literal syntax.

Parameters
pathOrStrings

The API route path as a string, or template strings array

string | TemplateStringsArray

values

...unknown[]

Template literal interpolated values (when using tagged template syntax)

Returns

string

Complete URL to the backend route

Example
// Regular function call
const url1 = client.backend.url('/assets/sprite.png')
const url2 = client.backend.url(`/assets/${fileKey}`)

// Tagged template literal (recommended)
const url3 = client.backend.url`/assets/${fileKey}`

// Use in JSX/HTML elements
const imageUrl = client.backend.url`/assets/${sprite.key}`
const videoUrl = client.backend.url('/videos/intro.mp4')
const downloadUrl = client.backend.url`/downloads/${file.key}`
baseUrl
baseUrl: string;

Defined in: clients/base.ts:34

Inherited from
PlaycademyBaseClient.baseUrl
config
protected config: Partial<ClientConfig>;

Defined in: clients/base.ts:38

Inherited from
PlaycademyBaseClient.config
connectionManager?
protected optional connectionManager: ConnectionManager;

Defined in: clients/base.ts:43

Inherited from
PlaycademyBaseClient.connectionManager
credits
credits: {
  add: (amount) => Promise<number>;
  balance: () => Promise<number>;
  spend: (amount) => Promise<number>;
};

Defined in: clients/public.ts:58

Playcademy Credits (platform currency) management.

  • get() - Get user's credit balance
  • add(amount) - Award credits to user
add()
add: (amount) => Promise<number>;

Adds Playcademy Credits to the user's inventory. This is a convenience method that automatically finds the credits item ID.

Parameters
amount

number

The amount of credits to add (must be positive)

Returns

Promise<number>

Promise resolving to the new total balance

Example
const newBalance = await client.credits.add(100)
console.log('New balance after adding 100 credits:', newBalance)
balance()
balance: () => Promise<number>;

Gets the current balance of Playcademy Credits for the authenticated user. This is a convenience method that finds the primary currency in the user's inventory.

Returns

Promise<number>

Promise resolving to the current credits balance

Example
const balance = await client.credits.balance()
console.log('Current credits:', balance)
spend()
spend: (amount) => Promise<number>;

Spends (removes) Playcademy Credits from the user's inventory. This is a convenience method that automatically finds the credits item ID.

Parameters
amount

number

The amount of credits to spend (must be positive)

Returns

Promise<number>

Promise resolving to the new total balance

Example
const newBalance = await client.credits.spend(50)
console.log('New balance after spending 50 credits:', newBalance)
gameId?
protected optional gameId: string;

Defined in: clients/base.ts:37

Inherited from
PlaycademyBaseClient.gameId
gameUrl?
optional gameUrl: string;

Defined in: clients/base.ts:35

Inherited from
PlaycademyBaseClient.gameUrl
identity
identity: {
  _getContext: () => {
     isInIframe: boolean;
  };
  connect: (options) => Promise<AuthResult>;
};

Defined in: clients/public.ts:26

Connect external identity providers to the user's Playcademy account.

  • connect(provider) - Link Discord, Google, etc. via OAuth popup
_getContext()
_getContext: () => {
  isInIframe: boolean;
};

Internal

Gets the current identity connection context (for internal use).

Returns
{
  isInIframe: boolean;
}
isInIframe
isInIframe: boolean;
connect()
connect: (options) => Promise<AuthResult>;

Connects an external identity provider to the user's Playcademy account.

For games in iframes: Uses popup flow to avoid navigation issues. For standalone apps: Uses redirect flow for traditional OAuth.

Parameters
options

AuthOptions

Connection options including provider and callback URL

Returns

Promise<AuthResult>

Promise resolving to the connection result

Examples
// Connect TimeBack identity
const result = await client.identity.connect({
    provider: AuthProvider.TIMEBACK,
    callbackUrl: 'https://myapp.com/api/auth/callback',
    onStateChange: (state) => {
        console.log('Connection state:', state.message)
    }
})

if (result.success) {
    console.log('Connected as:', result.user.email)
}
// Force popup mode even in standalone context
const result = await client.identity.connect({
    provider: AuthProvider.TIMEBACK,
    callbackUrl: 'https://myapp.com/api/auth/callback',
    mode: 'popup'
})
// Provide custom OAuth configuration for external games
const result = await client.identity.connect({
    provider: AuthProvider.TIMEBACK,
    callbackUrl: 'https://myapp.com/api/auth/callback',
    oauth: {
        clientId: 'my-oauth-client-id',
        // Optional: override default endpoints
        authorizationEndpoint: 'https://custom-idp.com/oauth2/authorize',
        tokenEndpoint: 'https://custom-idp.com/oauth2/token',
        scope: 'openid email profile custom_scope'
    }
})
// The SDK automatically includes Playcademy user ID in the OAuth state
const result = await client.identity.connect({
    provider: AuthProvider.TIMEBACK,
    callbackUrl: 'https://myapp.com/api/auth/callback'
})

// On your server callback, parse the state to get the user ID:
import { PlaycademyClient } from '@playcademy/sdk'

app.get('/api/auth/callback', async (req, res) => {
    const { csrfToken, data } = PlaycademyClient.identity.parseOAuthState(req.query.state)
    const playcademyUserId = data?.playcademy_user_id
    const gameId = data?.game_id

    // Now you can associate the OAuth user with the Playcademy user
    await linkAccounts(oauthUserId, playcademyUserId)
})
initPayload?
protected optional initPayload: InitPayload;

Defined in: clients/base.ts:42

Inherited from
PlaycademyBaseClient.initPayload
internalClientSessionId?
protected optional internalClientSessionId: string;

Defined in: clients/base.ts:40

Inherited from
PlaycademyBaseClient.internalClientSessionId
listeners
protected listeners: EventListeners = {};

Defined in: clients/base.ts:39

Inherited from
PlaycademyBaseClient.listeners
realtime
realtime: {
  token: {
     get: () => Promise<RealtimeTokenResponse>;
  };
};

Defined in: clients/public.ts:70

Realtime multiplayer authentication.

  • getToken() - Get token for WebSocket/realtime connections
token
token: {
  get: () => Promise<RealtimeTokenResponse>;
};

Token sub-namespace for realtime token management

token.get()
get: () => Promise<RealtimeTokenResponse>;

Gets a realtime JWT token for establishing WebSocket connections. This token is used by the platform's multiplayer WebSocket client for authentication.

Returns

Promise<RealtimeTokenResponse>

Promise resolving to token response

Example
// Get a realtime token for WebSocket authentication
const response = await client.realtime.token.get()
console.log('Realtime token:', response.token)

// Token is used internally by websocketStore for multiplayer connections
runtime
runtime: {
  assets: {
     arrayBuffer: (path) => Promise<ArrayBuffer>;
     blob: (path) => Promise<Blob>;
     fetch: (path, options?) => Promise<Response>;
     json: <T>(path) => Promise<T>;
     text: (path) => Promise<string>;
     url: string;
  };
  exit: () => Promise<void>;
  getGameToken: (gameId, options?) => Promise<GameTokenResponse>;
  getListenerCounts: () => Record<string, number>;
  onForceExit: (handler) => void;
  onInit: (handler) => void;
  onOverlay: (handler) => void;
  onPause: (handler) => void;
  onResume: (handler) => void;
  onTokenRefresh: (handler) => void;
  ready: () => void;
  removeAllListeners: () => void;
  removeListener: (eventType, handler) => void;
  sendTelemetry: (data) => void;
};

Defined in: clients/public.ts:35

Game runtime lifecycle and asset loading.

  • exit() - Return to Cademy hub
  • getGameToken() - Get short-lived auth token
  • assets.url(), assets.json(), assets.fetch() - Load game assets
  • on('pause'), on('resume') - Handle visibility changes
assets
assets: {
  arrayBuffer: (path) => Promise<ArrayBuffer>;
  blob: (path) => Promise<Blob>;
  fetch: (path, options?) => Promise<Response>;
  json: <T>(path) => Promise<T>;
  text: (path) => Promise<string>;
  url: string;
};

Static assets sub-namespace. Helper methods for loading static files bundled with your game. Use these for runtime asset loading that Vite can't analyze at build time.

assets.arrayBuffer()
arrayBuffer: (path) => Promise<ArrayBuffer>;

Fetches a file from the CDN as an ArrayBuffer.

Parameters
path

string

Relative path to the file

Returns

Promise<ArrayBuffer>

Promise resolving to an ArrayBuffer

Example
// Load binary data
const buffer = await client.runtime.assets.arrayBuffer('assets/data.bin')

// Load WebAssembly module
const wasmBuffer = await client.runtime.assets.arrayBuffer('game.wasm')
const module = await WebAssembly.compile(wasmBuffer)
assets.blob()
blob: (path) => Promise<Blob>;

Fetches a file from the CDN as a Blob.

Parameters
path

string

Relative path to the file

Returns

Promise<Blob>

Promise resolving to a Blob

Example
// Load image as blob
const imageBlob = await client.runtime.assets.blob('images/hero.png')
const objectUrl = URL.createObjectURL(imageBlob)
img.src = objectUrl
assets.fetch()
fetch: (path, options?) => Promise<Response> = fetchAsset;

Fetches a static asset from the game deployment.

Internal fetch helper used by json, blob, text, arrayBuffer methods.

Parameters
path

string

options?

RequestInit

Returns

Promise<Response>

Param

Relative path to the asset

Param

Optional fetch options

Returns

Promise resolving to the fetch Response

Example
const response = await client.runtime.assets.fetch('data/config.json')
const data = await response.json()
assets.json()
json: <T>(path) => Promise<T>;

Fetches and parses a JSON file from the CDN.

Type Parameters
T

T = unknown

Parameters
path

string

Relative path to the JSON file

Returns

Promise<T>

Promise resolving to the parsed JSON data

Example
// Load dynamic level data
const levelData = await client.runtime.assets.json(`levels/level-${id}.json`)
console.log('Level name:', levelData.name)
assets.text()
text: (path) => Promise<string>;

Fetches a text file from the CDN.

Parameters
path

string

Relative path to the text file

Returns

Promise<string>

Promise resolving to the file contents as a string

Example
// Load text data
const story = await client.runtime.assets.text('data/story.txt')
console.log(story)
assets.url()
url(pathOrStrings, ...values): string;

Builds a complete URL to a static asset bundled with your game. Useful for loading files at runtime that Vite can't analyze at build time.

Supports both regular function call and tagged template literal syntax.

Parameters
pathOrStrings

The asset path as a string, or template strings array

string | TemplateStringsArray

values

...unknown[]

Template literal interpolated values (when using tagged template syntax)

Returns

string

Complete URL to the CDN asset

Example
// Regular function call
const url1 = client.runtime.assets.url('levels/level-5.json')
const url2 = client.runtime.assets.url(`badges/${badgeType}.png`)

// Tagged template literal (recommended for dynamic paths)
const url3 = client.runtime.assets.url`levels/level-${levelId}.json`

// Use in JSX/HTML elements
img.src = client.runtime.assets.url`badges/${badgeType}.png`
audio.src = client.runtime.assets.url`sfx/${soundEffect}.wav`
exit()
exit: () => Promise<void>;

Gracefully exits the game runtime. Automatically ends any active game session and emits an exit event.

Returns

Promise<void>

Promise that resolves when exit is complete

Example
// Clean up and exit the game
await client.runtime.exit()
getGameToken()
getGameToken: (gameId, options?) => Promise<GameTokenResponse>;

Retrieves a game token for the specified game. Optionally applies the token to the current client instance.

Parameters
gameId

string

The ID of the game to get a token for

options?

Optional configuration

apply?

boolean

Whether to automatically apply the token to this client

Returns

Promise<GameTokenResponse>

Promise resolving to game token response

Example
// Get token without applying it
const tokenResponse = await client.runtime.getGameToken('game-123')

// Get token and apply it to current client
const tokenResponse = await client.runtime.getGameToken('game-123', { apply: true })
getListenerCounts()
getListenerCounts: () => Record<string, number>;

Gets the count of active listeners for debugging purposes.

Returns

Record<string, number>

Object with listener counts by event type

Example
const counts = client.runtime.getListenerCounts()
console.log(`Active listeners:`, counts)
onForceExit()
onForceExit: (handler) => void;

Listens for force exit events from the parent. Called when the game must terminate immediately (emergency exit).

Parameters
handler

() => void

Function to call when game must force exit

Returns

void

Example
client.runtime.onForceExit(() => {
  game.emergencyCleanup()
  // Game should exit immediately after cleanup
})
onInit()
onInit: (handler) => void;

Listens for game initialization events from the parent. Called when the parent sends initial configuration and auth context.

Parameters
handler

(context) => void

Function to call when initialization occurs

Returns

void

Example
client.runtime.onInit((context) => {
  console.log(`Game ${context.gameId} initialized`)
  console.log(`API base URL: ${context.baseUrl}`)
})
onOverlay()
onOverlay: (handler) => void;

Listens for overlay visibility events from the parent. Called when UI overlays are shown/hidden over the game.

Parameters
handler

(isVisible) => void

Function to call when overlay state changes

Returns

void

Example
client.runtime.onOverlay((isVisible) => {
  if (isVisible) {
    game.showOverlayMode()
  } else {
    game.hideOverlayMode()
  }
})
onPause()
onPause: (handler) => void;

Listens for pause events from the parent. Called when the game should pause execution (e.g., user switches tabs).

Parameters
handler

() => void

Function to call when game should pause

Returns

void

Example
client.runtime.onPause(() => {
  game.pause()
  audioManager.pauseAll()
})
onResume()
onResume: (handler) => void;

Listens for resume events from the parent. Called when the game should resume execution after being paused.

Parameters
handler

() => void

Function to call when game should resume

Returns

void

Example
client.runtime.onResume(() => {
  game.resume()
  audioManager.resumeAll()
})
onTokenRefresh()
onTokenRefresh: (handler) => void;

Listens for token refresh events from the parent. Called when the parent updates the authentication token.

Parameters
handler

(data) => void

Function to call when token is refreshed

Returns

void

Example
client.runtime.onTokenRefresh(({ token, exp }) => {
  console.log(`Token refreshed, expires at: ${new Date(exp)}`)
  // Token is automatically applied to the client
})
ready()
ready: () => void;

Signals that the game has finished loading and is ready to receive messages. Should be called once after game initialization is complete.

Returns

void

Example
// After game has loaded
await client.runtime.ready()
removeAllListeners()
removeAllListeners: () => void;

Removes all runtime event listeners. Use this for cleanup when the game is shutting down.

Returns

void

Example
// Clean up all runtime listeners before exit
client.runtime.removeAllListeners()
await client.runtime.exit()
removeListener()
removeListener: (eventType, handler) => void;

Removes a specific event listener. Use this to stop listening for specific events.

Parameters
eventType

MessageEvents

The message event type to stop listening for

handler

RuntimeEventHandler

The exact handler function that was registered

Returns

void

Example
const pauseHandler = () => game.pause()
client.runtime.onPause(pauseHandler)

// Later, remove the specific handler
client.runtime.removeListener(MessageEvents.PAUSE, pauseHandler)
sendTelemetry()
sendTelemetry: (data) => void;

Sends performance telemetry data to the parent. Used for monitoring game performance and analytics.

Parameters
data

Performance metrics data

fps

number

Current frames per second

mem

number

Current memory usage in MB

Returns

void

Example
// Send current performance metrics
client.runtime.sendTelemetry({
  fps: game.getCurrentFPS(),
  mem: performance.memory ? performance.memory.usedJSHeapSize / 1024 / 1024 : 0
})
scores
scores: {
  submit: (gameId, score, metadata?) => Promise<ScoreSubmission>;
};

Defined in: clients/public.ts:64

Game score submission and leaderboards.

  • submit(gameId, score, metadata?) - Record a game score
submit()
submit: (gameId, score, metadata?) => Promise<ScoreSubmission>;

Submits a score for a specific game. Note: This still requires a gameId as scores must be associated with a game.

Parameters
gameId

string

The game ID to submit the score for

score

number

The score value to submit

metadata?

Record<string, unknown>

Optional metadata about the score

Returns

Promise<ScoreSubmission>

Promise resolving to the created score record

Example
const scoreRecord = await client.scores.submit('game-123', 1250, {
  level: 5,
  difficulty: 'hard'
})
console.log('Score submitted:', scoreRecord.id)
timeback
timeback: {
  endActivity: (data) => Promise<EndActivityResponse>;
  pauseActivity: () => void;
  resumeActivity: () => void;
  startActivity: (metadata) => void;
  get user(): TimebackUser;
};

Defined in: clients/public.ts:51

TimeBack integration for activity tracking and user context.

User context (cached from init, refreshable):

  • user.role - User's role (student, parent, teacher, etc.)
  • user.enrollments - Courses the player is enrolled in for this game
  • user.organizations - Schools/districts the player belongs to
  • user.fetch() - Refresh user context from server

Activity tracking:

  • startActivity(metadata) - Begin tracking an activity
  • pauseActivity() / resumeActivity() - Pause/resume timer
  • endActivity(scoreData) - Submit activity results to TimeBack
endActivity()
endActivity: (data) => Promise<EndActivityResponse>;

End the current activity and submit results to TimeBack. Calculates duration from startActivity, computes XP based on score and time, and submits both ActivityEvent and TimeSpent events.

Parameters
data

EndActivityScoreData

Score data and optional XP override

Returns

Promise<EndActivityResponse>

Promise resolving to end activity response

Throws

Error if startActivity was not called first

Example
// Auto-calculate XP
await client.timeback.endActivity({
  correctQuestions: 8,
  totalQuestions: 10
})

// Report mastery only
await client.timeback.endActivity({
  correctQuestions: 8,
  totalQuestions: 10,
  masteredUnits: 1
})

// Override XP
await client.timeback.endActivity({
  correctQuestions: 8,
  totalQuestions: 10,
  xpAwarded: 15
})
pauseActivity()
pauseActivity: () => void;

Pause the current activity timer. Paused time is not counted toward the activity duration. Must be called after startActivity and before endActivity.

Returns

void

Throws

Error if no activity is in progress or if already paused

Example
client.timeback.startActivity({ activityId: 'math-quiz-1' })
// ... student starts quiz ...

// Student needs a break
client.timeback.pauseActivity()

// ... student returns ...
client.timeback.resumeActivity()
resumeActivity()
resumeActivity: () => void;

Resume the current activity timer after a pause. Must be called after pauseActivity.

Returns

void

Throws

Error if no activity is in progress or if not currently paused

Example
client.timeback.startActivity({ activityId: 'math-quiz-1' })
client.timeback.pauseActivity()
// ... break time ...
client.timeback.resumeActivity()
// ... student continues quiz ...
startActivity()
startActivity: (metadata) => void;

Start tracking an activity. Stores activity metadata and start time internally. Must be called before endActivity.

Parameters
metadata

ActivityData

Activity metadata (only activityId required)

Returns

void

Example
// Minimal - most common
client.timeback.startActivity({
  activityId: 'level-1-quiz'
})
// Auto-derives: activityName "Level 1 Quiz"

// With custom name override
client.timeback.startActivity({
  activityId: 'level-1-quiz',
  activityName: 'Advanced Arithmetic Challenge'
})
user
Get Signature
get user(): TimebackUser;

TimeBack user context with role, enrollments, and organizations. Access cached data via properties, or call fetch() for fresh data.

Example
// Access cached data (from init)
const role = client.timeback.user.role
const enrollments = client.timeback.user.enrollments

// Fetch fresh data from server (cached for 5 min)
const fresh = await client.timeback.user.fetch()

// Force refresh bypassing cache
const forced = await client.timeback.user.fetch({ force: true })
Returns

TimebackUser

users
users: {
  inventory: {
     add: (identifier, qty) => Promise<InventoryMutationResponse>;
     get: () => Promise<InventoryItemWithItem[]>;
     has: (identifier, minQuantity) => Promise<boolean>;
     quantity: (identifier) => Promise<number>;
     remove: (identifier, qty) => Promise<InventoryMutationResponse>;
  };
  me: () => Promise<AuthenticatedUser>;
};

Defined in: clients/base.ts:380

Current user data and inventory management.

  • me() - Get authenticated user profile
  • inventory.get() - List user's items
  • inventory.add(slug, qty) - Award items to user
inventory
inventory: {
  add: (identifier, qty) => Promise<InventoryMutationResponse>;
  get: () => Promise<InventoryItemWithItem[]>;
  has: (identifier, minQuantity) => Promise<boolean>;
  quantity: (identifier) => Promise<number>;
  remove: (identifier, qty) => Promise<InventoryMutationResponse>;
};

Inventory management methods for the current user.

inventory.add()
add: (identifier, qty) => Promise<InventoryMutationResponse>;

Adds items to the user's inventory. Accepts either an item UUID or slug. Emits an 'inventoryChange' event when successful.

Parameters
identifier

string

The item UUID or slug

qty

number

The quantity to add (must be positive)

Returns

Promise<InventoryMutationResponse>

Promise resolving to mutation response with new total

Example
// Using slug
const result = await client.users.inventory.add('gold-coin', 100)

// Using UUID
const result = await client.users.inventory.add('550e8400-e29b-41d4-a716-446655440000', 100)

console.log('New total:', result.newTotal)
inventory.get()
get: () => Promise<InventoryItemWithItem[]>;

Retrieves the user's complete inventory.

Returns

Promise<InventoryItemWithItem[]>

Promise resolving to array of inventory items with item details

Example
const inventory = await client.users.inventory.get()
inventory.forEach(item => {
  console.log(`${item.item.name}: ${item.quantity}`)
})
inventory.has()
has: (identifier, minQuantity) => Promise<boolean>;

Checks if the user has at least the specified quantity of an item. Accepts either an item UUID or slug.

Parameters
identifier

string

The item UUID or slug

minQuantity

number = 1

Minimum quantity required (defaults to 1)

Returns

Promise<boolean>

Promise resolving to true if user has enough of the item

Example
const hasKey = await client.users.inventory.has('gold-coin')
const hasEnoughGold = await client.users.inventory.has('gold-coin', 100)
const hasPotion = await client.users.inventory.has('uuid-123-456', 5)

if (hasKey && hasEnoughGold) {
  console.log('Can enter premium dungeon!')
}
inventory.quantity()
quantity: (identifier) => Promise<number>;

Gets the current quantity of an item. Accepts either an item UUID or slug.

Parameters
identifier

string

The item UUID or slug

Returns

Promise<number>

Promise resolving to the current quantity (0 if not owned)

Example
const qty = await client.users.inventory.quantity('health-potion')
const qty2 = await client.users.inventory.quantity('uuid-123-456')
console.log('Health potions:', qty)
inventory.remove()
remove: (identifier, qty) => Promise<InventoryMutationResponse>;

Removes items from the user's inventory. Accepts either an item UUID or slug. Emits an 'inventoryChange' event when successful.

Parameters
identifier

string

The item UUID or slug

qty

number

The quantity to remove (must be positive)

Returns

Promise<InventoryMutationResponse>

Promise resolving to mutation response with new total

Example
// Using slug
const result = await client.users.inventory.remove('HEALTH_POTION', 1)

// Using UUID
const result = await client.users.inventory.remove('uuid-456-789', 1)

console.log('Remaining:', result.newTotal)
me()
me: () => Promise<AuthenticatedUser>;

Retrieves the current user's profile information with authentication context.

Returns

Promise<AuthenticatedUser>

Promise resolving to user profile data including auth provider info

Example
const user = await client.users.me()
console.log('Username:', user.username)
console.log('Email:', user.email)
console.log('Has Timeback Account:', user.hasTimebackAccount)
Inherited from
PlaycademyBaseClient.users
identity
static identity: {
  parseOAuthState: (state) => {
     csrfToken: string;
     data?: Record<string, string>;
  };
};

Defined in: clients/public.ts:90

Static identity utilities for OAuth operations

parseOAuthState()
parseOAuthState: (state) => {
  csrfToken: string;
  data?: Record<string, string>;
};

Parses an OAuth state parameter to extract CSRF token and custom data. Use this in your server callback to retrieve the data encoded in the state.

Parses an OAuth state parameter to extract CSRF token and any encoded data.

Parameters
state

string

The OAuth state parameter to parse

Returns
{
  csrfToken: string;
  data?: Record<string, string>;
}

Object containing CSRF token and optional decoded data

csrfToken
csrfToken: string;
data?
optional data: Record<string, string>;
Param

The OAuth state parameter from the callback

Returns

Object containing the CSRF token and optional custom data

Example
// In your server callback endpoint
import { PlaycademyClient } from '@playcademy/sdk'

app.get('/api/auth/callback', async (req, res) => {
    const { csrfToken, data } = PlaycademyClient.identity.parseOAuthState(req.query.state)

    // Validate CSRF token
    if (!isValidCsrf(csrfToken)) {
        return res.status(403).send('Invalid state')
    }

    // Access Playcademy user ID if available
    const playcademyUserId = data?.playcademy_user_id
    const gameId = data?.game_id

    // Exchange code for tokens...
    // Link accounts...
})
init()
static init: <T>(this, options?) => Promise<T>;

Defined in: clients/public.ts:84

Auto-initializes a PlaycademyClient with context from the environment

Auto-initializes a PlaycademyClient with context from the environment. Works in both iframe mode (production/development) and standalone mode (local dev).

This is the recommended way to initialize the SDK as it automatically:

  • Detects the runtime environment (iframe vs standalone)
  • Configures the client with the appropriate context
  • Sets up event listeners for token refresh
  • Exposes the client for debugging in development mode
Type Parameters
T

T extends PlaycademyBaseClient = PlaycademyBaseClient

Parameters
this

(config?) => T

options?

Optional configuration overrides

allowedParentOrigins?

string[]

baseUrl?

string

Override the base URL for API requests

enableConnectionMonitoring?

boolean

onDisconnect?

DisconnectHandler

Returns

Promise<T>

Promise resolving to a fully initialized PlaycademyClient

Throws

Error if not running in a browser context

Example
// Default initialization
const client = await PlaycademyClient.init()

// With custom base URL
const client = await PlaycademyClient.init({ baseUrl: 'https://custom.api.com' })
login()
static login: (baseUrl, email, password) => Promise<LoginResponse>;

Defined in: clients/public.ts:87

Authenticates a user with email and password

Authenticates a user with email and password.

This is a standalone authentication method that doesn't require an initialized client. Use this for login flows before creating a client instance.

Parameters
baseUrl

string

The base URL of the Playcademy API

email

string

User's email address

password

string

User's password

Returns

Promise<LoginResponse>

Promise resolving to authentication response with token

Deprecated

Use client.auth.login() instead for better error handling and automatic token management

Throws

PlaycademyError if authentication fails or network error occurs

Example
// Preferred approach:
const client = new PlaycademyClient({ baseUrl: '/api' })
const result = await client.auth.login({
  email: 'user@example.com',
  password: 'password'
})

// Legacy approach (still works):
try {
  const response = await PlaycademyClient.login('/api', 'user@example.com', 'password')
  const client = new PlaycademyClient({ token: response.token })
} catch (error) {
  console.error('Login failed:', error.message)
}

Methods

_ensureGameId()
protected _ensureGameId(): string;

Defined in: clients/base.ts:295

Ensures a gameId is available, throwing an error if not.

Returns

string

Inherited from
PlaycademyBaseClient._ensureGameId
_setAuthContext()
_setAuthContext(context): void;

Defined in: clients/base.ts:189

Internal

Sets the authentication context for the client.

Parameters
context
isInIframe

boolean

Returns

void

Inherited from
PlaycademyBaseClient._setAuthContext
checkConnection()
checkConnection(): Promise<ConnectionState | "unknown">;

Defined in: clients/base.ts:177

Manually triggers a connection check immediately.

Returns

Promise<ConnectionState | "unknown">

Inherited from
PlaycademyBaseClient.checkConnection
emit()
protected emit<E>(event, payload): void;

Defined in: clients/base.ts:208

Emits an event to all registered listeners.

Type Parameters
E

E extends keyof ClientEvents

Parameters
event

E

payload

ClientEvents[E]

Returns

void

Inherited from
PlaycademyBaseClient.emit
getBaseUrl()
getBaseUrl(): string;

Defined in: clients/base.ts:81

Gets the effective base URL for API requests.

Returns

string

Inherited from
PlaycademyBaseClient.getBaseUrl
getConnectionState()
getConnectionState(): ConnectionState | "unknown";

Defined in: clients/base.ts:170

Gets the current connection state.

Returns

ConnectionState | "unknown"

Inherited from
PlaycademyBaseClient.getConnectionState
getGameBackendUrl()
protected getGameBackendUrl(): string;

Defined in: clients/base.ts:93

Gets the effective game backend URL for integration requests.

Returns

string

Inherited from
PlaycademyBaseClient.getGameBackendUrl
getToken()
getToken(): null | string;

Defined in: clients/base.ts:138

Gets the current authentication token.

Returns

null | string

Inherited from
PlaycademyBaseClient.getToken
getTokenType()
getTokenType(): TokenType;

Defined in: clients/base.ts:131

Gets the current token type.

Returns

TokenType

Inherited from
PlaycademyBaseClient.getTokenType
isAuthenticated()
isAuthenticated(): boolean;

Defined in: clients/base.ts:145

Checks if the client has a valid API token.

Returns

boolean

Inherited from
PlaycademyBaseClient.isAuthenticated
on()
on<E>(event, callback): void;

Defined in: clients/base.ts:200

Registers an event listener for client events.

Type Parameters
E

E extends keyof ClientEvents

Parameters
event

E

callback

(payload) => void

Returns

void

Inherited from
PlaycademyBaseClient.on
onAuthChange()
onAuthChange(callback): void;

Defined in: clients/base.ts:152

Registers a callback to be called when authentication state changes.

Parameters
callback

(token) => void

Returns

void

Inherited from
PlaycademyBaseClient.onAuthChange
onDisconnect()
onDisconnect(callback): () => void;

Defined in: clients/base.ts:159

Registers a callback to be called when connection issues are detected.

Parameters
callback

(context) => void | Promise<void>

Returns
(): void;
Returns

void

Inherited from
PlaycademyBaseClient.onDisconnect
ping()
ping(): string;

Defined in: clients/base.ts:112

Simple ping method for testing connectivity.

Returns

string

Inherited from
PlaycademyBaseClient.ping
request()
protected request<T>(
   path, 
   method, 
options?): Promise<T>;

Defined in: clients/base.ts:221

Makes an authenticated HTTP request to the platform API.

Type Parameters
T

T

Parameters
path

string

method

Method

options?
body?

unknown

headers?

Record<string, string>

raw?

boolean

Returns

Promise<T>

Inherited from
PlaycademyBaseClient.request
requestGameBackend()
protected requestGameBackend<T>(
   path, 
   method, 
   body?, 
   headers?, 
raw?): Promise<T>;

Defined in: clients/base.ts:257

Makes an authenticated HTTP request to the game's backend Worker.

Type Parameters
T

T

Parameters
path

string

method

Method

body?

unknown

headers?

Record<string, string>

raw?

boolean

Returns

Promise<T>

Inherited from
PlaycademyBaseClient.requestGameBackend
setToken()
setToken(token, tokenType?): void;

Defined in: clients/base.ts:123

Sets the authentication token for API requests.

Parameters
token

null | string

tokenType?

TokenType

Returns

void

Inherited from
PlaycademyBaseClient.setToken

PlaycademyError

Defined in: core/errors.ts:4

Base error class for Cademy SDK specific errors.

Extends

  • Error

Constructors

Constructor
new PlaycademyError(message): PlaycademyError;

Defined in: core/errors.ts:5

Parameters
message

string

Returns

PlaycademyError

Overrides
Error.constructor

Interfaces

ApiErrorInfo

Defined in: core/errors.ts:258

Extracted error information for display purposes.

Properties

code
code: string;

Defined in: core/errors.ts:262

API error code

details?
optional details: unknown;

Defined in: core/errors.ts:266

Additional error context

message
message: string;

Defined in: core/errors.ts:264

Human-readable error message

status
status: number;

Defined in: core/errors.ts:260

HTTP status code


ConnectionMonitorConfig

Defined in: core/connection/types.ts:21

Configuration options for ConnectionMonitor.

See

ConnectionMonitor for usage

Properties

baseUrl
baseUrl: string;

Defined in: core/connection/types.ts:23

Base URL for heartbeat pings (e.g., 'https://api.playcademy.com')

enableHeartbeat?
optional enableHeartbeat: boolean;

Defined in: core/connection/types.ts:31

Enable periodic heartbeat monitoring (default: true)

enableOfflineEvents?
optional enableOfflineEvents: boolean;

Defined in: core/connection/types.ts:33

Enable browser online/offline event listeners (default: true)

failureThreshold?
optional failureThreshold: number;

Defined in: core/connection/types.ts:29

Number of consecutive failures before triggering disconnect (default: 2)

heartbeatInterval?
optional heartbeatInterval: number;

Defined in: core/connection/types.ts:25

How often to send heartbeat pings in milliseconds (default: 10000)

heartbeatTimeout?
optional heartbeatTimeout: number;

Defined in: core/connection/types.ts:27

How long to wait for heartbeat response in milliseconds (default: 5000)


ConnectionStatePayload

Defined in: types/events.ts:96

Connection state payload. Broadcast from platform to games when connection changes.

Properties

reason
reason: string;

Defined in: types/events.ts:98

state
state: "online" | "offline" | "degraded";

Defined in: types/events.ts:97


DevUploadHooks

Defined in: namespaces/platform/dev.types.ts:58

Properties

onClose()?
optional onClose: () => void;

Defined in: namespaces/platform/dev.types.ts:60

Returns

void

onEvent()?
optional onEvent: (e) => void;

Defined in: namespaces/platform/dev.types.ts:59

Parameters
e

DevUploadEvent

Returns

void


DisconnectContext

Defined in: types/client.ts:29

Context provided to disconnect handlers

Properties

displayAlert()
displayAlert: (message, options?) => void;

Defined in: types/client.ts:37

Utility to display a platform-level alert

Parameters
message

string

options?
duration?

number

type?

"error" | "info" | "warning"

Returns

void

reason
reason: string;

Defined in: types/client.ts:33

Reason for the disconnect

state
state: "offline" | "degraded";

Defined in: types/client.ts:31

Current connection state

timestamp
timestamp: number;

Defined in: types/client.ts:35

Timestamp when disconnect was detected


DisplayAlertPayload

Defined in: types/events.ts:7

Properties

message
message: string;

Defined in: types/events.ts:8

options?
optional options: {
  duration?: number;
  type?: "error" | "info" | "warning";
};

Defined in: types/events.ts:9

duration?
optional duration: number;
type?
optional type: "error" | "info" | "warning";

ErrorResponseBody

Defined in: core/errors.ts:55

Structure of error response bodies returned by API endpoints.

Example

{
  "error": {
    "code": "NOT_FOUND",
    "message": "Item not found",
    "details": { "identifier": "abc123" }
  }
}

Properties

error?
optional error: {
  code?: string;
  details?: unknown;
  message?: string;
};

Defined in: core/errors.ts:56

code?
optional code: string;
details?
optional details: unknown;
message?
optional message: string;

Type Aliases

ApiErrorCode

type ApiErrorCode = 
  | "BAD_REQUEST"
  | "UNAUTHORIZED"
  | "FORBIDDEN"
  | "ACCESS_DENIED"
  | "NOT_FOUND"
  | "METHOD_NOT_ALLOWED"
  | "CONFLICT"
  | "ALREADY_EXISTS"
  | "GONE"
  | "PRECONDITION_FAILED"
  | "PAYLOAD_TOO_LARGE"
  | "VALIDATION_FAILED"
  | "TOO_MANY_REQUESTS"
  | "RATE_LIMITED"
  | "EXPIRED"
  | "INTERNAL"
  | "INTERNAL_ERROR"
  | "NOT_IMPLEMENTED"
  | "SERVICE_UNAVAILABLE"
  | "TIMEOUT"
  | string;

Defined in: core/errors.ts:15

Error codes returned by the API. These map to specific error types and HTTP status codes.


ConnectionState

type ConnectionState = "online" | "offline" | "degraded";

Defined in: core/connection/types.ts:14

Possible connection states.

  • online: Connection is stable and healthy
  • offline: Complete loss of network connectivity
  • degraded: Connection is slow or experiencing intermittent issues

DevUploadEvent

type DevUploadEvent = 
  | {
  type: "init";
}
  | {
  loaded: number;
  percent: number;
  total: number;
  type: "s3Progress";
}
  | {
  type: "finalizeStart";
}
  | {
  currentFileLabel?: string;
  percent: number;
  type: "finalizeProgress";
}
  | {
  message: string;
  type: "finalizeStatus";
}
  | {
  type: "complete";
}
  | {
  type: "close";
};

Defined in: namespaces/platform/dev.types.ts:49


DisconnectHandler()

type DisconnectHandler = (context) => void | Promise<void>;

Defined in: types/client.ts:24

Handler called when connection state changes to offline or degraded. Games can implement this to handle disconnects gracefully.

Parameters

context

DisconnectContext

Returns

void | Promise<void>

Variables

messaging

const messaging: PlaycademyMessaging;

Defined in: messaging.ts:809

Playcademy Messaging Singleton

This is the main messaging instance used throughout the Playcademy platform. It's exported as a singleton to ensure consistent communication across all parts of the application.

Why a Singleton?:

  • Ensures all parts of the app use the same messaging instance
  • Prevents conflicts between multiple messaging systems
  • Simplifies the API - no need to pass instances around
  • Maintains consistent event listener management

Usage in Different Contexts:

In Games:

import { messaging, MessageEvents } from '@playcademy/sdk'

// Tell parent we're ready
messaging.send(MessageEvents.READY, undefined)

// Listen for pause/resume
messaging.listen(MessageEvents.PAUSE, () => game.pause())
messaging.listen(MessageEvents.RESUME, () => game.resume())

In Parent Shell:

import { messaging, MessageEvents } from '@playcademy/sdk'

// Send initialization data to game
messaging.send(MessageEvents.INIT, { baseUrl, token, gameId })

// Listen for game events
messaging.listen(MessageEvents.EXIT, () => closeGame())
messaging.listen(MessageEvents.READY, () => showGame())

Automatic Transport Selection: The messaging system automatically chooses the right transport method:

  • Uses postMessage when game is in iframe sending to parent
  • Uses CustomEvent for local development and parent-to-game communication

Type Safety: All message sending and receiving is fully type-safe with TypeScript.

Functions

extractApiErrorInfo()

function extractApiErrorInfo(error): null | ApiErrorInfo;

Defined in: core/errors.ts:285

Extract useful error information from an API error. Useful for displaying errors to users in a friendly way.

Parameters

error

unknown

Returns

null | ApiErrorInfo

Example

try {
  await client.shop.purchase(itemId)
} catch (error) {
  const info = extractApiErrorInfo(error)
  if (info) {
    showToast(`Error: ${info.message}`)
  }
}

On this page

@playcademy/sdk
Overview
Public vs Internal SDK
Public SDK (@playcademy/sdk)
Internal SDK (@playcademy/sdk/internal)
Key Benefits
Use Cases
Connection Monitoring
Installation
Quick Start
Automatic Initialization (Recommended)
Environment Detection
Core Features
Game Session Management
User & Inventory Management
Credits & Currency
Experience & Levels
TimeBack Integration
Real-time Authentication
API Reference
Core Modules
Authentication (client.auth)
Users (client.users)
Games (client.games)
Credits (client.credits)
Levels (client.levels)
Maps (client.maps)
Runtime (client.runtime)
Real-time (client.realtime)
TimeBack (client.timeback)
Leaderboard (client.leaderboard) - Game-specific
Scores (client.scores) - Platform-wide
Developer Tools
Developer Authentication (client.dev.auth)
Game Management (client.dev.games)
API Keys (client.dev.keys)
Item Management (client.dev.items)
Event System
Available Events
Disconnect Handling
Event-Driven UI Updates
Advanced Usage
Manual Initialization
Custom Configuration
Error Handling
Development Environment
Integration with Playcademy Vite Plugin
Manual Sandbox Setup
Best Practices
Initialization & Setup
State Management
Performance Optimization
Error Handling
Development Workflow
Testing
Unit Testing
Integration Testing
Troubleshooting
Common Issues
Debugging
Contributing
Enumerations
MessageEvents
Enumeration Members
AUTH_CALLBACK
AUTH_STATE_CHANGE
CONNECTION_STATE
DISPLAY_ALERT
EXIT
FORCE_EXIT
INIT
KEY_EVENT
OVERLAY
PAUSE
READY
RESUME
TELEMETRY
TOKEN_REFRESH
Classes
ApiError
Example
Extends
Constructors
Constructor
Parameters
status
code
message
details?
rawBody?
Returns
Overrides
Properties
code
details
rawBody
status
Methods
is()
Parameters
code
Returns
Example
isClientError()
Returns
isRetryable()
Returns
isServerError()
Returns
fromResponse()
Parameters
status
statusText
body
Returns
ConnectionManager
See
Constructors
Constructor
Parameters
config
Returns
Example
Methods
checkNow()
Returns
Example
getState()
Returns
Example
onDisconnect()
Parameters
callback
Returns
Returns
Example
reportRequestFailure()
Parameters
error
Returns
reportRequestSuccess()
Returns
stop()
Returns
ConnectionMonitor
Example
See
Constructors
Constructor
Parameters
config
Returns
Methods
checkNow()
Returns
Example
getState()
Returns
onChange()
Parameters
callback
Returns
Returns
Example
reportRequestFailure()
Parameters
error
Returns
Example
reportRequestSuccess()
Returns
Example
start()
Returns
stop()
Returns
PlaycademyClient
Extends
Constructors
Constructor
Parameters
config?
Returns
Inherited from
Properties
authContext?
isInIframe
Inherited from
authStrategy
Inherited from
backend
delete()
Type Parameters
T
Parameters
path
headers?
Returns
Example
download()
Parameters
path
method
body?
headers?
Returns
Example
get()
Type Parameters
T
Parameters
path
headers?
Returns
Example
patch()
Type Parameters
T
Parameters
path
body?
headers?
Returns
Example
post()
Type Parameters
T
Parameters
path
body?
headers?
Returns
Example
put()
Type Parameters
T
Parameters
path
body?
headers?
Returns
Example
request()
Type Parameters
T
Parameters
path
method
body?
headers?
Returns
Example
url()
Parameters
pathOrStrings
values
Returns
Example
baseUrl
Inherited from
config
Inherited from
connectionManager?
Inherited from
credits
add()
Parameters
amount
Returns
Example
balance()
Returns
Example
spend()
Parameters
amount
Returns
Example
gameId?
Inherited from
gameUrl?
Inherited from
identity
_getContext()
Returns
isInIframe
connect()
Parameters
options
Returns
Examples
initPayload?
Inherited from
internalClientSessionId?
Inherited from
listeners
Inherited from
realtime
token
token.get()
Returns
Example
runtime
assets
assets.arrayBuffer()
Parameters
path
Returns
Example
assets.blob()
Parameters
path
Returns
Example
assets.fetch()
Parameters
path
options?
Returns
Param
Param
Returns
Example
assets.json()
Type Parameters
T
Parameters
path
Returns
Example
assets.text()
Parameters
path
Returns
Example
assets.url()
Parameters
pathOrStrings
values
Returns
Example
exit()
Returns
Example
getGameToken()
Parameters
gameId
options?
apply?
Returns
Example
getListenerCounts()
Returns
Example
onForceExit()
Parameters
handler
Returns
Example
onInit()
Parameters
handler
Returns
Example
onOverlay()
Parameters
handler
Returns
Example
onPause()
Parameters
handler
Returns
Example
onResume()
Parameters
handler
Returns
Example
onTokenRefresh()
Parameters
handler
Returns
Example
ready()
Returns
Example
removeAllListeners()
Returns
Example
removeListener()
Parameters
eventType
handler
Returns
Example
sendTelemetry()
Parameters
data
fps
mem
Returns
Example
scores
submit()
Parameters
gameId
score
metadata?
Returns
Example
timeback
endActivity()
Parameters
data
Returns
Throws
Example
pauseActivity()
Returns
Throws
Example
resumeActivity()
Returns
Throws
Example
startActivity()
Parameters
metadata
Returns
Example
user
Get Signature
Example
Returns
users
inventory
inventory.add()
Parameters
identifier
qty
Returns
Example
inventory.get()
Returns
Example
inventory.has()
Parameters
identifier
minQuantity
Returns
Example
inventory.quantity()
Parameters
identifier
Returns
Example
inventory.remove()
Parameters
identifier
qty
Returns
Example
me()
Returns
Example
Inherited from
identity
parseOAuthState()
Parameters
state
Returns
csrfToken
data?
Param
Returns
Example
init()
Type Parameters
T
Parameters
this
options?
allowedParentOrigins?
baseUrl?
enableConnectionMonitoring?
onDisconnect?
Returns
Throws
Example
login()
Parameters
baseUrl
email
password
Returns
Deprecated
Throws
Example
Methods
_ensureGameId()
Returns
Inherited from
_setAuthContext()
Parameters
context
isInIframe
Returns
Inherited from
checkConnection()
Returns
Inherited from
emit()
Type Parameters
E
Parameters
event
payload
Returns
Inherited from
getBaseUrl()
Returns
Inherited from
getConnectionState()
Returns
Inherited from
getGameBackendUrl()
Returns
Inherited from
getToken()
Returns
Inherited from
getTokenType()
Returns
Inherited from
isAuthenticated()
Returns
Inherited from
on()
Type Parameters
E
Parameters
event
callback
Returns
Inherited from
onAuthChange()
Parameters
callback
Returns
Inherited from
onDisconnect()
Parameters
callback
Returns
Returns
Inherited from
ping()
Returns
Inherited from
request()
Type Parameters
T
Parameters
path
method
options?
body?
headers?
raw?
Returns
Inherited from
requestGameBackend()
Type Parameters
T
Parameters
path
method
body?
headers?
raw?
Returns
Inherited from
setToken()
Parameters
token
tokenType?
Returns
Inherited from
PlaycademyError
Extends
Constructors
Constructor
Parameters
message
Returns
Overrides
Interfaces
ApiErrorInfo
Properties
code
details?
message
status
ConnectionMonitorConfig
See
Properties
baseUrl
enableHeartbeat?
enableOfflineEvents?
failureThreshold?
heartbeatInterval?
heartbeatTimeout?
ConnectionStatePayload
Properties
reason
state
DevUploadHooks
Properties
onClose()?
Returns
onEvent()?
Parameters
e
Returns
DisconnectContext
Properties
displayAlert()
Parameters
message
options?
duration?
type?
Returns
reason
state
timestamp
DisplayAlertPayload
Properties
message
options?
duration?
type?
ErrorResponseBody
Example
Properties
error?
code?
details?
message?
Type Aliases
ApiErrorCode
ConnectionState
DevUploadEvent
DisconnectHandler()
Parameters
context
Returns
Variables
messaging
Functions
extractApiErrorInfo()
Parameters
error
Returns
Example