NEOLearn

DatastoreService

Game save data: a running game's per-player and shared data, leaderboards, and the player's data export.

Updated October 17, 2026

On this page

Game save data: a key-value store per experience, so a game can save without its own backend. A running game calls it with its session's game token (Authorization: Bearer <game token>, SessionService.Join): the experience comes from the token, so a game only ever reaches its own data, and only while its player is still in that session. Values are JSON text (at most 4 MB each). Every entry has a version, raised by every write; Set with if_version is a compare-and-set on it. Scopes: "user" is one player's data (user_id empty means the token's own player); "global" is shared by every player of the experience. A player's "user" scope is written by that player, or by the session's authority for a player in the session. "global", and an ordered store's keys other than the writer's own user id, are written only by the session's authority: the host of a peer session, the player of a solo one (without a host, the member who joined first). Any member of the session reads any scope of the experience. Per experience: requests per minute (a base plus more per player in its sessions) and total stored bytes are capped (resource_exhausted). Old values are kept for 30 days. Every method is a POST with a JSON body; see the overview for the protocol, authentication and errors.

Summary#

MethodAuthDescription
GetGame token
SetGame tokenWrites a value. With if_version, only when the entry's current version is version (0: the key doesn't exist yet); otherwise ok is false and the current value comes back.
UpdateGame tokenMerges patch (a JSON object) into the stored object atomically: each top-level field replaces the stored one, a null removes it. A missing key starts as {}.
DeleteGame token
ListKeysGame tokenKeys in a scope, in key order, limit at a time (at most 1000).
IncrementOrderedGame tokenOrdered stores (leaderboards): integer values by key, sorted. Adds delta (creating the key at 0). key empty: the token's own user id.
ListOrderedGame tokenThe top (or, ascending, bottom) entries of an ordered store, with their rank (1 = first).
ExportMyDataAccountSigned-in accounts (an access token): everything games stored about the caller (data export).

Methods#

Get#

HTTP
POST /neo.platform.v1.DatastoreService/Get
Content-Type: application/json

Auth: A running game's game token (SessionService.Join), while its player is in that session.

Request: DatastoreGetRequest. Response: DatastoreGetResponse.

Set#

Writes a value. With if_version, only when the entry's current version is version (0: the key doesn't exist yet); otherwise ok is false and the current value comes back.

HTTP
POST /neo.platform.v1.DatastoreService/Set
Content-Type: application/json

Auth: A running game's game token (SessionService.Join), while its player is in that session.

Request: DatastoreSetRequest. Response: DatastoreSetResponse.

Update#

Merges patch (a JSON object) into the stored object atomically: each top-level field replaces the stored one, a null removes it. A missing key starts as {}.

HTTP
POST /neo.platform.v1.DatastoreService/Update
Content-Type: application/json

Auth: A running game's game token (SessionService.Join), while its player is in that session.

Request: DatastoreUpdateRequest. Response: DatastoreUpdateResponse.

Delete#

HTTP
POST /neo.platform.v1.DatastoreService/Delete
Content-Type: application/json

Auth: A running game's game token (SessionService.Join), while its player is in that session.

Request: DatastoreDeleteRequest. Response: DatastoreDeleteResponse.

ListKeys#

Keys in a scope, in key order, limit at a time (at most 1000).

HTTP
POST /neo.platform.v1.DatastoreService/ListKeys
Content-Type: application/json

Auth: A running game's game token (SessionService.Join), while its player is in that session.

Request: DatastoreListKeysRequest. Response: DatastoreListKeysResponse.

IncrementOrdered#

Ordered stores (leaderboards): integer values by key, sorted. Adds delta (creating the key at 0). key empty: the token's own user id.

HTTP
POST /neo.platform.v1.DatastoreService/IncrementOrdered
Content-Type: application/json

Auth: A running game's game token (SessionService.Join), while its player is in that session.

Request: IncrementOrderedRequest. Response: IncrementOrderedResponse.

ListOrdered#

The top (or, ascending, bottom) entries of an ordered store, with their rank (1 = first).

HTTP
POST /neo.platform.v1.DatastoreService/ListOrdered
Content-Type: application/json

Auth: A running game's game token (SessionService.Join), while its player is in that session.

Request: ListOrderedRequest. Response: ListOrderedResponse.

ExportMyData#

Signed-in accounts (an access token): everything games stored about the caller (data export).

HTTP
POST /neo.platform.v1.DatastoreService/ExportMyData
Content-Type: application/json

Auth: A signed-in account. Guests are refused.

Request: ExportMyDataRequest. Response: ExportMyDataResponse.

Types#

DatastoreDeleteRequest#

FieldTypeDescription
storestring
scopestring
userIdstring
keystring

DatastoreDeleteResponse#

FieldTypeDescription
foundboolean

DatastoreGetRequest#

FieldTypeDescription
storestring[A-Za-z0-9_.-]{1,50}; empty: "default".
scopestring"user" (default) or "global".
userIdstring
keystring1..128 characters.

DatastoreGetResponse#

FieldTypeDescription
foundboolean
valuestringJSON text.
versionstring (int64)
updatedAtstring

DatastoreListKeysRequest#

FieldTypeDescription
storestring
scopestring
userIdstring
prefixstring
limitnumber
afterstringContinue after this key (the previous page's next).

DatastoreListKeysResponse#

FieldTypeDescription
keysarray of string
nextstringNon-empty when there are more: pass it as after.

DatastoreSetRequest#

FieldTypeDescription
storestring
scopestring
userIdstring
keystring
valuestringJSON text, at most 4 MB.
ifVersionboolean
versionstring (int64)

DatastoreSetResponse#

FieldTypeDescription
okboolean
versionstring (int64)The entry's version now (the new one, or the current one when ok is false).
valuestringWhen ok is false: the current value (JSON text; empty when the key doesn't exist).

DatastoreUpdateRequest#

FieldTypeDescription
storestring
scopestring
userIdstring
keystring
patchstringA JSON object.

DatastoreUpdateResponse#

FieldTypeDescription
valuestring
versionstring (int64)

ExportedEntry#

FieldTypeDescription
experienceIdstring
storestring
scopestring"user" or "global".
keystring
valuestring
versionstring (int64)
updatedAtstring

ExportedOrderedEntry#

FieldTypeDescription
experienceIdstring
storestring
keystring
valuestring (int64)
updatedAtstring

ExportMyDataRequest#

No fields: send {}.

ExportMyDataResponse#

FieldTypeDescription
entriesarray of ExportedEntry
orderedarray of ExportedOrderedEntry

IncrementOrderedRequest#

FieldTypeDescription
storestring
keystring
deltastring (int64)

IncrementOrderedResponse#

FieldTypeDescription
valuestring (int64)

ListOrderedRequest#

FieldTypeDescription
storestring
limitnumber1..100 (default 10).
ascendingboolean
offsetnumber

ListOrderedResponse#

FieldTypeDescription
entriesarray of OrderedEntry

OrderedEntry#

FieldTypeDescription
keystring
valuestring (int64)
rankstring (int64)

See also#