Welcome to the Mhanndalorian Bot, a Discord bot for the mobile game Star Wars Galaxy of Heroes. Now offering the Mhanndalorian API for developers.
The Mhanndalorian API is a special API able to provide read only access to game data that requires authentication to get. The use of this API is offered through the Patreon subscription tiers listed below and requires an approval process.
Developer API Access Membership
$1
per month
per month
Developer API Access Membership will allow you access to the following features:
Mhanndalorian Bot Discord
- The SWGOH Registry, a collective database of player's SWGOH allycodes and their Discord user IDs.
-
Retrieve authenticated game data for your accounts and your end users accounts1 for the following data.
- Territory War Battle Logs
- Territory War Leaderboards
- Territory Battles Battle Logs
- Territory Battles Leaderboards
- Active Raids
- Player Inventory
- Grand Arena Championships
Mhanndalorian Bot Discord
Bot Mhann#2253
1Access to end user accounts is only upon approval of your intended usage based on a thorough review of your tool during the application process.
Getting Started
Getting access to the api
- In your Patreon account go to Settings and link your Discord account. This will make sure you gain access to all Subscriber benefits in Discord.
- Join the Mhanndalorian Bot Discord server and contact one of the individuals listed in the membership tier.
- Upon approval of your usage you will be instructed how to purchase the subscription.
- Install Mhanndalorian Bot into the support Discord for your tool. All the default permissions are necessary for the bot to function properly.
- After installing Mhanndalorian Bot, you will need to run the following commands in the discord channel:
/register
and enter your ally code. You must verify your account following the instructions from the bot. - Once registered, your api key will be generated and sent to you when completed.
Using the api
All users must register with the Mhanndalorian Bot and run the/eaconnect
command in the Discord channel for the bot to explicitly allow access to the authenticated game data for their verified ally code. In order to access the endpoints, you will need to form an HTTP request as shown below. All data will be returned to you in JSON format. There are two options for generating API calls. Option #1 is simpler to setup, but is less secure as your API key is transmitted in the header. Option #2 requires additional setup, but is very secure as it uses an HMAC signature and your API key is not transmitted. Below, there are additional details regarding how to generate the HMAC signature along with various code examples.
Generating the call
Request Method: POST
HEADERS (option #1 - less secure):
Content-Type: application/json
Accept-Encoding: br,gzip,deflate
api-key: your-api-key
x-discord-id: Your Discord Id *
HEADERS (option #2 - very secure):
Content-Type: application/json
Accept-Encoding: br,gzip,deflate
x-timestamp: Unix timestamp in milliseconds
Authorization: HMAC signature
x-discord-id: Your Discord Id *
BODY (All endpoints except /api/guild):
*x-discord-id header field is required if:
HEADERS (option #1 - less secure):
Content-Type: application/json
Accept-Encoding: br,gzip,deflate
api-key: your-api-key
x-discord-id: Your Discord Id *
HEADERS (option #2 - very secure):
Content-Type: application/json
Accept-Encoding: br,gzip,deflate
x-timestamp: Unix timestamp in milliseconds
Authorization: HMAC signature
x-discord-id: Your Discord Id *
BODY (All endpoints except /api/guild):
{ "payload": { "allyCode": "561963325" //Ally code you are looking up "enums": boolean } }BODY (/api/guild endpoint):
{ "payload": { "guildId": "B2-VYdu3SEevuO3NTCW52Q" //Guild being looked up "enums": boolean } }
- Your application is approved to authenticate as other users
- You are using HMAC with the /api/database endpoint.
- You are using any non-authenticated endpoints.
Endpoints
All endpoints are documented below. Clicking an endpoint will show a sample response. Some field values have been replaced with "removed" but are available in an actual response. Requests will be sent as a POST to the following url, adding the desired endpoint to the end of it:
https://mhanndalorianbot.work/api
- Authenticated Endpoints (breaks connection):
/activeraid
- Fetches data about the current raid.
/events
- Fetches data about current and upcoming events in game.
/gac
- Fetches Grand Arena Championship map data of all squads placed on defense, active match data, and event leaderboard data.
/inventory
- Fetches inventory including unequipped mods, currencies, materials, and gear.
/leaderboard
- Fetches data about current squad arena and fleet arena leaderboard.
/squadfetch
- Fetches all saved squad and fleet loadouts from your account.
/tb
- Fetches Territory Battle data including platoons and leaderboards.
/tbleaderboardhistory
- Fetches historical leaderboard data for the last 4 TBs.
/tblogs
- Fetches TB log data (Details about every action that happens in TB).
/tw
- Fetches Territory War data.
/twleaderboard
- Fetches Territory War leaderboard data for the guild including banners earned for attack, defend, total and rogue actions.
/twlogs
- Fetches Territory War log data including attacks, deployments, holds, and preloads.
- Non-Authenticated Endpoints (Does not break connection):
/database
- Used to interact with the SWGOH registry. This endpoint works a bit different than other endpoints. See documentation here.
/guild
- Fetches guild data including members (with brief details), recentRaidResult, recentTerritoryWarResult, profile, and guild reset data.
/player
- Fetches player data including name, playerId, allyCode, guildId, guildName, lastActivityTime, profileStat, playerRating, rosterUnits, datacrons, and more.
HMAC Details
To prevent tampering with messages, replay attacks, unauthorized access, and ensure API key security, an implementation of hash message authentication code (HMAC) is provided. When using the API with an HMAC signaure, the api-key field is removed from the headers and the Authorization and x-timestamp fields are included. The Authorization field contains the HMAC signature and the x-timestamp field is the Unix epoch time in milliseconds.The SHA256 hash algorithm is used, when creating the HMAC signature. The HMAC should add these attributes of the message in this order:
- Request time (the same value as in the x-timestamp)
- Request method (POST)
- Request path (the API path, such as /api/inventory)
- The MD5 hash of the stringified version of the JSON request body in hex format.
// Generate Unix epoch time in milliseconds
const timestamp = Date.now();
// Create a base HMAC object using SHA256 algorithm
const hmac = crypto.createHmac('sha256', apiKey);
// Add the request timestamp to the HMAC object
hmac.update(timestamp.toString());
// Add the HTTP method (in upper case) to the HMAC object
hmac.update(method.toUpperCase());
// Add the API endpoint URI (in lower case) to the HMAC object
hmac.update(endpoint.toLowerCase());
// Create a serialized string from the payload JSON
const payloadString = JSON.stringify(payload);
// Generate MD5 hash of the payload string
const payloadHash = crypto
}
.createHash('md5')
.update(payloadString)
.digest('hex');
// Add the payload hash to the HMAC object
hmac.update(payloadHash);
// Calculate the HMAC signature
const HMACSignature = hmac.digest('hex');
// Return the HMAC signature and timestamp
return {x-timestamp: timestamp, Authorization: HMACSignature};"""HMAC signing function for Mhanndalorian Bot APIs.
Args:
"""
# Get the current time in milliseconds
req_time = str(int(time.time() * 1000))
# Create a base HMAC object using SHA256 algorithm
hmac_obj = hmac.new(key=api_key.encode(), digestmod=hashlib.sha256)
# Add the request timestamp to the HMAC object
hmac_obj.update(req_time.encode())
# Add the HTTP method (in upper case) to the HMAC object
hmac_obj.update(method.upper().encode())
# Add the API endpoint URI to the HMAC object
hmac_obj.update(endpoint.lower().encode())
# Create a serialized string from the payload JSON/dictionary object
payload_str = dumps(payload, separators=(',', ':'))
# Generate MD5 hash of the payload string
payload_hash = hashlib.md5(payload_str.encode()).hexdigest()
# Add the payload MD5 hash to the HMAC object
hmac_obj.update(payload_hash.encode())
# Return the HTTP headers that must be included with the HMAC signed request
return {"x-timestamp": req_time, "Authorization": hmac_obj.hexdigest()} api_key: The API key assigned by Mhanndalorian Bot
method: The HTTP method of the request
endpoint: The API endpoint URI
payload: Dictionary containing the payload of the HTTP request
Returns:Dictionary containing the 'x-timestamp' and 'Authorization' headers for the signed request
// Generate Unix epoch time in milliseconds
long timestamp = Instant.now().toEpochMilli();
// Create a base HMAC object using SHA256 algorithm
SecretKeySpec secretKeySpec = new SecretKeySpec(apiKey.getBytes(), "HmacSHA256");
Mac mac = Mac.getInstance(secretKeySpec.getAlgorithm());
mac.init(secretKeySpec);
// Add the request timestamp to the HMAC object
mac.update(String.valueOf(timestamp).getBytes());
// Add the HTTP method (in upper case) to the HMAC object
mac.update(method.toUpperCase().getBytes());
// Add the API endpoint URI (in lower case) to the HMAC object
mac.update(endpoint.toLowerCase().getBytes());
// Create a serialized string from the payload JSON
ObjectMapper objectMapper = new ObjectMapper();
String payloadString = objectMapper.writeValueAsString(payload);
// Generate MD5 hash of the payload string
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(payloadString.getBytes());
byte[] payloadHash = digest.digest();
// Add the payload hash to the HMAC object
mac.update(payloadHash);
// Calculate the HMAC signature
String HMACSignature = new String(mac.doFinal());
// Return the HMAC signature and timestamp
return Map.of(
}
"x-timestamp", timestamp,
"Authorization", HMACSignature
);
/// <summary>
/// HMAC signing function for Mhanndalorian Bot APIs.
///
/// Args:
/// api_key: The API key assigned by Mhanndalorian Bot
/// method: The HTTP method of the request
/// endpoint: The API endpoint URI
/// payload: Dictionary containing the payload of the HTTP request
///
/// Returns:
/// Dictionary containing the 'x-timestamp' and 'Authorization' headers for the signed request
/// </summary>
public static Dictionary hmac_sign(string api_key, string method, string endpoint, Dictionary payload)
{
}
// Get the current time in milliseconds
string req_time = ((long)(DateTimeOffset.Now.ToUnixTimeMilliseconds())).ToString();
// Create a base HMAC object using SHA256 algorithm with the API key as key
// In C#, we'll use HMACSHA256 which computes the HMAC in one shot.
// We'll simulate sequential updates by concatenating all parts into one message.
// Add the request timestamp to the message
string message = req_time;
// Add the HTTP method (in upper case) to the message
message += method.ToUpperInvariant();
// Add the API endpoint URI (in lower case) to the message
message += endpoint.ToLowerInvariant();
// Create a serialized string from the payload JSON/dictionary object using minimal separators
// In System.Text.Json the default is a minified JSON string.
string payload_str = JsonSerializer.Serialize(payload);
// Generate MD5 hash of the payload string
using (MD5 md5 = MD5.Create())
{
{
}byte[] payloadBytes = Encoding.UTF8.GetBytes(payload_str);
byte[] md5HashBytes = md5.ComputeHash(payloadBytes);
// Convert MD5 hash bytes to hexadecimal string (lowercase)
StringBuilder sb = new StringBuilder();
foreach (byte b in md5HashBytes)
{
}
// Compute the HMAC SHA256 signature using the concatenated message
byte[] keyBytes = Encoding.UTF8.GetBytes(api_key);
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
string authorization;
using (HMACSHA256 hmac = new HMACSHA256(keyBytes))
{
sb.Append(b.ToString("x2"));
}
string payload_hash = sb.ToString();
// Add the payload MD5 hash to the message
message += payload_hash;
byte[] hashBytes = hmac.ComputeHash(messageBytes);
// Convert HMAC hash bytes to hexadecimal string (lowercase)
StringBuilder sb = new StringBuilder();
foreach (byte b in hashBytes)
{
}
// Return the HTTP headers that must be included with the HMAC signed request
return new Dictionarysb.Append(b.ToString("x2"));
}
authorization = sb.ToString();
{ "x-timestamp", req_time },
{ "Authorization", authorization }
};