OpenCloud | Assets API

Assets API

Greetings everyone!

Today I will be creating a tutorial on how you can use the assets API. This API in the Open Cloud currently allow us upload or update an asset. This API has just came out very recently so I have decided to make it so that there is a tutorial on how to use this API in node.js due to the tutorial Roblox has made there are examples in CURL only.

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 Assets 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 Assets API are the same.

Tutorial Contents:

  • An explanation of what this Open Cloud API is and how it can be used.

  • Explaining and showing how to use it/send a request to the API endpoint.

  • Showing the errors that you may get (with an example of basic error management).

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 Assets API endpoint I will not be going into major details into how to send requests.


What is the Assets API and what can we use it for?

The Assets API allows you to upload or update an asset onto Roblox. You can either upload to your account or a group. You can upload audios, decals and models. Once uploaded you can get information about the asset you just uploaded. This OpenCloud API is very useful because it allows us to automate the upload of assets. You could for example have a blender plugin which will automatically upload an asset or something such as that speeding up workflow.

How to use the Assets API?

To use the Assets API we must first create an Open Cloud API key which acts as our authentication for the API request. To create our Open Cloud API key we simply go to https://create.roblox.com/credentials and then click the large blue button which says “CREATE API KEY”. Once clicked you need fill in the name and if you want you can also add a description (description is not required however). After putting a name and description if you scroll down the page there will be an area called “Access Permissions”. In this section you click the selection menu, then choose the “Assets API” option and press the white button which says “ADD API SYSTEM”. By default you will have the person who the assets will be uploaded via the key (for example if you make the API on a group the assets will be uploaded to the group) however you need to add the operations the API key can perform. There are two different ones which are write and read, I suggest just having both selected to make it easier however the write basically allows you to upload assets and the read is just to get info about the asset you uploaded. You then need to move down to the last section called “Security”. This area you need to place your IP address (or hosting of the API address). If you wish any IP to be able to use it you should be able to just add 0.0.0.0/0 as the IP address. This is however not recommended due to anyone being able to use the key if they get access to it. You should then copy your API key, you must write this down somewhere as you cannot see it again once you go off the page.

Now we can get into the main programming. There are three different endpoints; one to update an asset, one to upload an asset and one to get info on an uploaded asset. I will first be starting with the create endpoint because this makes the most logical sense and then I will move onto the get so that the information of the uploaded asset can be collected. Then lastly I will show how you can update an asset via the last asset endpoint on the Assets API.

Create Asset:

The request type for the create asset is a POST request because we are posting a request for a new asset to be uploaded. The API endpoint for creating an asset is https://apis.roblox.com/assets/v1/assets so a POST request will be sent to this API endpoint. In this request there are two required parameters for the request however both of these parameters are to be put in the request as formData. In node.js (or at least with Axios unsure about other packages) there is no direct way to create formData. Due to this we require to download a package called form-data (this can be downloaded by running the command npm i form-data in the terminal) which will be used to create the form data we will be adding as the request parameter(s). We can create a new form data by doing new FormData(), form data referencing the package we just downloaded. In the form data the two things that we need to add is a parameter called request and a parameter called fileContent. The request parameter is where we will add the information for the asset upload and the fileContent is the file/asset that we want to upload.

I will first be starting with the request parameter. In the request parameter we require to add an object containing the required/needed information for the upload of the asset. The required sections in this object is the asset type, the user or group which the asset will be uploaded to, the description of the asset and the name that we want to upload the asset as. The asset type will be written in the object as assetType and can be any of the supported types of assets to be uploaded via this API. At the time of writing this tutorial the supported asset types (that you can add in the value of assetType) are Audio, Decal and Model. The user or group upload information is set under a {} under the key of creationContext and in the {} there is another which is called creator.In the {} of the creator should be either groupId or userId which are the two options. The groupId is the group you want to upload the asset to and the userId is the user you want to upload to (you have to choose which one, not include both). The description is set in the object as description where you then add the description as a string and the name of the asset is in the object as displayName with the value being a string of the asset name. Now that is the requirements for the object but we cannot send the object as a raw object so we require to use JSON.stringify() to turn the object into a string to be sent in the request. This object should also be appended to the form data we created as the key of request and the value of our object after being stringify.

The other thing we need in the form data is the asset that we want to upload. This can be done through appending the file to the form data by the key of fileContent and then using the package fs to set the file. fs should be already downloaded in node.js but if it is not then you may need to download the package with npm i fs. To add the asset file by using fs we can use the method fs.readFileSync("FileName") with replacing FileName with out asset file + the extension of the file (e.g. .png). We then also need to add the file name + the extension to the end of the append as a option or we will receive an error. Now that is our file sorted out and appended to the form data. The form data should then be added as the parameter in the main request.

The last thing to do is to add the headers for the request. The header which is required is the x-api-key header which will be the API key which we created at the start of this tutorial. Depending on what package you are using to send your request you may also need to add the header Content-Type which will have the value of multipart/form-data which is the content type for a form data request. Now you can just add your .then and .catch to know if the request is successful or if there is an error which has been catched. If successful it should send us back the operation ID in the format of operations/{operation-ID} inside of path which will be in the body.

request parameter object options:

Example Code:

const Axios = require(`axios`)
const FormData = require('form-data');
const fs = require(`fs`)


function createAsset() {
    let bodyFormData = new FormData();
    bodyFormData.append('request', JSON.stringify({
        "assetType": "Decal",
        "creationContext": {
            "creator": {
                "groupId": "3465611"
            }
        },
        "description": "Random description for test upload!",
        "displayName": "TestAsset for upload"
    }))

    bodyFormData.append('fileContent', fs.readFileSync("test.png"), "test.png")

    Axios.post("https://apis.roblox.com/assets/v1/assets", bodyFormData, {
        headers:{
            'x-api-key': "API KEY HERE",
        }
    }).then(response =>{
        console.log(response.data.path)
    }).catch(err =>{
        console.log(err.response.data)
    })
}

sendAssetCreateRequest()

Successful Request:

image

Get Operation:

The request type for the get operation is a GET request because we are getting information about the operation we just ran. The API endpoint for the get operation request is https://apis.roblox.com/assets/v1/operations/{operation-id} so a get request will be sent to this endpoint. In this request we only require one parameter which is inside of the path and this is our operation ID. We can get the operation ID from either the update asset request or the create asset request and is basically just the ID of the operation. In the update or create request it should however have the path for it already set up so you don’t even need to include the operations part but rather just add the path where the operations/{operation-id} part is. After we have the operation ID part sorted out all it is to do is add in the headers. For the headers the only needed header if your using axios is the API key to authenticate the request and this is set as x-api-key as normal.

Example Code:

const Axios = require(`axios`)

function getOperation(operationPath) {
    Axios.get("https://apis.roblox.com/assets/v1/" + operationPath, {
        headers:{
            'x-api-key': "APIKEYHERE"
        }
    }).then(response =>{
        console.log(response)
    }).catch(err =>{
        console.log(err.response.data)
    })
}

getOperation()

Successful Request:

image

Update Asset:

Before I continue onto the update asset I would just like to state that at the current moment of writing this tutorial only models can be updated and none of the other assets type however support for the other assets types will come in the future. Moving onto the main explanation of the update asset endpoint, the type of request which will be sent is a PATCH request and the endpoint which the request will be sent to is https://apis.roblox.com/assets/v1/assets/{assetId}. In the request there are three different parameters which are required to be added however two are set one way and one another way. The first parameter which is required to be set is the assetId and this is inside of the path of the request. The assetId is just the ID of the asset which we want to update. The other two parameters need to be set as form data exactly like the create asset one. I will not go into much detail because it is the exact same then the create asset one (the other two parameters) being that a parameter called request and fileContent need to be set as form data in the request. The request is information for the request and the fileContent is the asset file to update with. I am not 100% sure about what we can add in the request part because I have not tested this endpoint however you require to add the asset ID and I think you also can add in update details such as changing the asset name possibly. The rest of this endpoint I suggest you refer back to the create asset as this explains everything. The only other thing outside of the parameters is the API key which is set in the headers as your normal x-api-key like any other request in the OpenCloud.

request parameter object options:

Example Code (I have not tested this):

const Axios = require(`axios`)
const FormData = require('form-data');
const fs = require(`fs`)


function updateAsset(assetID) {
    let formData = new FormData()
    formData.append("request", JSON.stringify({
        assetId: assetID
    }))
    bodyFormData.append('fileContent', fs.readFileSync("test.fbx"), "test.fbx")

    Axios.patch("https://apis.roblox.com/assets/v1/assets/" + assetID, formData, {
        headers:{
            'x-api-key': "API KEY HERE"
        }
    }).then(response =>{
        console.log(response.data)
    }).catch(err =>{
        console.log(err.response.data)
    })
}

updateAsset()

Expected Successful Response:

Error Handling

I will now be moving onto my last section of this tutorial which will be about Error handling. Error handling is very important because if you don’t your system can get issues and break. One of the main part of error handling is first to catch the error. After a request with axios if we get an error, axios will attempt to show us this error. If we just leave this error unattended it will break out bot/application so due to this we can use .catch() to catch any errors we get. We can then use the information from the error we get to send a response back explaining what the issue is.

The main error codes for the Assets API are as stated inside of the documentation are:

Conclusion of tutorial

I will now be ending my tutorial on how to use the Assets API. I hope this tutorial helped some people who may not understand curl or in general was confused about the Roblox documentation. 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 have any issues you can also check below:

Useful Tip From @R0bl0x10501050 : OpenCloud | Assets API - #5 by R0bl0x10501050

13 Likes

I’ve been having issues with the fileContent parameter on my end for the last week. Will update rblx with the Assets API thanks to this.

1 Like

I have legit had the same issue. It took me a while to figure out were I was going wrong with the fileContent cuz it just kept on giving me stupid ass errors. I wish Roblox could try document there API’s better and in a more easy way for not just CURL.

1 Like

Thanks alot. I’ve been trying to figure out how to implement CreateAsset for ages. Now I’ll finally be able to implement it.

1 Like

I’d also like to point these out - if you run the example code for the CreateAsset endpoint and receive a 415 code, add the ...bodyFormData.getHeaders() line:

Axios.post("https://apis.roblox.com/assets/v1/assets", bodyFormData, {
		headers: {
			...bodyFormData.getHeaders(),
			'x-api-key': YOUR_TOKEN_HERE,
		}

and if you still receive 400 when everything is filled in properly, console.log the response or err variables and look at the bottom of the response data in the console:

image

In this case, the entire asset name was moderated, so all I have to do was change it. It appears that in the case of a single word of the name and not the entire thing the asset will still upload and #'s will replace the filtered word.

2 Likes

Is there a way to get the ImageID from the decal’s assetID straight from the Open Cloud API or some other method that will not require you to manually convert those to ImageIDs so a script can actually use them in a game. My problem is that I’m trying to load a lot of images and use them, and the open cloud api is great for that, but it uploads decals instead of images, so now I’m stuck at this question. Sorry for bumping this old conversation, but I haven’t seen anyone mention the open cloud api on other posts about this issue with decal’s having different IDs. If anyone knows anything, please share with us!

1 Like

I find it a bit strange that we have to run another API request just to get the information of an operation? Surely it would be better to include all this operation information inside the response of the initial post request for creating an asset?

I know you’re just providing a tutorial but even if someone else reads this…

I personally agree with you but from the look of other API’s thats the way Roblox has decided to “layout” there API’s. It’s annoying having to send another request and honestly I find it pointless but I can’t change the way it works.