External Submissions
When making a submssion via your game server, there is some information that we will need about your experience in the submission that can help us identify you.
When making a submission from in game, you will need to set the content type to application/json and set your Authorization header to your stored API key (imported using the HTTPService in Roblox Studio).
Url = "api.roball.xyz/submissions/game_server", Method = "POST", Headers = { ["Content-Type"] = "application/json", ["Authorization"] = Key:AddPrefix("Bearer ") }, Body = Data
-- An example in Luau using HttpService:RequestAsyncInside the body which contains your data, 4 seperate JSON objects are required,
{ "submissionData": { ... }, "TargetedEventData": [ ... ], "playerData": { ... }}Submission Data
Section titled “Submission Data” "submissionData": { "submitter_id": 12345678, "submitter_name": "ExampleUser", "submission_date": "2025-08-16T12:34:56Z", "place_id": 987654321, "server_instance": "abcdef12-3456-7890-abcd-ef1234567890", "place_owner_id": 87654321, "match_type": "League"}Submission Data is the key data about your Game that allows us to help maintain your limits on submitting games per day to ensure you don’t breach caps. Shown above is an example of what it might look like:
* Submitter ID: The ID of the person submitting the match or "N/A"* Submitter Name: The username of the person submitting the match or "N/A"* Submission Date: use DateTime.now():ToIsoDate() to get a valid timestamp* Place ID: The ID of the place you are using.* Server Instance: The Server Instance of this game, use game.JobId* Place Owner ID: Use game.CreatorId* Match Type: This is the type of match you want to submit.Targeted Event Data
Section titled “Targeted Event Data”"TargetedEventData": [ { "eventName": "Goal", "eventData": ["PlayerOne", "PlayerTwo", "Team Blue","81"], "timestamp": "N/A" }, { "eventName": "YellowCard", "eventData": ["PlayerThree"], "timestamp": "N/A" }, { "eventName": "RedCard", "eventData": ["PlayerFour"], "timestamp": "N/A" }]Targeted Event Data is where your data for Targeted Events goes on during your game lands. It is expected to be an array of JSON objects. One for each event. Your league is required to determine which events you wish to capture with RoBall.
At present, football (soccer) is the only sport available on the site and the type of Targeted Events supported (defined by eventName) are Goal, YellowCard and RedCard. For each event, the following information is required:
- eventName: The name of the event as dictated above.
- eventData: An array (or table in Luau) that will contain the roblox username (or ID) of the person(s) involved as well as custom timestamps (in strings).
- For Goals, index 0 must contain the name of the person who scored. Index 1 can contain the name of the assister and index 3 can hold the Direct Team (the name of the Team which this goal occured on) while index 3 can hold the custom timestamp (which is not required).
- For Yellow Cards and Red Cards, index 0 must hold the name of the offender and index one can hold the Direct Team (the name of the Team which this card occured on) while index 2 can hold a custom timestamp if wanted
- timestamp: This can be a real timestamp by use of DateTime.now():ToIsoDate() or set to “N/A” for each event if you wish to not have it.
Non Targeted Event Data
Section titled “Non Targeted Event Data”"nonTargetedEventData": [ { "eventName": "Free Kick", "eventData": ["Team Green"], "timestamp": "N/A" }, { "eventName": "Foul", "eventData": ["PlayerThree","Player Five", "Team Blue"], "timestamp": "N/A" }]Non Targeted Event Data is where your data for Non Targeted Events goes on during your game lands. It is expected to be an array of JSON objects. One for each event. Your league is required to determine which non-targeted events you wish to capture with RoBall.
At present, football (soccer) is the only sport available on the site and the type of Non Targeted Events supported (defined by eventName) are set pieces (Free Kick, Corner Kick, Goal Kick, Penalties etc), fouls and saves. For each event, the following information is required:
- eventName: The name of the event as dictated above.
- eventData: An array (or table in Luau) that will contain the roblox username of the person(s) involved as well as custom timestamps (in strings).
- For all events excluding Saves and Fouls, index 0 must contain the name of the team reciving the set piece. Index 1 can contain the custom timestamp (which is not required).
- For Foul, index 0 must hold the name of the offender while index 1 must hold the name of the person being fouled, index 2 must hold the team of the person committing the foul. The custom timestamp and be stored in index 3 (which is not required).
- For Saves, index 0 must carry the name of the person making the save while index one must hold the name of the team the player was on when the save is made. The custom timestamp and be stored in index 2 (which is not required).
- timestamp: This can be a real timestamp by use of DateTime.now():ToIsoDate() or set to “N/A” for each event if you wish to not have it.
Player Data
Section titled “Player Data”"playerData": { "Blue": { "team_name": "Team Blue", "players": { "name": "PlayerOne", "displayName": "Player One", "id": 123456, "isGK": false }, { "name": "PlayerTwo", "displayName": "Player Two", "id": 234567, "isGK": false } } , "Green": { "team_name": "Team Green", "players": { { "name": "PlayerThree", "displayName": "Player Three", "id": 345678, "isGK": false }, { "name": "PlayerFour", "displayName": "Player Four", "id": 456789, "isGK": false }
} }}Player Data is where information about who has participated in your match is held. In here, 2 Seperate key value pairs are required. The names of each key should either be Blue or Green. The values in this object are arrays which store a json object for each player on said team.
Note that if 2 or more key value pairs are present, the 2 largest values (or array lengths in this case) will be used and generalised. This will not be useful if the game server has extra teams in your game server (such as spectators/fans or officials/referees).
Each object within each team’s array must contain the following:
- A team name (stored as team_name) which carries the name of the team you wish to see on the website.
- A players object with one object per each player on the given team. Each object should contain the following:
- Name (string): The player’s unique Roblox Username
- DisplayName (string): The player’s Roblox display name (Not including this? Use “N/A” for each player)
- Id (integer): The player’s roblox ID (player.userId)
- isGk (defaults to False): A boolean value dictating whether or not this player was a Goalkeeper in the match. This may be useful if:
- Your Goalkeeper teams are seperate from the rest of your teams (by which you will need to loop over the goalkeeper teams seperately to correctly identify them)
- You have seperate means for determing goal keepers
There is no limit on the number of players that can be represented but it’s important to remember that each player will carry their own record on the match page.
Sending and Results
Section titled “Sending and Results”Once the data has been placed in one large JSON Object and encoded (using the HTTPService), the request can be made. It is recommened to use pcall to catch any errors (such as an authorization failure or server failure).
The endpoint to use for game server submissions is: https.//api.roball.xyz/submissions/game_server, with the method set to POST.
Different response codes can mean different things here:
| Status | Meaning | When it happens |
|---|---|---|
200 | OK | Submission was sucess, you should recieve a JSON object back containing a match_id field holding the New match ID. |
400 | Bad Request | Some of the required data was missing or there was errors in the data provided. |
401 | Unauthorized | This could mean numerous errors: Missing API Key, Key did not match any league, the user making the submission is not permitted to do so (This is important for leagues without the Pro license). |
500 | Internal Server Error | Something went wrong on our end. Please try again and reach out to the Support Server if it persists. |