Account Transfer

Move an anonymous save with a short-lived code.

Transfer codes let a player attach the same Persistly account on another browser or device without adding full authentication. They are temporary, single-use, and still use the normal account session model after transfer.

Flow

The original device creates the code; the new device consumes it.

This keeps recovery explicit. Persistly never exposes public account lookup by playerRef or externalAccountRef.

01

Device A already has a Persistly account session from normal save sync.

02

The game calls createTransferCode when the player asks to move the save.

03

Persistly returns a short-lived one-time code and an expiry time.

04

Device B consumes the code and receives a new accountSessionToken for the same account.

05

The SDK attaches that account, then the game loads or refreshes slots through the normal save APIs.

Boundaries

Treat transfer codes like temporary save-access keys.

They are useful for no-login games, but they are not a replacement for a trusted account system.

Transfer codes are for anonymous device transfer, not sign-in, usernames, email login, or social auth.

A code is short-lived and single-use. Anyone with the active code can attach the save until it expires.

Creating a code requires the original device to already have accountId and accountSessionToken.

Consuming a code does not use playerRef, externalAccountRef, username, or public account lookup.

If local account/session data is already present on Device B, clear or switch local account state intentionally before attaching.

JavaScript

Create and consume a transfer code through the facade.

Use this for browser games that want a simple move-to-another-device screen.

TYPESCRIPT
// Device A: show this code to the player.
const transfer = await PersistlyGameSaves.shared.createTransferCode();
showTransferCode(transfer.transferCode, transfer.expiresAt);

// Device B: attach the same Persistly account.
await PersistlyGameSaves.shared.attachWithTransferCode(playerEnteredCode);
const loaded = await PersistlyGameSaves.shared.loadData();

Unity

Use the same flow from Unity.

Unity method names stay idiomatic, but the product model is the same.

C#
// Device A
var transfer = await PersistlyGameSaves.Shared.CreateTransferCodeAsync();
ShowTransferCode(transfer.TransferCode, transfer.ExpiresAt);

// Device B
await PersistlyGameSaves.Shared.AttachWithTransferCodeAsync(playerEnteredCode);
var loaded = await PersistlyGameSaves.Shared.LoadDataAsync<PlayerState>();

Godot

Use the same flow from Godot.

Godot keeps snake_case helper names while using the same runtime routes.

GDSCRIPT
# Device A
var transfer := await PersistlyGameSaves.create_transfer_code()
show_transfer_code(transfer["transferCode"], transfer["expiresAt"])

# Device B
await PersistlyGameSaves.attach_with_transfer_code(player_entered_code)
var loaded := await PersistlyGameSaves.load_data()