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"
| Parameter | Location | Required | Description |
|---|
X-Network-ID | Header | Yes | Your network identifier |
X-Network-Secret | Header | Yes | Your 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-Component | Header | No | Optional 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_id | Query | No | Filter by server group ID(s), comma-separated |
state | Query | No | Filter by state(s), comma-separated (e.g., AVAILABLE,STARTING) |
serverhost_id | Query | No | Filter by serverhost ID |
persistent_server_id | Query | No | Filter by persistent server ID |
type | Query | No | Filter by type(s), comma-separated (matches server group OR persistent server type) |
name | Query | No | Filter by name(s), comma-separated (matches server group OR persistent server name) |
tags | Query | No | Filter by tag(s), comma-separated (matches if any tag matches in server group OR persistent server) |
numerical_id | Query | No | Filter by numerical ID(s), comma-separated (e.g., 1,5,10) |
sort_by | Query | No | Sort field: created_at, updated_at, numerical_id, state |
sort_order | Query | No | Sort 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 value | Meaning |
|---|
X-DB-Cache: HIT | Rows were served from the response cache |
X-DB-Cache: MISS | Rows 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"
}
| Parameter | Location | Required | Description |
|---|
server_id | Query | Yes | UUID of the server record to delete |
X-Network-ID | Header | Yes | Your network identifier |
X-Network-Secret | Header | Yes | Your network secret or an app JWT for the target network. When the controller has JWT authentication configured, either credential type is accepted. |
X-SC-Component | Header | No | Optional 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
| Property | Type | Description |
|---|
serverId | String | Unique identifier |
groupName | String | Parent group name |
numericalId | long | Numerical ID within group (1, 2, 3…) |
state | ServerState | Current lifecycle state |
host | String | Server host machine |
ip | String | IP address |
port | int | Server port |
minMemory | int | Minimum memory (MB) |
maxMemory | int | Maximum memory (MB) |
maxPlayers | int | Player limit |
playerCount | int | Current online players |
properties | Map<String, String> | Custom metadata |
createdAt | Instant | Creation timestamp |
ServerState
| State | Description |
|---|
PREPARING | Copying template files |
STARTING | JVM process launching |
AVAILABLE | Ready for players |
INGAME | Has active players |
STOPPING | Shutdown 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).