Handling API Requests for Data Stores

Before sending requests to Open Cloud APIs for data stores, you need to understand how to handle them properly. For information on the usage of the API, see the Usage Guide.

Authorization

Like all Open Cloud APIs, data store endpoints require all requests to include the x-api-key header, which contains an API key with enough permissions for the request. This requires you to apply the key to the experience and the data store, and the endpoint operation is permitted. If the key is invalid, 403 Unauthorized is returned. For more information on API keys, see Managing API Keys.

Throttling

All endpoints have two types of universe level throttling: request-per-minute throttling and throughput throttling. With every experience, request-per-minute throttling allows you to send a certain number of requests per minute, and throughput throttling allows you to send a certain amount of data per minute, regardless of the number of API keys.

Unlike the Lua API, these limits currently do not scale based on user counts. Exceeding these limits causes the endpoint to return 429 Too Many Requests.

Request Type Endpoints Throttle Limits
Write
  • Set Entry
  • Increment Entry
  • Delete Entry
  • 10 MB/min/universe write throughput
  • 300 reqs/min/universe
Read
  • List Data Stores
  • List Entries
  • Get Entry
  • List Entry Versions
  • Get Entry Version
  • 20 MB/min/universe write throughput
  • 300 reqs/min/universe

Input Validation

Before sending your request, make sure to validate endpoint parameters on formatting requirements and constraints based on the following table. Individual endpoints can have additional requirements beyond these. If a parameter doesn't satisfy the following restrictions, the endpoint returns a 400 Bad Request.

Input Type Notes
universeId number
  • The value of DataModel.GameId, which is the unique identifier of your experience.
  • Be careful not to mistake this with a Place ID (DataModel.PlaceId), which identifies a place in an experience, not the entire experience.
datastoreName string
  • Length must be 50 bytes or less.
  • Cannot be null or empty.
scope string
  • The scope of a data store. See Legacy Scope Support.
  • Length must be 50 bytes or less.
  • Defaults to global when not provided.
entryKey string
  • Length must be 50 bytes or less.
  • Cannot be null or empty.
content-md5 string
roblox-entry-attributes string
  • Serialized by JSON object.
  • Length must be less than 300 bytes.
roblox-entry-userids String
  • Serialized by JSON array of 0-4 numbers.
  • No more than 4 user IDs.
cursor string
  • An indicator of more data available in the requested result set. See Cursors.

Content-MD5

Content-MD5 is the base-64 encoded MD5 checksum of content. It's an optional request header for the Set Entry endpoint that checks the data integrity and detects potential issues.

You can use the langugae of your choice to calculate the value of the content-md5 header. The following example uses Python. The hashlib.md5() and base64.b64encode() functions are available in Python standard libraries (2.7, 3+).

Generating Content-MD5

# With prompts
$ python -c "import base64, hashlib; print('content-md5: ' + str(base64.b64encode(hashlib.md5(bytes(input('content: '), encoding='utf8')).digest()), encoding='utf8'))"
content: 750
content-md5: sTf90fedVsft8zZf6nUg8g==
# Using just stdin and stdout
$ echo "750" | python -c "import base64, hashlib; print(str(base64.b64encode(hashlib.md5(bytes(input(), encoding='utf8')).digest()), encoding='utf8'))"
sTf90fedVsft8zZf6nUg8g==

If you run into issues generating a valid content-md5 value, you might need to encode your request body in UTF-8 binary before computing the checksum.

Cursors

Endpoints that return lists of data might also return a nextPageCursor string. This indicates that there is more data available in the requested result set. To receive it, provide this string in the cursor query parameter on a subsequent request. If the cursor parameter is provided but invalid, the endpoint returns 400 Bad Request.

The format of cursor strings is not defined. You should not interpret or parse them as they may change at any time.