Reference documentation

Runtime Reference

Playdrop runtime docs explain what a hosted app gets from the platform after it launches.

Updated April 6, 2026

Runtime Reference

Playdrop runtime docs explain what a hosted app gets from the platform after it launches.

This page is organized by creator-facing surfaces:

  • lifecycle
  • identity
  • multiplayer
  • monetization
  • assets at runtime
  • AI generation at runtime
  • meta, meaning achievements and leaderboards
  • shared runtime libraries

Use this page when you want to answer:

  • what Playdrop provides inside the host
  • which APIs a hosted app can call
  • what the app still owns itself

Lifecycle

Use the lifecycle surface to understand how Playdrop boots, pauses, resumes, and hosts your app.

Load the public SDK loader, then initialize inside your app:

html example

<script src="https://assets.playdrop.ai/sdk/playdrop.js"></script>

ts example

const sdk = await playdrop.init();

Lifecycle gives you:

  • host handshake
  • app readiness
  • preview and play phases
  • pause and resume
  • audio and controller state
  • app metadata such as auth mode

Minimum working example

ts example

const sdk = await playdrop.init();
sdk.host.ready();

console.log("audio enabled", sdk.host.audioEnabled);

sdk.host.onPause((reason) => {
  console.log("paused", reason);
});

sdk.host.onResume((reason) => {
  console.log("resumed", reason);
});

sdk.host.onAudioPolicyChange(({ enabled, reason }) => {
  console.log("audio policy", enabled, reason);
});

Use sdk.host for host lifecycle and audio policy.

  • sdk.host.audioEnabled tells you whether host audio is currently allowed.
  • sdk.host.onPause(...) and sdk.host.onResume(...) report host pause state changes.
  • sdk.host.onAudioPolicyChange(...) reports audio policy changes from the host.
  • sdk.app remains the app metadata surface, for example authMode, type, and display metadata.

Identity

Use the identity surface when your app needs player profile data, auth state, avatar information, or app-scoped save data.

Identity gives you:

  • login state
  • username and display profile data
  • avatar and creator/player identity context
  • app-scoped save data

ts example

const sdk = await playdrop.init();

console.log(sdk.me.username);
console.log(sdk.me.displayName);
console.log(sdk.me.avatarUrl);
console.log(sdk.me.isLoggedIn);

Prompt login only when it fits your contract:

ts example

if (sdk.app.authMode === "OPTIONAL" && !sdk.me.isLoggedIn) {
  await sdk.me.promptLogin();
}

Save app data:

ts example

await sdk.me.appData.set("profile", {
  level: 12,
  coins: 480,
});

const profile = await sdk.me.appData.get("profile");

Multiplayer

Playdrop multiplayer is room-based. The public runtime surface focuses on players, room data, events, and binary events.

You do not need ECS knowledge to use this layer.

Multiplayer gives you:

  • room join and leave
  • current room users
  • room data updates
  • event messages
  • binary events for compact high-frequency payloads

ts example

const sdk = await playdrop.init();
const room = await sdk.me.joinRoom();

room.onUsersChange((users) => {
  console.log(users.map((user) => user.username));
});

room.onEvent("chat", (event) => {
  console.log(event.payload);
});

await room.sendEvent("chat", { message: "hello" });
await room.updateRoomData({ state: "ready" });

Monetization

Use the monetization surface when your app needs Playdrop-managed purchases, creator ads, and receipt-aware flows.

Monetization gives you:

  • product and price lookup through the Playdrop shop surface
  • purchase flow hooks
  • first-party interstitial and rewarded ads
  • purchase state integration with the host lifecycle
  • receipt and entitlement-aware app behavior

Shop purchases:

ts example

const sdk = await playdrop.init();

const catalog = await sdk.shop.listProducts();
const product = catalog.find((item) => item.key === "starter_pack");

if (product) {
  const result = await sdk.shop.purchase(product.key);
  console.log(result.status);
}

Ads:

ts example

const sdk = await playdrop.init();

const interstitialLoad = await sdk.ads.interstitial.load();
if (interstitialLoad.status === "ready") {
  const interstitial = await sdk.ads.interstitial.show();
  console.log(interstitial.status);
}

const rewardedLoad = await sdk.ads.rewarded.load();
if (rewardedLoad.status === "ready") {
  const rewarded = await sdk.ads.rewarded.show();
  if (rewarded.status === "completed") {
    console.log("grant your in-game reward");
  }
}

Ad load can return:

  • ready
  • no_fill
  • rate_limited
  • blocked

Ad show can return:

  • interstitial: dismissed, not_ready, expired
  • rewarded: completed, dismissed, not_ready, expired

The host decides whether a rewarded ad fully completed. Your app only receives the final result.

Assets at Runtime

Hosted apps can inspect and use catalogue content again at runtime.

This is where catalogue and runtime connect directly.

Assets at runtime gives you:

  • category and taxonomy lookup
  • public and creator asset listing
  • asset detail lookup
  • version browsing
  • file and source downloads
  • pack lookup
  • creator mutation helpers when the authenticated workflow allows it

Browse and inspect content:

ts example

const sdk = await playdrop.init();

const categories = await sdk.assets.catalog.listCategories();
const publicAssets = await sdk.assets.catalog.listPublic({ limit: 10 });
const creatorAssets = await sdk.assets.catalog.listForCreator("playdrop", { limit: 10 });
const asset = await sdk.assets.catalog.get("playdrop", "sample-asset");
const versions = await sdk.assets.catalog.listVersions("playdrop", "sample-asset", { limit: 5 });

Load asset files:

ts example

const fileBlob = await sdk.assets.catalog.downloadFile("playdrop", "sample-asset", 2, { role: "primary" });
const sourceBundle = await sdk.assets.catalog.downloadSource("playdrop", "sample-asset", 2);

Use creator mutations only when the running environment and account permissions allow it:

ts example

await sdk.assets.catalog.update("sample-asset", { displayName: "Sample Asset v2" });
await sdk.assets.catalog.updateVersion("sample-asset", 2, { visibility: "PUBLIC", setAsCurrent: true });
await sdk.assets.packs.update("starter-pack", { displayName: "Starter Pack v2" });

AI Generation

Use the AI runtime surface when a hosted app or creator tool needs Playdrop-managed generation jobs for images, music, SFX, video, or 3D assets.

AI generation gives you:

  • creation of generation jobs
  • polling and result lookup
  • attachment to catalogue content workflows
  • consistent platform billing and generation handling

ts example

const sdk = await playdrop.init();

const job = await sdk.ai.assets.createGenerationJob({
  modality: "IMAGE",
  inputPrompt: "Pixel-art knight portrait",
  aspectRatio: "1:1",
  assetVisibility: "PUBLIC",
  assetSubcategory: "generic",
});

const result = await sdk.ai.assets.getGenerationJob(job.id);
console.log(result.status);

Meta

Meta features cover achievements and leaderboards.

These are first-class platform surfaces and should be documented as such, not hidden inside generic SDK language.

Meta gives you:

  • achievement definitions published with the app
  • achievement progress and completion APIs
  • leaderboard submission and read APIs
  • platform-consistent player meta display values

Achievements:

ts example

const sdk = await playdrop.init();

await sdk.achievements.unlock("first_finish");
await sdk.achievements.setProgressAtLeast("coin_collector", 5);

const achievements = await sdk.achievements.list();
console.log(achievements.length);

Leaderboards:

ts example

const sdk = await playdrop.init();

await sdk.leaderboards.submitScore("fastest_lap", 61_543);

const board = await sdk.leaderboards.get("fastest_lap", { top: 10 });
console.log(board.entries[0]?.scoreDisplay);

Achievement and leaderboard definitions belong in the app publish contract inside Catalogue JSON.

Shared Libraries

Playdrop also exposes shared runtime libraries that a hosted app can load from the SDK-pinned environment.

Shared libraries give you:

  • SDK-pinned three
  • SDK-pinned rapier
  • SDK-pinned nipplejs

ts example

const sdk = await playdrop.init();

const three = await sdk.libs.three.load({
  addons: ["loaders/GLTFLoader.js", "controls/OrbitControls.js"],
});
const rapier = await sdk.libs.rapier.load();
const nipplejs = await sdk.libs.nipplejs.load();

console.log(sdk.libs.three.info());
console.log(three.GLTFLoader, rapier.init, nipplejs.create);

Platform Boundary

Playdrop owns the host shell, runtime handshake, canonical player identity, app-scoped storage primitives, room transport, purchase flow, generation jobs, and pinned runtime library delivery.

Your app still owns gameplay rules, scene graph, authority model, prompt strategy, unlock semantics, custom backend behavior, and how all of these platform signals become product behavior.