Skip to main content
The Servers API lets you query, start, stop, and update running servers. Access it via api.server().

Get Servers

// Get all servers
api.server().getAllServers()
    .thenAccept(servers -> System.out.println("Total: " + servers.size()));

// Get servers with query filters
api.server().getAllServers(new ServerQuery())
    .thenAccept(servers -> { ... });

// Get server by ID
api.server().getServerById("server-uuid")
    .thenAccept(server -> System.out.println(server.getState()));

// Get servers in a group
api.server().getServersByGroup("lobby")
    .thenAccept(servers -> servers.forEach(s ->
        System.out.println(s.getServerId() + ": " + s.getState())));

// Get server by group and numerical ID (e.g., Lobby-1)
api.server().getServerByNumericalId("lobby", 1)
    .thenAccept(server -> System.out.println(server.getServerId()));

// Get current server (from within a running server)
api.server().getCurrentServer()
    .thenAccept(server -> System.out.println("Running on: " + server.getServerId()));

Start Server

StartServerRequest request = new StartServerRequest("group-uuid", "lobby");

api.server().startServer(request)
    .thenAccept(server -> System.out.println("Started: " + server.getServerId()));

Stop Server

api.server().stopServer("server-uuid")
    .thenAccept(success -> System.out.println("Stopped: " + success));

Update Server

UpdateServerRequest update = UpdateServerRequest.builder()
    .maxPlayers(64)
    .build();

api.server().updateServer("server-uuid", update)
    .thenAccept(server -> System.out.println("Updated: " + server.getMaxPlayers()));

List servers (REST)

To list servers in a network with optional filters, use the REST API endpoint GET /v0/servers. The response includes server details, server group or persistent server metadata, blueprint information, and workflow configurations.
curl "https://your-controller/v0/servers?state=AVAILABLE&type=lobby" \
  -H "X-Network-ID: your-network-id" \
  -H "X-Network-Secret: your-network-secret"
ParameterLocationRequiredDescription
X-Network-IDHeaderYesYour network identifier
X-Network-SecretHeaderYesYour network secret or an app JWT for the target network. When the controller has JWT authentication configured, either credential type is accepted. JWTs must be valid for the network in X-Network-ID and are subject-permission scoped; network secrets grant full network access.
X-SC-ComponentHeaderNoOptional caller component name (for example, serverhost). When set, the value is attached to the controller’s request wide event as the component field so request logs can be filtered by the originating SimpleCloud component. Leading and trailing whitespace is trimmed.
server_group_idQueryNoFilter by server group ID(s), comma-separated
stateQueryNoFilter by state(s), comma-separated (e.g., AVAILABLE,STARTING)
serverhost_idQueryNoFilter by serverhost ID
persistent_server_idQueryNoFilter by persistent server ID
typeQueryNoFilter by type(s), comma-separated (matches server group OR persistent server type)
nameQueryNoFilter by name(s), comma-separated (matches server group OR persistent server name)
tagsQueryNoFilter by tag(s), comma-separated (matches if any tag matches in server group OR persistent server)
numerical_idQueryNoFilter by numerical ID(s), comma-separated (e.g., 1,5,10)
sort_byQueryNoSort field: created_at, updated_at, numerical_id, state
sort_orderQueryNoSort order: asc (default) or desc

Response cache

To reduce database load from high-frequency callers (dashboards, panels, polling clients), the controller caches the underlying database rows for GET /v0/servers for 2 seconds. Identical back-to-back requests within this window are served from the in-memory response cache instead of re-querying Postgres. Caching only applies when the caller has no per-user permission filtering applied. Permission-filtered callers always bypass the cache to prevent leaking results between callers with different permissions. When caching is in effect, the response includes an X-DB-Cache header for observability:
Header valueMeaning
X-DB-Cache: HITRows were served from the response cache
X-DB-Cache: MISSRows were fetched from the database and written into the cache
The header is omitted entirely for permission-filtered requests (which always bypass the cache) and when the response cache is not configured.
The 2-second TTL is short enough that responses remain effectively real-time for UI use cases. If you need stricter freshness guarantees, treat any response with X-DB-Cache: HIT as up to 2 seconds stale.

Delete server record

To remove a server record directly from the database without stopping the process or publishing lifecycle events, use the REST API endpoint DELETE /v0/servers/database. This is useful for cleaning up stale or orphaned records when the server process has already terminated.
This operation only removes the database row. It does not stop the server process, trigger cleanup workflows, or emit events. Use stopServer for normal shutdown.
curl -X DELETE "https://your-controller/v0/servers/database?server_id=SERVER_UUID" \
  -H "X-Network-ID: your-network-id" \
  -H "X-Network-Secret: your-network-secret"
Response:
{
  "server_id": "123e4567-e89b-12d3-a456-426614174000",
  "message": "Server row deleted successfully"
}
ParameterLocationRequiredDescription
server_idQueryYesUUID of the server record to delete
X-Network-IDHeaderYesYour network identifier
X-Network-SecretHeaderYesYour network secret or an app JWT for the target network. When the controller has JWT authentication configured, either credential type is accepted.
X-SC-ComponentHeaderNoOptional caller component name attached to the controller’s request wide event as the component field. Leading and trailing whitespace is trimmed.

Server properties

Servers inherit properties from their group, but you can override them per-instance:
// Add or update properties (merges with existing)
Map<String, String> props = Map.of("map", "castle", "mode", "competitive");
api.server().updateServerProperties("server-uuid", props);

// Remove specific properties
api.server().deleteServerProperties("server-uuid", List.of("mode"));

Server Model

PropertyTypeDescription
serverIdStringUnique identifier
groupNameStringParent group name
numericalIdlongNumerical ID within group (1, 2, 3…)
stateServerStateCurrent lifecycle state
hostStringServer host machine
ipStringIP address
portintServer port
minMemoryintMinimum memory (MB)
maxMemoryintMaximum memory (MB)
maxPlayersintPlayer limit
playerCountintCurrent online players
propertiesMap<String, String>Custom metadata
createdAtInstantCreation timestamp

ServerState

StateDescription
PREPARINGCopying template files
STARTINGJVM process launching
AVAILABLEReady for players
INGAMEHas active players
STOPPINGShutdown in progress

Environment Variables

Inside a running server, access server info without the API:
String group = System.getenv("SIMPLECLOUD_GROUP");
String uniqueId = System.getenv("SIMPLECLOUD_UNIQUE_ID");
String numericalId = System.getenv("SIMPLECLOUD_NUMERICAL_ID");
String host = System.getenv("SIMPLECLOUD_HOST");
String ip = System.getenv("SIMPLECLOUD_IP");
String port = System.getenv("SIMPLECLOUD_PORT");
String maxPlayers = System.getenv("SIMPLECLOUD_MAX_PLAYERS");
String maxMemory = System.getenv("SIMPLECLOUD_MAX_MEMORY");
Custom group properties are also available with SIMPLECLOUD_ prefix (uppercase, dashes become underscores).