Open Cloud | Messaging Service API (node.js)

Messaging Service API

Greetings everyone!

Today I will be creating a tutorial on how you can use the kinda recent Open Cloud Messaging Service API. This API in the Open Cloud is based off the MessagingService on Roblox but allow us to public messages from outside of Roblox in our own application. I have seen some people not sure how to use this (and I cannot blame them as the docs are not the best to be honest).

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 Messaging Service API which are written using JavaScript (in the runtime environment node.js) and Lua/Luau. Sending requests will be different for different programming languages however the basic idea of how to use the Messaging Service API are the same.

Tutorial Contents:

  • An explanation of what this Open Cloud API is and some uses of this (there are many so we will just go over a few).

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

  • Showing some examples of what this API can allow us to do.

  • Going over some basic error management from the documentation but I will go into a little more details.

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


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

The Messaging Service API is a quite recent addition to the Roblox Open Cloud. It allows us to send a “message” to all of the servers inside of an experience. This new API is based on the Messaging Service which we can use inside of experiences to communicate information between all the servers. The Messaging Service API allows us to do so much more then we could before allowing us to do things like live actions on servers or live messages on all servers without having to join each server to do an announcement or go in-game to use the Messaging Service to do the announcement. This API allows us to do announcements in all servers outside of Roblox for example in a Discord bot or website.

You may be wondering what type of things we can create with this API so I will give some examples of things this allow us to do. One thing which it allows us to do is create live actions in a server outside of Roblox. For example we could use this Messaging Service to create a live kick system where we can kick a player out of a server they are in from a Discord server. We could do this before by using long polling which is better then short polling however it was still not super beneficent with possible problems. With this Messaging Service API it allows us to send a message to all of the servers to see if the user is in a server which will allow us to kick a user basically instantly.

How to use the Messaging Service API?

To use the Messaging Service 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. 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 “Messaging Service API” option and press the white button which says “Add API System”. You then search for your experience, add the experience and then on the select down menu where it allows you to add operations click “Publish”. 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.

Next we can get into the main programming itself. If we take a look in the documentation for this Message Service API we can see that the type of request we are sending is a POST request to the endpoint of https://apis.roblox.com/messaging-service/v1/universes/{universeId}/topics/{topic}. Before we can do anything though we need to know how to get the universe ID and also explain what the “topic” is so we can add this to the URL we will be sending the request to. We can get the universe ID by going to https://create.roblox.com/creations, clicking on the experience we want to get the universe ID of and then get the ID from the URL on the page. Please note that the number/ID on the URL in create.roblox.com and just a normal experience page on the Roblox site are different and only the one from create.roblox.com is the correct one we need. The next thing for the URL we need is this “topic”. The topic is basically just what we want to identify the message we send as so that we can detect it in our Roblox server. For example you could have a kick command as the topic of DiscordKick or something else like that.

Now we have the URL sorted out we can now move onto the message part of our request. If we take a look into the documentation example we can see that we will be placing our message which we will be sending through in the body of the POST request. Depending on what you are using (and what you want to send through) this Message Service API for you may need to turn the message we are sending through into a string. If we are just sending one single message (like an announcement) we can just send this as a string and don’t need to convert it. A time we may need to convert the message to a string is if we want to send more then one value through (for example for a live kick system we may want to send the user ID of the user but also the reason for the kick). We can do this by using JSON.stringify(). Below I will leave an example of when you should stringify the message and when you can just leave it. (depending on how we send it now will change how we use the message on the Roblox side)

image

Next I will move onto the last bit of our request which is our headers. Inside of our request header is our API key and the type of content we are passing through. For my API key I have stored it inside of a .env environment file for security reasons and so you cannot see it but where the “x-api-key” is where your API key we copied before should be placed. For the content type we can just keep it to application/json and it should work fine. Once we have done all of this we should really have everything complete. In my example which I will have below it is for an announcement Discord command (or at least the consent behind it). The example below will also have a catch which is to catch any errors and a simple error handing system via if statements but I will explain the errors you could get later on in this tutorial.

Example Module:

const axios = require('axios').default

module.exports.MessageSend = async function MessageSend(Message, Topic, interaction) {

    const response = await axios.post(
        `https://apis.roblox.com/messaging-service/v1/universes/${process.env.UNIVERSE_ID}/topics/${Topic}`,
        {
            'message': Message
        },
        {
            headers: {
                'x-api-key': process.env.OPENCLOUD_KEY,
                'Content-Type': 'application/json'
            }
        }
    ).catch(err =>{
        console.log(err.response.status)
        if (err.response.status == 401) return interaction.reply(`**Error:** API key not valid for operation, user does not have authorization`)
        if (err.response.status == 403) return interaction.reply(`**Error:** Publish is not allowed on universe.`)
        if (err.response.status == 500) return interaction.reply(`**Error:** Server internal error / Unknown error.`)
        if (err.response.status == 400){
            if (err.response.data == "requestMessage cannot be longer than 1024 characters. (Parameter 'requestMessage')") return interaction.reply(`**Error:** The request message cannot be longer then 1024 characters long.`)
            console.log(err.response.data)
        }
  })
    if (response){
        if (response.status == 200) return interaction.reply(`Message sucessfully sent!`)
        if (response.status != 200) return interaction.reply(`**Error:** An unknown issue has occurred.`)
    }
}

Now I will be quickly going over how we can receive this message on the Roblox side. If you know how to use the Roblox Message Service for Roblox experiences you should already know how to do this however you may not 100% know due to it being slightly different when passing through a table. Due to the way that the Messaging Service works we should also have our code inside of a pcall function in case of any errors with the code however to ensure the code below looks simple I have not wrapped the below in a pcall function however it’s highly recommended you do.

If we just send the request with one message we can just get the message from the SubscribeAsync event/function and then get the Data from this. This works fine for simple things such as a global announcement system however what if you want to create a live kick system which allow us to show a reason for the kick but we also then need the user ID. Like I said before in this case we require to turn the table into a JSON string which we can then send to our servers. Unlike the single message one we cannot just get the data from the message. Rather we require to “JSONDecode” method of the HTTP service to decode our table. Once we have decoded our table which was in a string format we can now simply just get the data out of the table like we would normally for a JSON table.

Roblox Example Announcement:

MS:SubscribeAsync("GlobalAnnoucement", function(msg)

game.ReplicatedStorage.GlobalAnnoucement:FireAllClients(msg.Data)

end)

Roblox Example Kick:

MS:SubscribeAsync("DiscordKick", function(msg)
	for i, v in pairs(game.Players:GetPlayers()) do
		if v.UserId == HS:JSONDecode(msg.Data).UserID then
			v:Kick("You have been kicked from this server for the reason of "..HS:JSONDecode(msg.Data).Reason)
		end
	end
end)

Messaging Service API Showcase

I will now be going over some simple things that I have created with the messaging service (and also for the currency add one the Open Cloud Datastore API a bit). These where created quickly so are quite simple examples however you can always get super advanced with this Messaging Service API.

I will be making the Roblox side code and the JS code for the below showcases open sourced, I just want to finish a few more commands and once done I will create a post about it and update you all on this post here.

Live Discord Command Server Kick:

Live Discord Command Global Message:

Live Discord Command Currency Add:

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 Messaging Service API as stated inside of the documentation are:

Some simple error handling code for the Discord bot commands I showcased above:

Conclusion of tutorial

I will now be ending my tutorial on how to use the Messaging Service API. I hope this tutorial helped some people and is more detailed then 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:

https://create.roblox.com/docs/open-cloud/messaging-service-api
https://devforum.roblox.com/t/announcing-messaging-service-api-for-open-cloud

YouTube Vid Made By Me:

34 Likes

I think the videos arent working

but nice tutorial overall

1 Like

Yea it seems to be working for me but someone told me the exact same that the videos are not working. I will upload them to YouTube and them implement them that way.

Edit: I have now changed all the vids for a YouTube uploaded copy so should work. If anyone have any other issues with the post please ensure to tell me.

1 Like

Thank you, Thank you, THANK YOU!!!

I’ve found MessagingService so confusing until reading this tutorial.

I appreciate you making this.

2 Likes

Eagerly awaiting the Discord announcement code. Thanks OP

1 Like

Also @SummerLife if you can include a full guide on how you crafted Discord Kick, Announce, and Currency Add in specific on your update, you’d be a godsend. Thank you again!

1 Like

All it really is you send the request, you use subscribeAsync to get when a message just loop through all the players to see if there is someone with that ID in the server and if so kick. I did leave some code for the kick in the tutorial.

I will have kick as one of the commands for the Discord bot thing I wanna add as a resource when I get round to finishing it.

Hello, i have a doubt at

const response = await axios.post(
        `https://apis.roblox.com/messaging-service/v1/universes/${process.env.UNIVERSE_ID}/topics/${Topic}`,
        {
            'message': Message
        },

can the Message in 'message': Message
be a JSON object?
I understand this is an example module but if I were to add this without like a module can I put {username: "Roblox", reason: "Example reason."} in place of Message if I wanted to have a table as the response?

(Edit): I have tried this and results in a error: Request body not in correct format.
Here is my code:

{
   'message': {user:"Roblox", toggleHeadlights: true},
},

Yes and no. The message that you put through must from my knowledge must be a string due to it wanting it in a string format. A way you can bypass this however is by converting the JSON table into a string via JSON.stringify() and then just convert the code back to JSON in the Roblox side as I said in the post.

Convert the {user:"Roblox", toggleHeadlights: true} into a string and then use JSONDecode on Roblox to get the table again to get the values.

Just ensure anything you do also follow the rate limits.

alright, I see what to do. Thank you soo much for taking time from your day to help me :smiley:

1 Like

I learnt a lot from this tutorial. If I’m being real this tutorial mostly cleared my API problem. I appreciate the tutorial!

But, confused about one thing (haven’t checked yet), but in the error handling part of the code in js, aren’t there supposed to be 3 equal signs (=) instead of 2? Or am I wrong? Please correct me, because I’m not a professional at js.

1 Like

This looks amazing, can’t wait to try it out. Seems a lot better than my current method of contacting an external database and then having the game read from that whenever something changes.

Also @AridTheDev, in JS, == checks if the variable is equal whilst ignoring datatypes, and === also checks if the datatypes are the same, therefore in this use case == should work fine.

2 Likes

Ah, I see. I can’t really match my luau skills with js, lol. Thanks!

2 Likes

Hey. Came back with a problem. All my other slash commands do register, but this one doesn’t. Where’s my problem?

[Code removed]

Edit: Fixed it by removing the .default while requiring axios.

Update!

I have now made a YouTube tutorial on the messaging service API! Feel free to check it out below:

1 Like

Am I able to subscribe a message on open cloud? The opposite side of publish…

1 Like

Currently no. At the moment the messaging service only has one API endpoint which is to Publish messages. I am unsure if Roblox will add this as a feature but the only real way that Roblox could do this would be via a websocket because of the way that events work and I know that Roblox in the past have been against websockets due to “security” issues.

1 Like