Cloud Storage
The Y8 SDK allows your game to store player-specific data in the cloud, enabling players to access their progress across devices.
Cloud Storage is intended for small amounts of persistent data such as save games, preferences, settings, and other player-specific information.
Authentication required
Cloud Storage requires the player to be authenticated.
Storage Guidelines
- Save only the data your game needs to persist.
- Use JSON for structured game data where appropriate.
- Individual values must not exceed 30 KB.
- Avoid saving data too frequently.
- If your game supports auto-save, throttle save requests.
- Prefer batching multiple changes into fewer save operations.
Save Data
Save player data to Cloud Storage.
y8Sdk.saveData({
key: "save",
value: JSON.stringify(gameState),
retries: true
})
.then(() => {
console.log("Game saved");
})
.catch((error) => {
console.error(error.message);
});
Parameters
| Property | Type | Required | Description |
|---|---|---|---|
key |
string |
Yes | Storage key. |
value |
string |
Yes | Value to store. Maximum size: 30 KB. |
retries |
boolean |
No | Automatically retry temporarily rejected saves. Default: true. |
Automatic retries
A save can be turned away when the server is rate-limiting the player. By default the SDK handles that for you: it retries up to five times, three seconds apart, before giving up.
A save that survives all of that fails with the code Y8Sdk.saveRejected,
which is worth distinguishing from a network error — it means the server
deliberately refused, not that the connection dropped:
y8Sdk.saveData({
key: "save",
value: JSON.stringify(gameState),
}).catch((error) => {
if (error.code === Y8Sdk.saveRejected) {
tellPlayerSaveFailed();
}
});
Because retries take time, a save can be in flight for up to fifteen seconds before it fails. If you would rather find out immediately and do your own buffering, switch them off:
y8Sdk.saveData({
key: "save",
value: JSON.stringify(gameState),
retries: false
});
JsResponse<SetData> response =
await Y8.Instance.SaveDataAsync(
"test_file_key",
new SaveFileData
{
stringValue = "Test save",
boolValue = true,
floatValue = 0.01f
}
);
if (response.IsSuccess)
{
Debug.Log("Game saved");
}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
key |
string |
Yes | Storage key. |
value |
string or serializable class |
Yes | Data to save. |
The C3 integration serializes the supplied value as JSON before sending it to Y8.
For structured data, you can use a Construct 3 Dictionary:
saveData → On clicked
Dictionary → Add key "score" with value score
Dictionary → Add key "coins" with value coins
Dictionary → Add key "level" with value level
Functions → Call saveData
saveKey: "saveGame"
saveItem: Dictionary.AsJSON

Y8.saveData(
"save",
gameState
);
The SDK automatically converts the game data to JSON before saving it.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
key |
String |
Yes | Storage key. |
gameState |
Dynamic |
Yes | Game data to save. |
Load Data
Retrieve previously saved player data.
y8Sdk.loadData({
key: "save"
})
.then((value) => {
if (value) {
const gameState = JSON.parse(value);
}
})
.catch((error) => {
console.error(error.message);
});
If no value exists for the specified key, the Promise resolves with null.
JsResponse<SaveFileData> response =
await Y8.Instance.LoadDataAsync<SaveFileData>("test_file_key");
if (response.IsSuccess)
{
Debug.Log(response.Data.stringValue);
}
If no value exists for the specified key, the returned data is null.
getData → On clicked
Functions → Call loadData
saveKey: "saveGame"

When saved data is found, the OnlineDataKeyFound function is triggered.
Construct 3 provides a 'getOnlineSaveData' function for retrieving the data loaded by the most recent loadData() call.

The function returns the loaded data as a JSON string.
You can use the JSON with a Construct 3 Dictionary to retrieve individual values.

On function OnlineDataKeyFound
Dictionary → Load from JSON string
Functions.getOnlineSaveData

When saved data is not found, the OnlineDataKeyNotFound function is triggered. You can use default values for your game variables.

Y8.loadData(
"save",
function(gameState:Dynamic):Void
{
if (gameState != null)
{
trace(gameState);
}
}
);
The SDK automatically parses the saved JSON data before passing it to the callback.
Remove Data
Delete previously saved data.
y8Sdk.removeData({
key: "save"
})
.then(() => {
console.log("Save removed");
})
.catch((error) => {
console.error(error.message);
});
JsResponse response =
await Y8.Instance.RemoveDataAsync("test_file_key");
if (response.IsSuccess)
{
Debug.Log("Save removed");
}
RemoveData → On clicked
Functions → Call RemoveData
key: "saveGame"
The player must be authenticated before removing saved data.
Y8.removeData("save");
Best Practices
- Save only essential player data.
- Use JSON for structured data where appropriate.
- Keep saved values below 30 KB.
- Avoid saving after every gameplay event.
- Prefer batching changes into fewer save operations.
- Use a consistent storage key for your game's save data.
- Ensure the player is authenticated before using Cloud Storage.
- Handle save and load errors appropriately.
- Throttle auto-save requests to avoid unnecessary requests.
Platform-Specific Notes
Values are stored as strings. Use JSON.stringify() when saving objects and JSON.parse() when loading them.
Serializable classes can be used for structured Cloud Storage data.
Structured data can be stored using JSON, such as Dictionary.AsJSON.
The SDK automatically converts game data to JSON when saving and parses it when loading.