Core Cells
A scalable, secure REST API to connect any game to a shared multiplayer backend. Manage users, project keys, JSON game states, matchmaking, and RTS sessions — all from one unified interface.
Everything you need to build, deploy, and scale multiplayer games
Each project gets a unique key for secure access and complete data isolation between games.
Players register once and can access multiple games with a single account.
Built-in support for matchmaking, real-time game sessions, and player state management.
Comprehensive REST API for multiplayer game development
Integrate our API into your game with our easy-to-use SDKs
Seamlessly integrate the API into your Unity projects with our C# SDK. Handles authentication, HTTP requests, JSON parsing, and project key management.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace michitai
{
/// <summary>
/// Provides a client for interacting with the MICHITAI Game API.
/// Handles authentication, player management, game rooms, and actions.
/// </summary>
public class GameSDK
{
private readonly string _apiToken;
private readonly string _apiPrivateToken;
private readonly string _baseUrl;
private static readonly HttpClient _http = new HttpClient();
private ILogger? _logger;
private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
/// <summary>
/// Initializes a new instance of the GameSDK class.
/// </summary>
/// <param name="apiToken">The public API token for authentication.</param>
/// <param name="apiPrivateToken">The private API token for privileged operations.</param>
/// <param name="baseUrl">Base URL of the API (default: https://api.michitai.com/v1/php/).</param>
public GameSDK(string apiToken, string apiPrivateToken, string baseUrl = "https://api.michitai.com/v1/php/", ILogger? logger = null)
{
_apiToken = apiToken;
_apiPrivateToken = apiPrivateToken;
_baseUrl = baseUrl.EndsWith("/") ? baseUrl : baseUrl + "/";
_logger = logger;
}
/// <summary>
/// Constructs a URL for API requests with the base URL, endpoint, and authentication token.
/// </summary>
/// <param name="endpoint">The API endpoint path.</param>
/// <param name="extra">Additional query string parameters (optional).</param>
/// <returns>Fully constructed URL string with authentication.</returns>
private string Url(string endpoint, string extra = "")
{
return $"{_baseUrl}{endpoint}?api_token={_apiToken}{extra}";
}
/// <summary>
/// Sends an HTTP request to the API and deserializes the JSON response.
/// </summary>
/// <typeparam name="T">The type to deserialize the response into.</typeparam>
/// <param name="method">The HTTP method (GET, POST, PUT, etc.).</param>
/// <param name="url">The URL to send the request to.</param>
/// <param name="body">The request body (optional). Will be serialized to JSON if provided.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the deserialized response.</returns>
private async Task<T> Send<T>(HttpMethod method, string url, object? body = null) where T : class
{
var req = new HttpRequestMessage(method, url);
if (body != null)
{
string json = JsonSerializer.Serialize(body, _jsonOptions);
req.Content = new StringContent(json, Encoding.UTF8, "application/json");
}
var res = await _http.SendAsync(req);
string str = await res.Content.ReadAsStringAsync();
T response;
try
{
response = JsonSerializer.Deserialize<T>(str, _jsonOptions)!;
}
catch(JsonException)
{
_logger?.Warn(str);
throw;
}
return response;
}
/// <summary>
/// Registers a new player in the game.
/// </summary>
/// <param name="name">Display name for the player.</param>
/// <param name="playerData">Additional player data as an object (will be serialized to JSON).</param>
/// <returns>Task containing player registration response with player ID and private key.</returns>
public Task<PlayerRegisterResponse> RegisterPlayer(string name, object playerData)
{
return Send<PlayerRegisterResponse>(
HttpMethod.Post,
Url("game_players.php"),
new { player_name = name, player_data = playerData }
);
}
/// <summary>
/// Authenticates a player using their player token.
/// </summary>
/// <param name="playerToken">The player's authentication token.</param>
/// <returns>Task containing player authentication response with player information.</returns>
public Task<PlayerAuthResponse> AuthenticatePlayer(string playerToken)
{
return Send<PlayerAuthResponse>(
HttpMethod.Put,
Url("game_players.php", $"&game_player_token={playerToken}")
);
}
/// <summary>
/// Retrieves a list of all players (requires private API token).
/// </summary>
/// <returns>Task containing list of players and total count.</returns>
public Task<PlayerListResponse> GetAllPlayers()
{
return Send<PlayerListResponse>(HttpMethod.Get, Url("game_players.php", $"&api_private_token={_apiPrivateToken}"));
}
/// <summary>
/// Retrieves game data for the current game.
/// </summary>
/// <returns>Task containing the game data response.</returns>
public Task<GameDataResponse> GetGameData()
{
return Send<GameDataResponse>(HttpMethod.Get, Url("game_data.php"));
}
/// <summary>
/// Updates the game data (requires private API token).
/// </summary>
/// <param name="data">The game data to update.</param>
/// <returns>Task indicating success or failure of the update.</returns>
public Task<SuccessResponse> UpdateGameData(object data)
{
return Send<SuccessResponse>(HttpMethod.Put, Url("game_data.php", $"&api_private_token={_apiPrivateToken}"), data);
}
/// <summary>
/// Retrieves data for a specific player.
/// </summary>
/// <param name="playerToken">The player's authentication token.</param>
/// <returns>Task containing the player's data.</returns>
public Task<PlayerDataResponse> GetPlayerData(string playerToken)
{
return Send<PlayerDataResponse>(
HttpMethod.Get,
Url("game_data.php", $"&game_player_token={playerToken}")
);
}
/// <summary>
/// Updates data for a specific player.
/// </summary>
/// <param name="playerToken">The player's authentication token.</param>
/// <param name="data">The data to update for the player.</param>
/// <returns>Task indicating success or failure of the update.</returns>
public Task<SuccessResponse> UpdatePlayerData(string playerToken, object data)
{
return Send<SuccessResponse>(
HttpMethod.Put,
Url("game_data.php", $"&game_player_token={playerToken}"),
data
);
}
/// <summary>
/// Retrieves the current server time.
/// </summary>
/// <returns>Task containing the server time in various formats.</returns>
public Task<ServerTimeResponse> GetServerTime()
{
return Send<ServerTimeResponse>(
HttpMethod.Get,
Url("time.php")
);
}
/// <summary>
/// Creates a new game room.
/// </summary>
/// <param name="gamePlayerToken">The player's authentication token.</param>
/// <param name="roomName">Name for the new room.</param>
/// <param name="password">Optional password for the room.</param>
/// <param name="maxPlayers">Maximum number of players allowed in the room (default: 4).</param>
/// <returns>Task containing the room creation response.</returns>
public Task<RoomCreateResponse> CreateRoomAsync(
string gamePlayerToken,
string roomName,
string? password = null,
int maxPlayers = 4)
{
return Send<RoomCreateResponse>(
HttpMethod.Post,
Url("game_room.php/rooms", $"&game_player_token={gamePlayerToken}"),
new
{
room_name = roomName,
password = password,
max_players = maxPlayers
}
);
}
/// <summary>
/// Retrieves a list of all available game rooms.
/// </summary>
/// <returns>Task containing the list of rooms.</returns>
public Task<RoomListResponse> GetRoomsAsync()
{
return Send<RoomListResponse>(
HttpMethod.Get,
Url("game_room.php/rooms")
);
}
/// <summary>
/// Joins an existing game room.
/// </summary>
/// <param name="gamePlayerToken">The player's authentication token.</param>
/// <param name="roomId">ID of the room to join.</param>
/// <param name="password">Room password if required.</param>
/// <returns>Task containing the join room response.</returns>
public Task<RoomJoinResponse> JoinRoomAsync(
string gamePlayerToken,
string roomId,
string? password = null)
{
return Send<RoomJoinResponse>(
HttpMethod.Post,
Url($"game_room.php/rooms/{roomId}/join", $"&game_player_token={gamePlayerToken}"),
password != null ? new { password = password } : new { password = "" }
);
}
/// <summary>
/// Leaves the current room.
/// </summary>
/// <param name="gamePlayerToken">The player's authentication token.</param>
/// <returns>Task indicating success or failure of leaving the room.</returns>
public Task<RoomLeaveResponse> LeaveRoomAsync(string gamePlayerToken)
{
return Send<RoomLeaveResponse>(
HttpMethod.Post,
Url("game_room.php/rooms/leave", $"&game_player_token={gamePlayerToken}")
);
}
/// <summary>
/// Retrieves a list of players in the current room.
/// </summary>
/// <param name="gamePlayerToken">The player's authentication token.</param>
/// <returns>Task containing the list of players in the room.</returns>
public Task<RoomPlayersResponse> GetRoomPlayersAsync(string gamePlayerToken)
{
return Send<RoomPlayersResponse>(
HttpMethod.Get,
Url("game_room.php/players", $"&game_player_token={gamePlayerToken}")
);
}
/// <summary>
/// Sends a heartbeat to keep the player's session alive.
/// </summary>
/// <param name="gamePlayerToken">The player's authentication token.</param>
/// <returns>Task containing the heartbeat response.</returns>
public Task<HeartbeatResponse> SendHeartbeatAsync(string gamePlayerToken)
{
return Send<HeartbeatResponse>(
HttpMethod.Post,
Url("game_room.php/players/heartbeat", $"&game_player_token={gamePlayerToken}")
);
}
/// <summary>
/// Submits a new game action.
/// </summary>
/// <param name="gamePlayerToken">The player's authentication token.</param>
/// <param name="actionType">Type of the action being submitted.</param>
/// <param name="requestData">Data associated with the action.</param>
/// <returns>Task containing the action submission response.</returns>
public Task<ActionSubmitResponse> SubmitActionAsync(
string gamePlayerToken,
string actionType,
object requestData)
{
return Send<ActionSubmitResponse>(
HttpMethod.Post,
Url("game_room.php/actions", $"&game_player_token={gamePlayerToken}"),
new
{
action_type = actionType,
request_data = requestData
}
);
}
/// <summary>
/// Polls for new actions that need to be processed.
/// </summary>
/// <param name="gamePlayerToken">The player's authentication token.</param>
/// <returns>Task containing any pending actions.</returns>
public Task<ActionPollResponse> PollActionsAsync(string gamePlayerToken)
{
return Send<ActionPollResponse>(
HttpMethod.Get,
Url("game_room.php/actions/poll", $"&game_player_token={gamePlayerToken}")
);
}
/// <summary>
/// Retrieves a list of pending actions for the player.
/// </summary>
/// <param name="gamePlayerToken">The player's authentication token.</param>
/// <returns>Task containing the list of pending actions.</returns>
public Task<ActionPendingResponse> GetPendingActionsAsync(string gamePlayerToken)
{
return Send<ActionPendingResponse>(
HttpMethod.Get,
Url("game_room.php/actions/pending", $"&game_player_token={gamePlayerToken}")
);
}
/// <summary>
/// Marks an action as completed.
/// </summary>
/// <param name="actionId">ID of the action to complete.</param>
/// <param name="gamePlayerToken">The player's authentication token.</param>
/// <param name="request">The completion request details.</param>
/// <returns>Task indicating success or failure of the completion.</returns>
public Task<ActionCompleteResponse> CompleteActionAsync(
string actionId,
string gamePlayerToken,
ActionCompleteRequest request)
{
return Send<ActionCompleteResponse>(
HttpMethod.Post,
Url($"game_room.php/actions/{actionId}/complete", $"&game_player_token={gamePlayerToken}"),
new
{
status = request.Status,
response_data = request.Response_data
}
);
}
}
public interface ILogger
{
void Log(string message);
void Warn(string message);
void Error(string message);
}
public class PlayerRegisterResponse
{
public bool Success { get; set; }
public required string Player_id { get; set; }
public required string Private_key { get; set; }
public required string Player_name { get; set; }
public int Game_id { get; set; }
}
public class PlayerAuthResponse
{
public bool Success { get; set; }
public required PlayerInfo Player { get; set; }
}
public class PlayerListResponse
{
public bool Success { get; set; }
public int Count { get; set; }
public required List<PlayerShort> Players { get; set; }
}
public class PlayerShort
{
public int Id { get; set; }
public required string Player_name { get; set; }
public int Is_active { get; set; }
public required string Last_login { get; set; }
public required string Created_at { get; set; }
}
public class PlayerInfo
{
public int Id { get; set; }
public int Game_id { get; set; }
public required string Player_name { get; set; }
public required Dictionary<string, object> Player_data { get; set; }
public int Is_active { get; set; }
public required string Last_login { get; set; }
public required string Created_at { get; set; }
public required string Updated_at { get; set; }
}
public class GameDataResponse
{
public bool Success { get; set; }
public required string Type { get; set; }
public int Game_id { get; set; }
public required Dictionary<string, object> Data { get; set; }
}
public class PlayerDataResponse
{
public bool Success { get; set; }
public required string Type { get; set; }
public int Player_id { get; set; }
public required string Player_name { get; set; }
public required Dictionary<string, object> Data { get; set; }
}
public class SuccessResponse
{
public bool Success { get; set; }
public required string Message { get; set; }
public required string Updated_at { get; set; }
}
public class ServerTimeResponse
{
public bool Success { get; set; }
public required string Utc { get; set; }
public long Timestamp { get; set; }
public required string Readable { get; set; }
}
public class RoomCreateResponse
{
public bool Success { get; set; }
public required string Room_id { get; set; }
public required string Room_name { get; set; }
public bool Is_host { get; set; }
}
public class RoomShort
{
public required string Room_id { get; set; }
public required string Room_name { get; set; }
public int Max_players { get; set; }
public int Current_players { get; set; }
public int Has_password { get; set; }
}
public class RoomListResponse
{
public bool Success { get; set; }
public required List<RoomShort> Rooms { get; set; }
}
public class RoomJoinResponse
{
public bool Success { get; set; }
public required string Room_id { get; set; }
public required string Message { get; set; }
}
public class RoomPlayer
{
public required string Player_id { get; set; }
public required string Player_name { get; set; }
public int Is_host { get; set; }
public int Is_online { get; set; }
}
public class RoomPlayersResponse
{
public bool Success { get; set; }
public required List<RoomPlayer> Players { get; set; }
public required string Last_updated { get; set; }
}
public class RoomLeaveResponse
{
public bool Success { get; set; }
public required string Message { get; set; }
}
public class HeartbeatResponse
{
public bool Success { get; set; }
public required string Status { get; set; }
}
public class ActionSubmitResponse
{
public bool Success { get; set; }
public required string Action_id { get; set; }
public required string Status { get; set; }
}
public class ActionInfo
{
public required string Action_id { get; set; }
public required string Action_type { get; set; }
public string? Response_data { get; set; }
public required string Status { get; set; }
}
public class ActionPollResponse
{
public bool Success { get; set; }
public required List<ActionInfo> Actions { get; set; }
}
public class PendingAction
{
public required string Action_id { get; set; }
public required string Player_id { get; set; }
public required string Action_type { get; set; }
public required string Request_data { get; set; }
public required string Created_at { get; set; }
public required string Player_name { get; set; }
}
public class ActionPendingResponse
{
public bool Success { get; set; }
public required List<PendingAction> Actions { get; set; }
}
public class ActionCompleteRequest
{
public ActionStatus Status { get; set; }
public object? Response_data { get; set; }
public ActionCompleteRequest(ActionStatus status, object? responseData = null)
{
Status = status;
Response_data = responseData;
}
}
public class ActionCompleteResponse
{
public bool Success { get; set; }
public required string Message { get; set; }
}
public enum ActionStatus
{
Pending,
Processing,
Completed,
Failed,
Read
}
}
Here's a complete example of how to use the michitai SDK in your C# application. This example demonstrates common operations like fetching game data, updating player information, and handling authentication.
using System;
using System.Threading.Tasks;
using System.Text.Json;
using michitai;
public class Game
{
private static GameSDK? sdk;
public static async Task Main()
{
Console.WriteLine("=== MICHITAI Game SDK Usage Example ===\n");
// 1️⃣ Initialize SDK
sdk = new GameSDK("YOUR_API_TOKEN", "YOUR_API_PRIVATE_TOKEN");
//sdk = new GameSDK("YOUR_API_TOKEN", "YOUR_API_PRIVATE_TOKEN", logger:new ConsoleLogger()); // for console logging
//sdk = new GameSDK("YOUR_API_TOKEN", "YOUR_API_PRIVATE_TOKEN", logger:new UnityLogger()); // for unity logging
Console.WriteLine("[INIT] SDK initialized\n");
// 2️⃣ Register Player
Console.WriteLine("[PLAYER] Registering new player...");
var reg = await sdk.RegisterPlayer("TestPlayer", new
{
level = 1,
score = 0,
inventory = new[] { "sword", "shield" }
});
string playerToken = reg.Private_key;
int playerId = int.Parse(reg.Player_id);
Console.WriteLine($"[PLAYER] Registered: ID={playerId}, Token={playerToken}\n");
// 3️⃣ Authenticate Player
Console.WriteLine("[PLAYER] Authenticating player...");
var auth = await sdk.AuthenticatePlayer(playerToken);
if (auth.Success)
{
var pdata = auth.Player.Player_data;
int level = pdata.ContainsKey("level") ? ((JsonElement)pdata["level"]).GetInt32() : 0;
Console.WriteLine($"[PLAYER] Authenticated: {auth.Player.Player_name} (Level={level})\n");
}
else
{
Console.WriteLine("[PLAYER] Authentication failed\n");
}
// 4️⃣ List all players
Console.WriteLine("[ADMIN] Fetching all players...");
var allPlayers = await sdk.GetAllPlayers();
Console.WriteLine($"[ADMIN] Total players: {allPlayers.Count}");
foreach (var p in allPlayers.Players)
{
Console.WriteLine($" - ID={p.Id}, Name={p.Player_name}, Active={p.Is_active}");
}
Console.WriteLine();
// 5️⃣ Get global game data
Console.WriteLine("[GAME] Loading game data...");
var gameData = await sdk.GetGameData();
Console.WriteLine($"[GAME] Game ID={gameData.Game_id}, Settings={gameData.Data.Count}\n");
// 6️⃣ Update global game data
Console.WriteLine("[GAME] Updating game settings...");
var updateGame = await sdk.UpdateGameData(new
{
game_settings = new { difficulty = "hard", max_players = 10 },
last_updated = DateTime.UtcNow.ToString("o")
});
Console.WriteLine($"[GAME] {updateGame.Message} at {updateGame.Updated_at}\n");
// 7️⃣ Get player-specific data
Console.WriteLine("[PLAYER] Loading player data...");
var playerData = await sdk.GetPlayerData(playerToken);
var pDataDict = playerData.Data;
int playerLevel = pDataDict.ContainsKey("level") ? ((JsonElement)pDataDict["level"]).GetInt32() : 0;
int playerScore = pDataDict.ContainsKey("score") ? ((JsonElement)pDataDict["score"]).GetInt32() : 0;
string[] inventory = pDataDict.ContainsKey("inventory")
? JsonSerializer.Deserialize<string[]>(((JsonElement)pDataDict["inventory"]).GetRawText())!
: new string[0];
Console.WriteLine($"[PLAYER] Level={playerLevel}, Score={playerScore}, Inventory=[{string.Join(", ", inventory)}]\n");
// 8️⃣ Update player data
Console.WriteLine("[PLAYER] Updating player progress...");
var updatedPlayer = await sdk.UpdatePlayerData(playerToken, new
{
level = 2,
score = 100,
inventory = new[] { "sword", "shield", "potion" },
last_played = DateTime.UtcNow.ToString("o")
});
Console.WriteLine($"[PLAYER] {updatedPlayer.Message} at {updatedPlayer.Updated_at}\n");
// 9️⃣ Get server time
Console.WriteLine("[SERVER] Getting server time...");
var serverTime = await sdk.GetServerTime();
if (serverTime.Success)
{
Console.WriteLine($"[SERVER] Server time (UTC): {serverTime.Utc}");
Console.WriteLine($"[SERVER] Timestamp: {serverTime.Timestamp}");
Console.WriteLine($"[SERVER] Readable: {serverTime.Readable}\n");
}
else
{
Console.WriteLine("[SERVER] Failed to get server time\n");
}
// 🔟 Create a new room
Console.WriteLine("[ROOM] Creating a new game room...");
var roomCreate = await sdk.CreateRoomAsync(
playerToken,
"Test Room",
"test123",
4
);
string roomId = roomCreate.Room_id;
Console.WriteLine($"[ROOM] Created room: ID={roomId}, Name={roomCreate.Room_name}, Is Host={roomCreate.Is_host}\n");
// 1️⃣1️⃣ List all available rooms
Console.WriteLine("[ROOM] Fetching available rooms...");
var rooms = await sdk.GetRoomsAsync();
Console.WriteLine($"[ROOM] Found {rooms.Rooms.Count} room(s):");
foreach (var room in rooms.Rooms)
{
Console.WriteLine($" - ID: {room.Room_id}, Name: {room.Room_name}, Players: {room.Current_players}/{room.Max_players}");
}
Console.WriteLine();
// 1️⃣2️⃣ Join the room (as another player would)
Console.WriteLine("[ROOM] Joining the room...");
var joinRoom = await sdk.JoinRoomAsync(
playerToken,
roomId,
"test123"
);
Console.WriteLine($"[ROOM] {joinRoom.Message}\n");
// 1️⃣3️⃣ List players in the room
Console.WriteLine("[ROOM] Fetching room players...");
var roomPlayers = await sdk.GetRoomPlayersAsync(playerToken);
Console.WriteLine($"[ROOM] Players in room ({roomPlayers.Players.Count}):");
foreach (var player in roomPlayers.Players)
{
Console.WriteLine($" - {player.Player_name} (ID: {player.Player_id}, Host: {player.Is_host == 1}, Online: {player.Is_online})");
}
Console.WriteLine();
// 1️⃣4️⃣ Send a heartbeat
Console.WriteLine("[ROOM] Sending heartbeat...");
var heartbeat = await sdk.SendHeartbeatAsync(playerToken);
Console.WriteLine($"[ROOM] Heartbeat status: {heartbeat.Status}\n");
// 1️⃣5️⃣ Submit an action
Console.WriteLine("[ACTION] Submitting move action...");
var action = await sdk.SubmitActionAsync(
playerToken,
"move",
new { x = 10, y = 20 }
);
string actionId = action.Action_id;
Console.WriteLine($"[ACTION] Action submitted: ID={actionId}, Status={action.Status}\n");
// 1️⃣6️⃣ Check pending actions
Console.WriteLine("[ACTION] Checking for pending actions...");
var pendingActions = await sdk.GetPendingActionsAsync(playerToken);
if (pendingActions.Actions != null && pendingActions.Actions.Count > 0)
{
foreach (var pendingAction in pendingActions.Actions)
{
Console.WriteLine($"[ACTION] Pending: {pendingAction.Action_type}, " +
$"Request: {pendingAction.Request_data}");
}
}
else
{
Console.WriteLine("[ACTION] No pending actions found\n");
}
// 1️⃣7️⃣ Complete an action (simulating server response)
if (!string.IsNullOrEmpty(actionId))
{
Console.WriteLine($"[ACTION] Completing action {actionId}...");
var completeAction = await sdk.CompleteActionAsync(
actionId,
playerToken,
new ActionCompleteRequest(ActionStatus.Completed,
new { success = true, message = "Moved successfully" })
);
Console.WriteLine($"[ACTION] {completeAction.Message}\n");
}
// 1️⃣8️⃣ Poll for completed actions
Console.WriteLine("[ACTION] Polling for completed actions...");
var completedActions = await sdk.PollActionsAsync(playerToken);
if (completedActions.Actions != null && completedActions.Actions.Count > 0)
{
foreach (var completedAction in completedActions.Actions)
{
Console.WriteLine($"[ACTION] Completed: {completedAction.Action_type}, " +
$"Result: {completedAction.Response_data}");
}
}
else
{
Console.WriteLine("[ACTION] No completed actions found\n");
}
// 1️⃣9️⃣ Leave the room
Console.WriteLine("[ROOM] Leaving the room...");
var leaveRoom = await sdk.LeaveRoomAsync(playerToken);
Console.WriteLine($"[ROOM] {leaveRoom.Message}\n");
Console.WriteLine("=== Demo Complete ===");
}
public class ConsoleLogger : ILogger
{
public virtual void Error(string message)
{
Console.WriteLine($"[Error] {message}");
}
public virtual void Log(string message)
{
Console.WriteLine($"[Log] {message}");
}
public virtual void Warn(string message)
{
Console.WriteLine($"[Warning] {message}");
}
}
#if UNITY_EDITOR
public class UnityLogger : ILogger
{
public virtual void Error(string message)
{
Debug.Log($"[Error] {message}");
}
public virtual void Log(string message)
{
Debug.LogWarning($"[Log] {message}");
}
public virtual void Warn(string message)
{
Debug.LogError($"[Warning] {message}");
}
}
#endif
}
SDK.cs file to your projectProgram.cs fileyour-api-key-here with your actual API keyUse our REST API directly from any platform or language. All endpoints return JSON responses with consistent error handling.
Description: Creates a new player in the game. Returns a player_id and private_key needed for future requests.
{
"player_name": "TestPlayer",
"player_data": {
"level": 1,
"score": 0,
"inventory": ["sword","shield"]
}
}
{
"success": true,
"player_id": "7",
"private_key": "46702c9b906e3361c26dbcd605ee9183",
"player_name": "TestPlayer",
"game_id": 4
}
Description: Updates player info such as active status. This does not change player data like level or inventory (those are in /game_data.php).
{}
{
"success": true,
"player": {
"id": 7,
"game_id": 4,
"player_name": "TestPlayer",
"player_data": {
"level": 1,
"score": 0,
"inventory": ["sword","shield"]
},
"is_active": 1,
"last_login": null,
"created_at": "2026-01-13 14:21:16",
"updated_at": "2026-01-13 14:21:16"
}
}
Description: Retrieves a list of all players in the game. Useful for admin dashboards or multiplayer matchmaking.
{}
{
"success": true,
"count": 7,
"players": [
{"id":3,"player_name":"TestPlayer","is_active":1,"last_login":null,"created_at":"2026-01-13 12:30:47"},
{"id":7,"player_name":"TestPlayer","is_active":1,"last_login":"2026-01-13 14:22:33","created_at":"2026-01-13 14:21:16"}
}
Description: Retrieves the global game data, including text, settings, and last update timestamp. Used to sync clients with the server.
{}
{
"success": true,
"type": "game",
"game_id": 4,
"data": {
"text": "hello world",
"game_settings": {
"difficulty": "hard",
"max_players": 10
},
"last_updated": "2025-01-13T12:00:00Z"
}
}
Description: Updates global game data. For example, changing settings or max players. Requires API key authentication.
{
"game_settings": {
"difficulty": "hard",
"max_players": 10
},
"last_updated": "2025-01-13T12:00:00Z"
}
{
"success": true,
"message": "Game data updated successfully",
"updated_at": "2026-01-13 14:24:23"
}
Description: Retrieves a specific player's data using their private_key. Includes level, score, and inventory.
{}
{
"success": true,
"type": "player",
"player_id": 7,
"player_name": "TestPlayer",
"data": {
"level": 1,
"score": 0,
"inventory": ["sword","shield"]
}
}
Description: Updates a specific player's data like level, score, inventory, and last played timestamp.
{
"level": 2,
"score": 100,
"inventory": ["sword","shield","potion"],
"last_played": "2025-01-13T12:30:00Z"
}
{
"success": true,
"message": "Player data updated successfully",
"updated_at": "2026-01-13 14:27:10"
}
Description: Retrieves the current server time in multiple formats including UTC timestamp and human-readable format.
{}
{
"success": true,
"utc": "2025-01-14T16:24:00+00:00",
"timestamp": 1736864640,
"readable": "2025-01-14 16:24:00 UTC"
}
Description: Creates a new game room. The creating player automatically becomes the host.
{
"room_name": "My Game Room",
"password": "secret123",
"max_players": 4
}
{
"success": true,
"room_id": "dc3723848639139113ca240958ba0bf8",
"room_name": "My Game Room",
"is_host": true
}
Description: Returns list of currently available game rooms (not full, public/visible).
{}
{
"success": true,
"rooms": [
{
"room_id": "dc3723848639139113ca240958ba0bf8",
"room_name": "My Game Room",
"max_players": 4,
"current_players": 1,
"has_password": true
}
]
}
Description: Join an existing room by ID. Password is required if the room is protected.
{
"password": "secret123"
}
{
"success": true,
"room_id": "dc3723848639139113ca240958ba0bf8",
"message": "Successfully joined the room"
}
Description: Returns list of players currently in the same room as you.
{}
{
"success": true,
"players": [
{
"player_id": "1",
"player_name": "TestPlayer",
"is_host": false,
"is_online": true
}
],
"last_updated": "2026-01-15T16:06:42Z"
}
Description: Leave the current room. If you were the host, a new host may be assigned automatically.
{}
{
"success": true,
"message": "Successfully left the room"
}
Description: Updates player's last activity timestamp (used to determine online status).
{}
{
"success": true,
"status": "ok"
}
Description: Submits a new player action to the room's action queue (movement, attack, item use, etc.). The action is initially marked as pending and awaits server/host processing.
{
"action_type": "move",
"request_data": {
"x": 10,
"y": 20
}
}
{
"success": true,
"action_id": "1c2bbd859e36dc7d7e5e9b4f263c88ce",
"status": "pending"
}
Description: Retrieves recently completed/processed actions from the room. Clients should poll this endpoint regularly to receive updates on action results.
{}
{
"success": true,
"actions": [
{
"action_id": "1c2bbd859e36dc7d7e5e9b4f263c88ce",
"action_type": "move",
"response_data": "{\"success\":true,\"message\":\"Moved successfully\"}",
"status": "completed"
}
]
}
Description: Returns list of currently pending actions in the room. Typically used by the host or server-side logic to process/approve actions.
{}
{
"success": true,
"actions": [
{
"action_id": "1c2bbd859e36dc7d7e5e9b4f263c88ce",
"player_id": "1",
"action_type": "move",
"request_data": "{\"x\":10,\"y\":20}",
"created_at": "2026-01-15 16:10:43",
"player_name": "TestPlayer"
}
]
}
Description: Marks a pending action as completed and attaches the result/response data. Usually called by the room host or authoritative server.
{
"status": "completed",
"response_data": {
"success": true,
"message": "Moved successfully"
}
}
{
"success": true,
"message": "Action completed"
}
Description: Shows what happens when a request is sent with an invalid or missing API key.
{
"success": false,
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key"
}
}