Skip to main content

Storage

Persist player data scoped to game ID and authenticated user. Supports cloud and local modes.

Storage Modes

ModeCross-deviceAuth requiredOffline
cloud (default)YesJWT + game-idNo
localNoNoYes

Set default mode via HyveSdkProvider config or at runtime:

// Via provider
<HyveSdkProvider config={{ storageMode: 'local' }}>

// At runtime
hyve.configureStorage('cloud');
hyve.getStorageMode(); // 'cloud' | 'local'

CRUD

// Save — uses default storage mode
await hyve.saveGameData('high_score', 1500);

// Save to specific mode
await hyve.saveGameData('settings', { volume: 0.8 }, undefined, undefined, 'local');

// Get — returns null if key never saved
const data = await hyve.getGameData('high_score');
// { key, value, created_at, updated_at } | null

// Delete — returns true if key existed
await hyve.deleteGameData('high_score');

Atomic Operations

Read-modify-write server-side in a single call. Avoids race conditions.

saveGameData(key, value, operation?, path?, storage?): Promise<SaveGameDataResponse>
// operation: 'set' | 'add' | 'subtract' | 'multiply' | 'divide' | 'modulo' | 'min' | 'max' | 'append'
// path: dot-notation up to 5 levels deep (e.g. 'stats.score')
await hyve.saveGameData('score', 100, 'add');                        // top-level add
await hyve.saveGameData('stats', 100, 'add', 'score'); // nested: stats.score += 100
await hyve.saveGameData('stats', 9999, 'max', 'high_score'); // keep higher value
await hyve.saveGameData('achievements', 'badge_gold', 'append'); // push to array

const res = await hyve.saveGameData('score', 500, 'add');
console.log(res.result); // new value after operation
OperationBehavior
setFull replace (default)
addNumeric addition
subtractNumeric subtraction
multiplyNumeric multiplication
divideNumeric division (float result)
moduloNumeric remainder
minKeep the smaller value
maxKeep the larger value
appendAppend to a JSON array

Batch Operations

// Save multiple
await hyve.batchSaveGameData([
{ key: 'level', value: 5 },
{ key: 'score', value: 1000, operation: 'add' },
{ key: 'achievements', value: 'badge_1', operation: 'append' },
]);

// Per-item results when any item uses an operation
const res = await hyve.batchSaveGameData([...]);
for (const item of res.results ?? []) {
if (item.success) console.log(item.key, '->', item.result);
else console.error(item.key, item.error);
}

// Get multiple
const items = await hyve.getMultipleGameData(['score', 'level']);

// Delete multiple — returns count deleted
const count = await hyve.deleteMultipleGameData(['score', 'level']);

Leaderboards

Rank players by a numeric value stored in persistent game data. Game ID is resolved automatically.

// 1. Store the player's score
await hyve.saveGameData('high_score', 4200);

// 2. Fetch ranked list
const board = await hyve.getGameDataLeaderboard({ key: 'high_score' });

for (const entry of board.entries) {
console.log(`#${entry.rank} ${entry.username}: ${entry.score}`);
}

// Caller's own rank is always included
if (board.user_position) {
console.log('Your rank:', board.user_position.rank);
}

If the stored value is an object, use score_path to point at the numeric field:

await hyve.saveGameData('stats', { level: 12, score: 9800 });

const board = await hyve.getGameDataLeaderboard({
key: 'stats',
score_path: 'score', // dot-notation
sort: 'desc', // 'asc' | 'desc' (default: 'desc')
limit: 20, // 1–100 (default: 10)
});

// Pagination
if (board.has_more && board.next_cursor) {
const next = await hyve.getGameDataLeaderboard({ key: 'stats', cursor: board.next_cursor });
}

Types

type GameDataValue = string | number | boolean | null | GameDataValue[] | { [key: string]: GameDataValue };

type GameDataOperation = 'set' | 'add' | 'subtract' | 'multiply' | 'divide' | 'modulo' | 'min' | 'max' | 'append';

interface GameDataItem {
key: string;
value: GameDataValue;
created_at: string; // ISO 8601
updated_at: string; // ISO 8601
}

interface GameDataBatchItem {
key: string;
value: GameDataValue;
operation?: GameDataOperation;
path?: string;
}

interface SaveGameDataResponse {
success: boolean;
message: string;
result?: GameDataValue;
}

interface BatchSaveGameDataResponse {
success: boolean;
message: string;
results?: { key: string; success: boolean; result?: GameDataValue; error?: string }[];
}

interface GetGameDataLeaderboardParams {
key: string;
score_path?: string;
sort?: 'asc' | 'desc';
limit?: number;
cursor?: string;
}

interface GameDataLeaderboardEntry {
rank: number;
username: string;
avatar_url?: string | null;
hyve_user_id: string;
score: number;
}

interface GameDataLeaderboardResponse {
entries: GameDataLeaderboardEntry[];
next_cursor?: string | null;
has_more: boolean;
user_position?: {
rank: number;
score: number;
entry: GameDataLeaderboardEntry;
} | null;
}

Limits

LimitValue
Max key length255 characters
Max value size1 MB
Max batch size100 items
Key formatCase-sensitive