Open Cloud | Datastore API (node.js)

Datastore API

Greetings everyone!

Today I will be creating a tutorial on how you can use the Open Cloud Data Store API’s. With the amount of people who found my Messaging Service API one useful I thought I might as well create a tutorial on the Datastore Open Cloud API in-case if anyone needs any help with this. The documentation is not the best again with only examples in Curl so I will be writing this tutorial which is in JavaScript (node.js) and will go step by step.

Quick Note: This tutorial is for how to use the Roblox API through the use of the Roblox Open Cloud. This tutorial is NOT for the Roblox internal API which uses Roblox security cookies to authenticate requests. This tutorial will also contain examples off how to use the Datastore Open Cloud API which are written using JavaScript (in the runtime environment node.js). Sending requests will be different for different programming languages however the basic idea of how to use the Datastore API are the same.

Tutorial Contents:

Please before using this tutorial learn how to send basic API requests before attempting to use this tutorial. Although it will explain how to use the Datastore API endpoinst I will not be going into major details into how to send requests.


What is the Datastore Open Cloud API and what can we use it for?

The Roblox Open Cloud Datastore API allows us to edit things inside of a datastore outside of the Roblox servers. It is basically in simple terms the things inside of the DataStoreService but allows us to use the datastores outside of Roblox in our applications. This allows us to expand our applications outside of what we could before and opens up a ton of new opportunities for our applications outside of Roblox which I will go onto more below.

There are many different things we can use this API for and allows us to easily interact with our datastore outside of Roblox. Some examples of things we can create with this API are Discord bots that allow us to add currency, remove currency, view currency someone has which can be implemented as just a normal Discord bot or as part of a support system for a Discord server. This could also allow us to ban people from inside of website or Discord bot which we can also use the Messaging Service API to have a live ban system. The things we can create with this API is endless and is really up to your imagination.

How to use the DataStore API?

Before we even go into how to use each of the endpoints inside of this API we first require to get an Open Cloud API key so that we can authenticate our requests. I will now explain how we can create this API key. First you need to go to https://create.roblox.com/credentials and press the blue button saying “CREATE API KEY”. Once clicked you require to add a name and you can then add a description (description is not required). Once you have done this we need to move onto the “Access Permission” section. When we click the select down menu on this section we want to click the “DataStore” option and press “Add API System”. Once we clicked this we need to search for our experience and press the “Add Experience” button. Once we have added our experience we need to select what we want the API key to be able to do. You can find out what each API endpoint permission requires in the documentation for this API. We lastly need to set the IP that the API key can be used on. If you rather anyone be able to use your API key from any IP address you should be able to put 0.0.0.0/0 as the IP address however this is highly not recommended for security reasons. We now should have the API key which we can save the API key to use on the API endpoints.

List DataStores in Universe

This API endpoint allows us to list all of our DataStores inside of universe inside of our experience. This request is a get request because we are receiving information (the data stores inside of a universe). In the endpoint URL we require to add the UniverseID where it says “UniverseID”. The endpoint we are sending the get request to is: https://apis.roblox.com/datastores/v1/universes/UniverseID/standard-datastores

Inside of the request we require two main parameters inside of the request and there is one other parameter which is only sometimes needed. The two parameters that we require in this request is the prefix and the limit of data stores which can be shown. The prefix is what you want the datastore name to begin with so if you wish it to just list out all datastores you can just leave the string blank. The limit is how much datastores you want to list/max amount to list. The parameter which is not required is the cursor parameter which is only required if you do not get a empty string on the nextPageCursor option we get from our response from the request. The reason why sometimes we may need to add the cursor parameter is if we have lots of datastores we may require to move to the next page. The last part of this endpoint is the header and the only one we need for this get request is the API key which we copied before. Now we should be able to get our datastores.

Example Code + Output (no error management):

List Entries

The next API endpoint is List Entries. This allows us to list the entries inside of a DataStore and also another get request. This API endpoint works a bit like the “List DataStores in Universe” however unlike the “List DataStores in Universe” one in this API endpoint we are listing the entries inside of a datastore. Again you will require to change where it says Universe ID to your universe ID form the experience. The API endpoint that we are using for this one is: https://apis.roblox.com/datastores/v1/universes/UniverseID/standard-datastores/datastore/entries

In this endpoint request we have three main parameters unlike the List DataStores one which only required two. The main parameters which are required is your DatastoreName, the prefix and the limit. The datastore name is the datastore you wish to list the Entries off, the prefix is like the “List DataStores in Universe” where we can choose what we want to only collect if it starts with our prefix (just leave blank if you want it to list everything) and the last one is the limit/max number of entries you wish to list). There are many other parameters that are not required like the scope, AllScopes, and the cursor. Again like “List DataStores in Universe” if the “nextPageCursor” response we get is not an empty string then we should send the request again with the cursor to go to the next page. The scope and AllScopes is quite basic to understand as well, scope allows you to set the scope (by default its global) and the AllScopes if set true allows all of the Scopes. You also need to add the API Key in the headers to authenticate the request.

Example Code + Output (no error management):

image

Get Entry

I will now be moving onto the Get Entry API endpoint. This endpoint allows us to get an entry from a datastore (getting it entryKey) unlike the “List Entries” one which will just list out all of the Entries. The Get Entry API endpoint is another get request. Again you will need to change the “UniverseID” in the endpoint to your universe ID. The endpoint which the request will be sent to is: https://apis.roblox.com/datastores/v1/universes/UniverseID/standard-datastores/datastore/entries/entry

In this API endpoint we have two main parameters which we will be in the request. These two main required parameters is the datastore name and the entryKey. The datastore is the datastore which the information is stored in and the entryKey is the key which you saved the data under (for example user_1471902232). In this request there is only one non-required parameter which is the scope and this will be defaulted to global.

Example Code + Output:

image

Set Entry

Next I will be explaining the API endpoint Set Entry. Set Entry allows you to either create or update an entry. Often people use the Get Entry first to get the value if you are removing currency so that you can add on the currency to the current value. This is our first post request and is one of the most complicated endpoints due to us requiring to convert our rawData into a md5 base 64 format. Again like all of the other endpoints you require to change the UniverseID to your universe ID. The API endpoint we will use for this is: https://apis.roblox.com/datastores/v1/universes/UniverseID/standard-datastores/datastore/entries/entry

First of all before we go onto what we need to have inside of our headers and parameters I will first be explaining how we can convert our raw data into the md5 base 64 format which is required for us to do. So to do this we first need to turn our data into a JSON string which we can do via JSON.stringify() to stringify our data. Once our data is converted to a string we can now convert our string data. We can do this by using an NPM package called crypto which is a built in module in node.js so you will not require to download this package. With the crypto module we first need to create a md5 hash and then update that hash with our JSON string changed data, which we then digest it with base64. We can do this via crypto.createHash("md5").update(JSONValue).digest("base64"). Now we should have our converted raw data we can now move onto the main request.

So the parameters that are required is the datastoreName and the entryKey; the datastore name is your datastore you wish to post an entry to and the entryKey is what you want to save it under. There are also 3 non-required parameters which is matchVersion, exclusiveCreate and scope. The scope is by default set to global, the matchVersion (by default it is set as null) allows you to only update if it matches a version and the exclusiveCreate (by default it is set as false) allows you to only create the entry if it does not exist. The headers that are required is the API key, the content in an md5 form and the content-type which needs to be set to application/json. The headers that are not required is the roblox-entry-userids and the roblox-entry-attributes. Although they are not required if you don’t add any values for them the value they currently have will be wiped clean.

Example Code + Output (no error handling):

image

Increment Entry

Next I will be explaining the Increment Entry endpoint. This is an API endpoint which allows us to increase an entry. Please note that to use this endpoint the entry you are increasing and the thing your increasing by is required to be an integers or it will cause issues because it cannot increase anything else. Increment Entry can be a solution to increasing someones currency in-game if you rather not get the value first by “Get Entry” and then setting it with the “Set Entry” endpoints. You will need to change the UniverseID in the endpoint URL to your universe ID the datastore is in. The request type is a post request and the API endpoint is: https://apis.roblox.com/datastores/v1/universes/UniverseID/standard-datastores/datastore/entries/entry/increment

Unlike the “Set Entry” endpoint we do not require to convert our raw data into a md5 format and we can just place in the raw data. The parameters which are required for this request is datastoreName, the entryKey and the incrementBy. The datastoreName is the datastore you wish to do this action within, the entryKey is the key for the entry you want to increase (e.g user_1471902232) and the incrementBy is how much you want to increase by. The headers which are required is your API Key and content-length in bytes.

Example Code + Output (no error handling):

image

Delete Entry

Now I will be explaining the Delete Entry endpoint. This API endpoint allows you to delete an entry inside of a datastore. This could be useful if you wish to reset someones currency without editing the amount they have. This request type is a delete request. You will need to change the UniverseID to your universe ID on the endpoint. The endpoint we will be sending this request to is: https://apis.roblox.com/datastores/v1/universes/UniverseID/standard-datastores/datastore/entries/entry

This is quite an easy endpoint to use unlike some of the other ones. The required parameters is the datastoreName and the entryKey which you wish to remove. You the just need to set the API Key as an header and send the request. You just need to ensure when doing your error handling your checking to see if there is an error of the entry not existing.

Example Code (no error handling):

List Entry Versions

I will next be moving onto List Entry Versions endpoint. This allows you to list the versions of an entry. This endpoint request is a get request and you will need to change the UniverseID in the endpoint. The endpoint we use for this request is: https://apis.roblox.com/datastores/v1/universes/UniverseID/standard-datastores/datastore/entries/entry/versions

There are three parameters which are required that is the datastoreName, entryKey and the limit. The datastoreName is the datastore where the entry is, the entryKey is the key which the entry is under and the limit is the same then the other endpoints above which list things out and is the limit/max amount it will list out. There is also four non-required parameters for the request which is the startTime, endTime and cursor. The startTime can be set if you only want to list versions after a startTime and the endTime can be if you only want to list versions before the a time. The cursor is like all the other list endpoints in that if you get a another page you can use the cursor value you get to move onto the next page. The only header which is required is the API Key.

Example Code (no error handling):

Get Entry Version

The last API endpoint there is inside of the Datastore API is the Get Entry Version. This allows you to get an version of an entry. It works very closely to the way that “Get Entry” works however this endpoint allows us to get a version of an entry unlike the “Get Entry” which gets the current entry not a version/past entry. This request is a get request and you require like all the other endpoints to replace where it says UniverseID with your place universe ID. The endpoint we will be sending the get request to is: https://apis.roblox.com/datastores/v1/universes/UniverseID/standard-datastores/datastore/entries/entry/versions/version

The required parameters for this request is the datastoreName, the entryKey and the versionId. The datastoreName is the name of the datastore you want to get a version of an entry in, the entryKey is the key for the entry you want to get a version off and the versionId is the ID of the version you want to get. There is also a non-required parameter which is scope which should by default be set at global. The only header which is required is the API Key.

Example Code (no error handling):

Error Management:

Due to there being soo many different errors you can get I will not be going over them all but you can check out all the errors below (or at least they are the ones Roblox claim you will only get). I have found due to how many there are and they are not all useful for all the endpoints the best bet would be to go through all the errors you can get and only error handle the ones that are required.

All of the errors you can get are here: Open Cloud: Data Store API Reference

Conclusion of tutorial

I hope this tutorial explaining the OpenCloud Datastore API helped some people and that you can now use the API endpoints in the Datastore API easily. If you have any questions or issues your welcome to commend them down below or send me a direct message here on the forums.

If you also have any questions or issues feel free to check out these links:

25 Likes

A really interresting i just tried and did a lot of test on the Open Cloud API of roblox and i really like it.
However i got an issue with SetEntry. My Datastore has a whole table (i’m using profileservice) and i want to change one of the value inside this table. I tried sending the whole table with the change using SetEntry but it didn’t seems to work i’m not sure of how it really work. Maybe it create a new entry which would be weird or i did smth wrong but if you have any idea i’m taking.
Great Tutorial !

1 Like

If you want your welcome to send me a direct message here on the DevForum with the code you currently have (the JS code) and I can take a look if I can see what your doing wrong.

I’ve been experimenting with Open Cloud DataStores recently. This resource has been quite helpful, thanks. However when I try to get a list of DataStores with the api I always only get one of my DataStores and a nextpagecursor value. Am I supposed to use this somehow to get the next set of results?

You can see more about my problem here:

1 Like

Hello,

First of all sorry for the late response, I have recently been going through some personal issues so have not really been checking any places such as the DevFourm as of recent.

I believe from checking the #help-and-feedback:scripting-support post you sent in your message that your issue has been solved already by @7z99, just wanted to check that everything has been solved for you or if you require any other assistance? I apologize if I have not included in this tutorial about the nextpagecursor and will ensure to check and edit the tutorial if I have missed it out.

I am glad that my tutorial has allowed you to get a better understanding of the Datastore API on the Roblox OpenClould. I find it a super useful API in the OpenCloud but the documentation at the moment for all of the API’s in the OpenCloud is not the best.

1 Like

Yes thanks, I did manage to solve my problems. It’s great proving community resources like this. Your a great asset to the community.

1 Like

I was recently working with Set Entry but I am getting 401 Errors. I’m not sure why. This is my code:

var id = "3021566345"
var key = "blablabla"
var datastore = "Test101"

var setkey = "setentrytest"
var setvalue = "500"

const url = "https://apis.roblox.com/datastores/v1/universes/" + id + "/standard-datastores/datastore/entries/entry"

axios.post(url, {
    params: {
        datastoreName: datastore,
        entryKey: setkey,
    },
    headers: {
        "x-api-key": key,
        "content-type": "application/json",
        "content-md5": crypto.createHash("md5").update(JSON.stringify(setvalue)).digest("base64")
    }
}).catch((error) => {
    console.error(JSON.stringify(error))
})

Do you have any idea why this may be happening? I definitely can connect to Open Cloud because I can run get requests such as List DataStores and List Keys

Sorry to be pestering you again

1 Like

Hello,

Do not at all worry about pestering me, I am here to help anyone who requires it. I will take a look at the code later when I have some free time. I remember having some issues with the same endpoint when I first used it and was stuck on the issue for a while but I cannot remember what I did on the top of my head to fix it.

If you fix it before, let me know so that I don’t find it when you have already found the issue.

1 Like

Ok so I had a review of the code and I think I may know the issue. For some reason it spits out a strange unauthorized request if you don’t have the raw value next to the URL (the body I think it is or smthing).

For example below we have the example which I left in this tutorial. For some reason if you leave the 300 out it says the request is unauthorized (300 being the value that I set in the example) .

It is very very strange on why it claims that the request is unauthorized if you don’t put the value there cuz I would expect to get a different error rather then an unauthorized error. Don’t at all feel bad with doing this incorrect cuz it took me a while to find out what the issue was when I first did it :laughing:

If you need any other help or this does not fix your problem then feel free to contact me again but I think this should be the problem.

1 Like

Wow thanks that fixed the problem.

But really weird bug. So if I send an integer as the value it works fine but if I try set a string as the value it returns Error 400 Bad Request something tells me that it might not be anything to do with sending along the extra petameter in axios.post() but rather to do with the md5 encryption. Any ideas? (I know you probably have better things to be doing than helping me :sweat_smile:)

What so what your saying is that if you set the value you are trying to set to a integer it works but if it is a string it does not?

Mind sharing the code your trying to use?

It is strange cuz the code which I made made up quick in my code editor just now, if I do exactly basically what you did with the md5 it works fine with a string.

Ensure that you also have the value that you pass next to the URL is the same then what your having the content in as md5 cuz if not it sends this error (just the one u pass in not in the headers is the raw version un-converted.

image

1 Like

Ok, I’ve been getting somewhere. If you just don’t include the content-md5 header it works with strings.

Ok now I am confused. I swear in the docs it says that you have to use md5 and encode it in base64 but it seems to work fine without changing it…

1 Like

Ahh. So in the Docs here: Data Stores | Roblox Creator Documentation they don’t say whether the content-md5 header is optional or not but if you click on the link for Content-MD5. There are nicely hidden away they say that it is optional and it is used to the low chance of data corruption during the POST request.

I will say that the Open Cloud Docs aren’t that beginner friendly, Anyway thanks very much for your help!

1 Like

Ah I see. Nice that Roblox hid that away from us just to ensure that they confuse all devs who wanna use it :laughing:

I will update my post cuz I think in this tutorial post I say that it is required. Thanks for letting me know.

1 Like

To anyone interested I have made a YT vid covering this.

1 Like