Simple Game Saves

Start with one save. Add slots and accounts when the game needs them.

PersistlyGameSaves gives game developers saveData/loadData for one-save games, saveSlot/loadSlot/listSlots for multi-save games, and accountData helpers for account-wide shared data. Under the hood, Persistly hides internal save ids behind account, session, slotInfo, and data facades.

Account Shape

The account stores accountData and slot references.

Use accountData for shared player data. Use slotInfo for preview and selection data. Use slot data for full playable progress.

JAVASCRIPT
type PersistlyAccountData = {
  schema: "persistly.account.v1";
  accountData: JsonObject;
  slots: Array<{
    slotId: string;
    slotInfo: JsonObject;
    archived?: boolean;
    archivedAt?: string;
  }>;
};

Rules

Simple data is the first path; slots and accounts are the growth path.

The facade avoids unsafe public lookup by userId while still letting games model one account with many slots. Advanced integrations can use account-scoped slot routes directly.

PersistlyGameSaves creates the remote account and slots on first sync, so beginner game code can start with saveData/loadData and grow into named slots when needed.

Anonymous games can use the flow as-is because the facade stores accountId, accountSessionToken, and slot references locally.

Games with their own auth can send a non-secret externalAccountRef such as provider plus subject for bookkeeping, but Persistly does not validate provider tokens in the public runtime API.

accountId is the permanent handle for the player account. The game must persist it locally or in its own backend.

accountSessionToken is required to load the account and create/load/sync account-owned slots.

Each slot is addressed through its stable slotId.

clearLocalAccount is local-only. archiveSlot retires an active slot. deleteSlot and deleteAccount are permanent erasure flows.

playerRef and externalAccountRef are non-authoritative references. They are stored for future trusted flows, not public lookup.

Normal game integrations should use account-scoped slot routes and keep internal save handles behind the SDK/API facade.

Recovery Boundary

Local slots are not cross-device account recovery by themselves.

Persistly can support anonymous games and games with external accounts, but the public runtime API does not expose public lookup by playerRef or externalAccountRef.

Runtime keys identify the environment for SDK traffic. They are not privileged admin credentials.

Account sessions authorize one account and its named slots. Store accountSessionToken like player save data, not like a public lookup value.

Clients should never use runtime keys to discover arbitrary accounts or saves by playerRef.

Trusted lookup by external auth provider belongs to future server-side/operator flows, not the public runtime API.

If an anonymous game still has a valid account session on one device, it can create a short-lived transfer code for another device.

If an anonymous game loses every account session, Persistly cannot safely recover that account from the public runtime API.

If your game already has accounts, store accountId and accountSessionToken in your trusted backend keyed by your authenticated user.

Username lookup, playerRef lookup, external provider token exchange, and Persistly-owned Auth are separate future layers.

JavaScript Example

Use the facade for accountData and slots.

The facade stores the session locally. If your game supports account login, export the account session and store it in your trusted backend for restore on another device.

JAVASCRIPT
import { PersistlyGameSaves } from "@persistlyapp/sdk";

await PersistlyGameSaves.configure({
  runtimeKey: process.env.NEXT_PUBLIC_PERSISTLY_RUNTIME_KEY!,
  playerRef: "player-184", // optional non-secret reference
  externalAccountRef: {
    provider: "auth0",
    subject: "auth0|user_123"
  },
});

// Account-wide gameplay data lives on the account.
await PersistlyGameSaves.shared.saveAccountData({
  diamonds: 1200,
  battlePassTier: "silver",
});

// Slot-specific progress lives in a named slot.
await PersistlyGameSaves.shared.saveSlot("mage", {
  checkpoint: "vault",
  level: 5,
}, {
  slotInfo: { characterName: "Ayla", slotLabel: "Mage" },
});

// First sync creates the account and the mage slot if needed.
await PersistlyGameSaves.shared.forceSync("mage");
await PersistlyGameSaves.shared.forceSyncAccount();

// Store this in your trusted backend if your game supports account login.
const session = await PersistlyGameSaves.shared.getAccountSession({
  includeToken: true,
});

Multiple Slots

Use accountData for account-wide state and slot data for playable progress.

JavaScript account-wide helpers include saveAccountData, patchAccountData, and local account-data inspection. Unity and Godot expose the same account-data path with idiomatic method names.

Use data.accountData for account-wide gameplay data such as tutorial flags, premium currency balances, unlocked account features, or shared settings.

Use slot data for slot-specific progress, inventory, checkpoints, equipment, and quest data.

Use account slotInfo only for small display or routing hints; keep gameplay authority inside data.

If you add a new slot later, create it through the account slot route so Persistly maintains slots.

Archive Semantics

Archive retired slots instead of deleting account history.

Archive keeps the account model safe for simple games and multi-slot games: the old slot can remain recoverable, while the visible slotId can be reused for a new slot.

Archive a slot when the player deletes or retires a slot; do not hard-delete it from the account in shipped clients.

Archived slots are retired from the active slot list and cannot be synced through the normal slot sync route.

Archiving frees the slotId so the player can create a new slot in the same visible slot later.

Full cloud/local slot comparison UI, provider-token recovery, username lookup, and Persistly-owned Auth are future layers, not required for this release.

Payment Boundary

Premium currency can be stored as gameplay state, but payments must be verified elsewhere.

Persistly save state is client-writable unless your game adds a trusted validation flow. Do not treat account data as a payment system.

AccountData is client-writable save data, not a trusted payment ledger.

Persistly may store derived gameplay values such as diamonds: 1200 after the game owner has verified a purchase elsewhere.

Purchases must be validated through a trusted Stripe, App Store, Google Play, Steam, or backend-owned flow before updating save data.

Do not store card data, raw receipts, payment transactions, invoices, or billing history in Persistly account data.