-
Notifications
You must be signed in to change notification settings - Fork 24
API Specification
WIP all contents of this page are subject to change.
Current API version: v1
(all current endpoints will of the form mac/<endpoint>/v1
)
Do:
- Remember best-practices when naming API endpoints.
- Remember JSON conventions
- verdicts: one of none/trusted/cheater/sus as set by user, but if masterbase reports convict then override the user setting in all scenarios
- tags: entirely separate set of strings. used to display if user is for example a friend, a MAC admin, etc
MAC and its client(s) are designed to be as modular and extensible as possible. The intention is to not only be completely transparent with what we are offering, but also to allow others to create, build and modify things as necessary and to fit their purpose/niche. We know that we cannot create a single product that solves everyones problems, but we can create an environment that allows everyone to solve their own or each others problems.
To allow this modularity and extensibility to extend to the API specification, we namespace our JSON keys at the top level. We also highly recommend that custom back or front ends that implement additional JSON keys do the same.
JSON keys mandatory to the function of the base MAC client (both the front and backend) are considered 'crucial' keys. These will be mapped behind a mac
top level key.
Returns the full game object, including server and lobby details, as well as all players currently in that server/lobby.
GET mac/game/v1
None
No payload required. This endpoint should be hit every time the player joins a new lobby/game. To update a lobby, use
mac/user/v#
instead.
{
}
Code:
import requests
base = "..."
response = requests.get(f"{base}/mac/game/v1")
Parameter | Type | Description |
---|---|---|
players | list | A list of objects of all currently in-game players. (See mac/user/v1 for info on player objects) |
map | string | The current game map |
ip | string | The current server IP as returned from status . |
maxPlayers | integer | The max players allowed in the lobby (this may differ from the actual value) |
gamemode | object | The gamemode object, which contains the type (string), matchmaking and vanilla flags |
"server": {
"players": [
{
"isSelf": false,
"name": "x",
"steamInfo": {
"accountName": "x",
"pfp": "x",
"steamID": "x",
"vacBans": "x",
//...Any Other info you can find
},
"gameInfo": {
"team": "RED"
"ping": 64,
"kills": 0,
"deaths": 0,
//...
},
"tags": ["Friend", "Convicted", "MAC User"],
},
{
//....
}
],
"map": "X",
"ip": "X",
"hostname": "X",
"maxPlayers": 32,
"numPlayers": 17,
"gamemode": {
"matchmaking": false,
"type": "Arena",
"vanilla": false
}
}
Response contains server data, game details such as map, IP and gamemode, and a list of every player in the game (including self) Possible tags: "Recently Disconnected", "Joining", "Steam Friend", "Same regional DB", "Competitive Player", "MegaAntiCheat Admin" Possible verdicts: "none", "cheater", "sus", "trusted", "convict"
Returns all relevant information that the backend has on the requested users.
PUT mac/user/v1
Parameter | Type | Description | Requirement Type |
---|---|---|---|
steamID64 | list | A list of steamID64's to retrieve data on | Optional |
name | list | A list of in-game names to retrieve data on | Optional |
One or both of the optional params may be specified.
{
"steamID64": ["abc", "xyz"],
"name": ["foo", "bar"],
}
Code:
import requests
base = "..."
params = {"steamID64": ['76561198210264393']}
response = requests.get(f"{base}/mac/user/v1", params=params)
Parameter | Type | Description |
---|---|---|
players | list | A list of player objects, containing the intersection of the set of players requested and the set of players in the game. |
errors | object | An object containing a key-value pair for each steamID64 or name that the backend failed to find data on, and the reason. |
<player>.isSelf | bool | If this player object represents the player currently running this client. |
<player>.name | string | the in-game name of this player, which may or may not vary from the steam name ('personaname' a.k.a <player>.steamInfo.accountName ) |
<player>.steamInfo | object | an object containing all of the data returned from the steam API on this steam account. Some keys will be renamed. See here for more details. |
<player>.gameInfo | object | an object containing all of the game data captured by the backend relevant to this player (i.e. team, score, ping) |
<player>.tags | list | The set of all tags collated from local, regional and remote, with consideration for tag precedence. |
{
"players": [
{
"isSelf": false,
"name": "x",
"steamInfo": {
"accountName": "x",
"pfp": "x",
"steamID": "x",
"vacBans": "x",
//...Any Other info you can find
},
"gameInfo": {
"team": "RED"
"ping": 64,
"kills": 0,
"deaths": 0,
//...
},
"tags": ["Friend", "Convicted", "MAC User"],
},
{
"isSelf": false,
"name": "foo",
//....
}
],
"errors": {
"xyz": "Player not found in game.",
"bar": "Player not found in game."
},
}
The response shall contain a
players
object for each player that was both provided in the payload, and found in the game. And anerrors
object for each player that the back-end could not return aplayers
object for
A post to the user
endpoint can be used to update locally stored data on the given user. Most significant is the ability to update the local verdict on any number of given users.
POST mac/user/v1
Parameter | Type | Description | Requirement Type |
---|---|---|---|
object | an object keyed by a users steamID64, containing an arbitrary number of namespaced key-value pairs of user persistent data to update. | Required |
{
"76561198210264393": {
"mac": {
"tag": ["Suspicious"],
},
"anotherNamespace": {
"customKey": "some custom value",
}
},
"76561198782264188": {
"mac": {
"tag": ["Suspicious"],
},
}
}
Code:
import requests
base = "..."
params = {"tag": {'76561198210264393': "Cheater", '76561198782264188': "Bot"}}
response = requests.post(f"{base}/mac/user/v1", params=params)
The
localVerdict
object may contain any number of"<steamID64>": "verdict",
key-value pairs, to enable bulk updates of the local verdict.
Parameter | Type | Description |
---|---|---|
errors | object | an object of key-value pairs of steamID64's and the reason why a given player could not be updated. |
{
"errors": {}
}
The response shall contain an errors object that would detail any errors encountered whilst trying to update the specified players stored data.
Returns the full list of locally stored user preferences concern the client (both front-end and back)
GET mac/pref/v1
None
{
}
Code:
import requests
base = "..."
response = requests.get(f"{base}/mac/pref/v1")
Parameter | Type | Description |
---|---|---|
keyNameTBA | object | A dummy param for the response payload meant to imitate the preference key name and associated value/object |
Data spec TBC, then this will be updated.
{
"mac": {
"keyNameTBA": {}
},
"anotherNamespace": {
"keyNameTBA": {},
}
}
The response shall be an object containing a set of key-value pairs where the key is the name of the stored user pref, and the value is whatever type is stored under that key (can be literal, string, object or list)
A post to pref
is to update user preferences and settings as interacted with via the front-end client.
POST mac/pref/v1
Parameter | Type | Description | Requirement Type |
---|---|---|---|
keyNameTBA | object | an object containing the updated value of the given user preference key name. | Optional |
Any number of keys may be specified in the params.
{
"mac": {
"autokick_enabled": True,
"autokick_interbal": 60,
},
"anotherNamespace": {
"xyz": { ... }
},
}
Code:
import requests
base = "..."
params = {"autokick_enabled": True, "autokick_interbal": 60}
response = requests.post(f"{base}/mac/pref/v1", params)
Parameter | Type | Description |
---|---|---|
changes | object | An object containing the key-value pairs of keys that were changed, and the value of what they now represent |
errors | object | An object containing all of the keys that could not be changed, and the reason why |
{
"changes": {
"mac": {
"autokick_enabled": True
}
}
"errors": {
"anotherNamespace": {
"autokick_interbal": "A key of that name does not exist."
}
}
}