# List all networks (admin only) Source: https://simplecloud.app/docs/en/developer/api-reference/admin/list-all-networks-admin-only https://controller.simplecloud.app/swagger/doc.json get /v0/admin/networks List all networks. Requires admin access. # Create a new blueprint Source: https://simplecloud.app/docs/en/developer/api-reference/blueprints/create-a-new-blueprint https://controller.simplecloud.app/swagger/doc.json post /v0/blueprints Create a new blueprint for a network # Delete a blueprint Source: https://simplecloud.app/docs/en/developer/api-reference/blueprints/delete-a-blueprint https://controller.simplecloud.app/swagger/doc.json delete /v0/blueprints Delete an existing blueprint # List blueprints Source: https://simplecloud.app/docs/en/developer/api-reference/blueprints/list-blueprints https://controller.simplecloud.app/swagger/doc.json get /v0/blueprints Get a list of blueprints for a network # Partially update a blueprint Source: https://simplecloud.app/docs/en/developer/api-reference/blueprints/partially-update-a-blueprint https://controller.simplecloud.app/swagger/doc.json patch /v0/blueprints Partially update an existing blueprint # Update a blueprint Source: https://simplecloud.app/docs/en/developer/api-reference/blueprints/update-a-blueprint https://controller.simplecloud.app/swagger/doc.json put /v0/blueprints Update an existing blueprint # Query current metric values Source: https://simplecloud.app/docs/en/developer/api-reference/metrics/query-current-metric-values https://controller.simplecloud.app/swagger/doc.json get /v0/metrics/query Get the latest values for a metric, optionally grouped by a label # Query logs with flexible filters Source: https://simplecloud.app/docs/en/developer/api-reference/metrics/query-logs-with-flexible-filters https://controller.simplecloud.app/swagger/doc.json post /v0/metrics/logs/query Query logs using POST body with array-based filters for maximum flexibility # Query metric time series Source: https://simplecloud.app/docs/en/developer/api-reference/metrics/query-metric-time-series https://controller.simplecloud.app/swagger/doc.json get /v0/metrics/query_range Get time-bucketed metric values for charts, optionally grouped by a label # Stream logs in real-time via SSE Source: https://simplecloud.app/docs/en/developer/api-reference/metrics/stream-logs-in-real-time-via-sse https://controller.simplecloud.app/swagger/doc.json get /v0/metrics/logs/stream Server-Sent Events endpoint for real-time log streaming with filters # Create network password Source: https://simplecloud.app/docs/en/developer/api-reference/networks/create-network-password https://controller.simplecloud.app/swagger/doc.json post /v0/networks/passwords Create a new network password for the authenticated network # Delete a network and all its resources Source: https://simplecloud.app/docs/en/developer/api-reference/networks/delete-a-network-and-all-its-resources https://controller.simplecloud.app/swagger/doc.json delete /v0/networks Delete a network and cascade delete all associated resources (servers, groups, blueprints, etc.) # Delete network password Source: https://simplecloud.app/docs/en/developer/api-reference/networks/delete-network-password https://controller.simplecloud.app/swagger/doc.json delete /v0/networks/passwords Delete a network password from the authenticated network # List network passwords Source: https://simplecloud.app/docs/en/developer/api-reference/networks/list-network-passwords https://controller.simplecloud.app/swagger/doc.json get /v0/networks/passwords List all network passwords for the authenticated network # Register a new network Source: https://simplecloud.app/docs/en/developer/api-reference/networks/register-a-new-network https://controller.simplecloud.app/swagger/doc.json post /v0/networks/register Register a new network and generate credentials # Update a network Source: https://simplecloud.app/docs/en/developer/api-reference/networks/update-a-network https://controller.simplecloud.app/swagger/doc.json patch /v0/networks Update the authenticated network # Verify network credentials Source: https://simplecloud.app/docs/en/developer/api-reference/networks/verify-network-credentials https://controller.simplecloud.app/swagger/doc.json post /v0/networks/verify Verify if the provided network credentials are valid # Create a new persistent server Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/create-a-new-persistent-server https://controller.simplecloud.app/swagger/doc.json post /v0/persistent-servers Create a new persistent server for a network # Delete a persistent server Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/delete-a-persistent-server https://controller.simplecloud.app/swagger/doc.json delete /v0/persistent-servers Delete an existing persistent server # Delete persistent server property keys Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/delete-persistent-server-property-keys https://controller.simplecloud.app/swagger/doc.json delete /v0/persistent-servers/properties Delete specific property keys from a persistent server # Execute a manual workflow for all running servers of a persistent server Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/execute-a-manual-workflow-for-all-running-servers-of-a-persistent-server https://controller.simplecloud.app/swagger/doc.json post /v0/persistent-servers/workflows/manual Execute a configured manual workflow for all eligible running servers of a persistent server # List persistent servers Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/list-persistent-servers https://controller.simplecloud.app/swagger/doc.json get /v0/persistent-servers Get a list of persistent servers for a network # Merge persistent server properties Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/merge-persistent-server-properties https://controller.simplecloud.app/swagger/doc.json patch /v0/persistent-servers/properties Merge/update specific property keys for a persistent server (deep merge) # Partially update a persistent server Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/partially-update-a-persistent-server https://controller.simplecloud.app/swagger/doc.json patch /v0/persistent-servers Partially update an existing persistent server # Replace persistent server properties Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/replace-persistent-server-properties https://controller.simplecloud.app/swagger/doc.json put /v0/persistent-servers/properties Replace entire properties object for a persistent server # Update a persistent server Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/update-a-persistent-server https://controller.simplecloud.app/swagger/doc.json put /v0/persistent-servers Update an existing persistent server # Connect player to server Source: https://simplecloud.app/docs/en/developer/api-reference/players/connect-player-to-server https://controller.simplecloud.app/swagger/doc.json post /v0/players/connect Connect a player to a specific server, server group, or persistent server # Delete player properties Source: https://simplecloud.app/docs/en/developer/api-reference/players/delete-player-properties https://controller.simplecloud.app/swagger/doc.json delete /v0/players/properties Delete specific property keys # Get client settings Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-client-settings https://controller.simplecloud.app/swagger/doc.json get /v0/players/sessions/settings Get client settings for an online player's current session # Get current session Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-current-session https://controller.simplecloud.app/swagger/doc.json get /v0/players/sessions/current Get the current active session for an online player # Get latest player profile Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-latest-player-profile https://controller.simplecloud.app/swagger/doc.json get /v0/players/profiles/latest Get the most recent profile (name/skin) for a player # Get online player count Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-online-player-count https://controller.simplecloud.app/swagger/doc.json get /v0/players/online/count Get the count of online players # Get player by name Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-player-by-name https://controller.simplecloud.app/swagger/doc.json get /v0/players/name Get a player by their name # Get player by UUID Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-player-by-uuid https://controller.simplecloud.app/swagger/doc.json get /v0/players/id Get a player by their Minecraft UUID # Get player online time Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-player-online-time https://controller.simplecloud.app/swagger/doc.json get /v0/players/online-time Get total online time for a player on this network # Get player properties Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-player-properties https://controller.simplecloud.app/swagger/doc.json get /v0/players/properties Get custom properties for a player # Kick a player Source: https://simplecloud.app/docs/en/developer/api-reference/players/kick-a-player https://controller.simplecloud.app/swagger/doc.json post /v0/players/kick Kick a player from the network # List online players Source: https://simplecloud.app/docs/en/developer/api-reference/players/list-online-players https://controller.simplecloud.app/swagger/doc.json get /v0/players/online Get a list of online players # List player profiles Source: https://simplecloud.app/docs/en/developer/api-reference/players/list-player-profiles https://controller.simplecloud.app/swagger/doc.json get /v0/players/profiles Get a player's profile history (name/skin changes) # List player sessions Source: https://simplecloud.app/docs/en/developer/api-reference/players/list-player-sessions https://controller.simplecloud.app/swagger/doc.json get /v0/players/sessions Get session history for a player on this network # List players Source: https://simplecloud.app/docs/en/developer/api-reference/players/list-players https://controller.simplecloud.app/swagger/doc.json get /v0/players Get a list of players for a network with optional filtering # Partially update a player Source: https://simplecloud.app/docs/en/developer/api-reference/players/partially-update-a-player https://controller.simplecloud.app/swagger/doc.json patch /v0/players Partially update admin-managed player fields like online time and optionally reset first/last seen timestamps to now # Patch player properties Source: https://simplecloud.app/docs/en/developer/api-reference/players/patch-player-properties https://controller.simplecloud.app/swagger/doc.json patch /v0/players/properties Merge properties with existing ones # Update client settings Source: https://simplecloud.app/docs/en/developer/api-reference/players/update-client-settings https://controller.simplecloud.app/swagger/doc.json put /v0/players/sessions/settings Update client settings for an online player's current session # Update player properties Source: https://simplecloud.app/docs/en/developer/api-reference/players/update-player-properties https://controller.simplecloud.app/swagger/doc.json put /v0/players/properties Replace all player properties # Bulk create plugin assignments Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/bulk-create-plugin-assignments https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-assignments/bulk-create Assign one or more plugins to multiple server groups and persistent servers atomically # Bulk delete plugin assignments Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/bulk-delete-plugin-assignments https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-assignments/bulk-delete Delete multiple plugin assignments in one request # Create a new plugin assignment Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/create-a-new-plugin-assignment https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-assignments Assign a plugin to a server group or persistent server. You can either provide a plugin_id to use an existing plugin, or provide plugin_name, source_type, and source_value to find or create the plugin automatically. # Delete a plugin assignment Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/delete-a-plugin-assignment https://controller.simplecloud.app/swagger/doc.json delete /v0/plugin-assignments Delete an existing plugin assignment # List plugin assignments Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/list-plugin-assignments https://controller.simplecloud.app/swagger/doc.json get /v0/plugin-assignments Get a list of plugin assignments for a network, optionally filtered by server group or persistent server # Update a plugin assignment Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/update-a-plugin-assignment https://controller.simplecloud.app/swagger/doc.json put /v0/plugin-assignments Update the plugin metadata for an existing assignment without deleting it first # Bulk install a plugin collection on targets Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-assignments/bulk-install-a-plugin-collection-on-targets https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-collection-assignments/bulk-create Install a plugin collection on multiple server groups and persistent servers atomically # Delete a plugin collection installation Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-assignments/delete-a-plugin-collection-installation https://controller.simplecloud.app/swagger/doc.json delete /v0/plugin-collection-assignments Delete a plugin collection installation without deleting the normal plugin assignments created from it # Install a plugin collection on a target Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-assignments/install-a-plugin-collection-on-a-target https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-collection-assignments Install a plugin collection on a server group or persistent server and materialize normal plugin assignments # List plugin collection installations Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-assignments/list-plugin-collection-installations https://controller.simplecloud.app/swagger/doc.json get /v0/plugin-collection-assignments Get plugin collection installations for a network, optionally filtered by target # Reapply plugin collection assignments Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-assignments/reapply-plugin-collection-assignments https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-collection-assignments/reapply Materialize missing plugin assignments from existing plugin collection assignments # Add a plugin to a plugin collection Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-plugins/add-a-plugin-to-a-plugin-collection https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-collection-plugins Add a plugin reference to a plugin collection without modifying existing assignments # Delete a plugin from a plugin collection Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-plugins/delete-a-plugin-from-a-plugin-collection https://controller.simplecloud.app/swagger/doc.json delete /v0/plugin-collection-plugins Delete a plugin from a plugin collection without deleting existing assignments created from it # List plugins in a plugin collection Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-plugins/list-plugins-in-a-plugin-collection https://controller.simplecloud.app/swagger/doc.json get /v0/plugin-collection-plugins Get the plugins configured for a plugin collection # Create a plugin collection Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collections/create-a-plugin-collection https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-collections Create a new plugin collection for a network # List plugin collections Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collections/list-plugin-collections https://controller.simplecloud.app/swagger/doc.json get /v0/plugin-collections Get a list of plugin collections for a network # Update a plugin collection Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collections/update-a-plugin-collection https://controller.simplecloud.app/swagger/doc.json put /v0/plugin-collections Update an existing plugin collection # Events API Source: https://simplecloud.app/docs/en/developer/api/events Subscribe to group, server, persistent server, and blueprint events ## Subscribe to an event The examples use the shared `CloudApi` client created in [Installation](/docs/en/developer/installation) and belong inside your plugin's methods. ```java theme={null} Subscription subscription = api.event().server().onStateChanged(event -> { String serverId = event.getServerId(); // React to the state change. }); ``` Keep the returned `Subscription` and close it when your plugin stops. The [event handling guide](/docs/en/developer/guides/event-handling) shows the complete plugin lifecycle and how to safely interact with your server platform from a callback. ## Choose an event category | Category | Subscription methods | Callback types | | -------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `group()` | `onCreated`, `onUpdated`, `onDeleted` | `GroupCreatedEvent`, `GroupUpdatedEvent`, `GroupDeletedEvent` | | `server()` | `onStarted`, `onStopped`, `onStateChanged`, `onUpdated`, `onDeleted` | `ServerStartedEvent`, `ServerStoppedEvent`, `ServerStateChangedEvent`, `ServerUpdatedEvent`, `ServerDeletedEvent` | | `persistentServer()` | `onCreated`, `onStarted`, `onStopped`, `onUpdated`, `onDeleted` | `PersistentServerCreatedEvent`, `PersistentServerStartedEvent`, `PersistentServerStoppedEvent`, `PersistentServerUpdatedEvent`, `PersistentServerDeletedEvent` | | `blueprint()` | `onCreated`, `onUpdated`, `onDeleted` | `BlueprintCreatedEvent`, `BlueprintUpdatedEvent`, `BlueprintDeletedEvent` | Server events describe individual server instances. Persistent server events describe changes to the persistent server itself, such as it being updated or starting a server instance. ## Keep state accurate Events notify you that something changed; query APIs provide the current state. Subscriptions only receive live events, so query the resource when your plugin starts or when missing an event would make its state incorrect. Close each subscription when you no longer need it. Both `close()` and `unsubscribe()` stop future delivery and can be called more than once. ## Read callback data Every callback provides `getNetworkId()` and an ISO 8601 timestamp through `getTimestamp()`. The remaining getters depend on the event type. Prefer the stable ID getter when identifying a resource. Some event payloads omit the embedded model. In that case, model getters such as `getServer()`, `getGroup()`, and `getBlueprint()` throw `IllegalStateException`. Query the matching resource API when you need its current data. | Callback type | Additional getters | | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `ServerStartedEvent` | `getServerId()`, `getServerGroupId()`, `getServer()` | | `ServerStoppedEvent` | `getServerId()`, `getServerGroupId()`, `getServer()`, `getCrashed()`, `getExitCode()` (`Integer` or `null`), `getReason()` (`String` or `null`) | | `ServerStateChangedEvent` | `getServerId()`, `getOldState()`, `getNewState()`, `getServer()` | | `ServerUpdatedEvent` | `getServerId()`, `getServerGroupId()`, `getServer()` | | `ServerDeletedEvent` | `getServerId()`, `getServerGroupId()`, `getServer()` | | Callback type | Additional getters | | ------------------- | ------------------------------------------------------ | | `GroupCreatedEvent` | `getServerGroupId()`, `getGroup()` | | `GroupUpdatedEvent` | `getServerGroupId()`, `getGroup()` | | `GroupDeletedEvent` | `getServerGroupId()`, `getName()` (`String` or `null`) | | Callback type | Additional getters | | ------------------------------ | --------------------------------------------------------------- | | `PersistentServerCreatedEvent` | `getPersistentServerId()`, `getName()` (`String` or `null`) | | `PersistentServerStartedEvent` | `getPersistentServerId()`, `getServerId()` (`String` or `null`) | | `PersistentServerStoppedEvent` | `getPersistentServerId()`, `getServerId()` (`String` or `null`) | | `PersistentServerUpdatedEvent` | `getPersistentServerId()`, `getName()` (`String` or `null`) | | `PersistentServerDeletedEvent` | `getPersistentServerId()`, `getName()` (`String` or `null`) | | Callback type | Additional getters | | ----------------------- | ---------------------------------------------------- | | `BlueprintCreatedEvent` | `getBlueprintId()`, `getBlueprint()` | | `BlueprintUpdatedEvent` | `getBlueprintId()`, `getBlueprint()` | | `BlueprintDeletedEvent` | `getBlueprintId()`, `getName()` (`String` or `null`) | # Groups API Source: https://simplecloud.app/docs/en/developer/api/groups Create, query, update, and delete server groups ## Create a group A group applies the same software, resources, and scaling behavior to each server it creates. The examples use the shared `CloudApi` client created in [Installation](/docs/en/developer/installation) and belong inside your plugin's methods. This example creates a Paper lobby group and its blueprint. SimpleCloud keeps one lobby running and can scale the group up to three servers while maintaining 20 available player slots. ```java theme={null} CreateGroupRequest request = CreateGroupRequest.builder() .name("lobby") .type(GroupServerType.SERVER) .minMemory(1024) .maxMemory(2048) .maxPlayers(100) .createBlueprint(CreateBlueprintRequest.builder() .configurator("paper") .serverSoftware("paper") .minecraftVersion("1.21.11") .build()) .scaling(ScalingConfig.builder() .scalingMode(ScalingMode.SLOTS) .minServers(1) .maxServers(3) .availableSlots(20) .build()) .build(); api.group().createGroup(request) .thenAccept(group -> System.out.println( "Created " + group.getName() + " with ID " + group.getServerGroupId() )); ``` The group name is also used for the new blueprint. To use a blueprint that already exists, replace `createBlueprint(...)` with: ```java theme={null} .source(SourceConfig.builder() .type(SourceType.BLUEPRINT) .blueprint("blueprint-uuid") .build()) ``` Do not set both `createBlueprint` and an existing blueprint or image source. Use up to 100 ASCII letters, digits, underscores, or hyphens (`[A-Za-z0-9_-]`). Group names are unique within the network. Name matching is case-insensitive, so `Lobby` and `lobby` identify the same group. Creating or renaming a group to a case-only variation of an existing name returns `409 Conflict`. A group and a persistent server may share a name. `SERVER` for game servers or `PROXY` for proxies. Defaults to `SERVER`. Minimum memory in MB. Maximum memory in MB. Player limit per server. Defaults to `50`. Whether the group may create servers. Defaults to `true`. Group priority. Host selection settings. Minimum and maximum servers and scaling behavior. Existing blueprint or container image used by the group. Blueprint to create with the group. Lifecycle and manual workflows. Custom group properties. Tags used to organize and filter groups. ## Find groups Look up a group by name or ID: ```java theme={null} api.group().getGroupByName("lobby") .thenAccept(group -> System.out.println(group.getServerGroupId())); api.group().getGroupById("group-uuid") .thenAccept(group -> System.out.println(group.getName())); ``` Both methods complete exceptionally when the group does not exist. Name lookups are case-insensitive. Use `GroupQuery` to filter the group list by type, tag, or result limit: ```java theme={null} GroupQuery query = GroupQuery.create() .filterByType(GroupServerType.SERVER) .filterByTag("production") .limit(25); api.group().getAllGroups(query) .thenAccept(groups -> groups.forEach(group -> System.out.println(group.getName()) )); ``` Call `getAllGroups()` without a query to return every group. ## Update a group `UpdateGroupRequest` changes only the fields you set: ```java theme={null} UpdateGroupRequest update = UpdateGroupRequest.builder() .maxPlayers(120) .build(); api.group().updateGroup("group-uuid", update) .thenAccept(group -> System.out.println("Updated " + group.getName())); ``` You can update `name`, `type`, `minMemory`, `maxMemory`, `maxPlayers`, `active`, `priority`, `deployment`, `scaling`, `source`, `workflows`, `properties`, and `tags`. When updating a nested object such as `ScalingConfig`, provide all values you want it to contain. Use the property methods below when you only want to merge individual properties. ## Manage group properties Group properties store custom data for your plugins. Updates merge with the existing map. ```java theme={null} Map properties = Map.of( "gameMode", "ADVENTURE", "region", "eu-west" ); api.group().updateGroupProperties("group-uuid", properties) .thenAccept(updated -> System.out.println("Properties: " + updated)); api.group().deleteGroupProperty("group-uuid", "region") .thenAccept(remaining -> System.out.println("Properties: " + remaining)); ``` Use `deleteGroupProperties` to remove several keys at once. Each property method returns the resulting map. ## Start another server Request one additional server when a specific application action needs another instance: ```java theme={null} api.group().getGroupByName("lobby") .thenCompose(api.group()::requestServerStart) .thenRun(() -> System.out.println("Start requested")); ``` This queues one start request without changing the group's scaling configuration. Use the [Servers API](/docs/en/developer/api/servers) or server events when your plugin needs to wait for the new server. ### Inspect the start queue The queue shows pending and failed manual start requests: ```java theme={null} api.group().getServerStartQueue() .thenAccept(queue -> { GroupStartQueueEntry lobby = queue.findByServerGroupName("lobby"); if (lobby == null) { return; } lobby.getStarts().stream() .filter(start -> start.getStatus() == GroupStartQueueItemStatus.FAILED) .forEach(start -> System.err.println(start.getFailureReason())); }); ``` `findByServerGroupId` and `findByServerGroupName` return `null` when the queue has no entry for the group. Clear pending start requests for a group with: ```java theme={null} api.group().clearServerStartQueue("group-uuid"); ``` This does not stop servers that have already been created. `GroupStartQueue` contains totals across every group and a list of `GroupStartQueueEntry` objects. Number of group entries. Number of pending starts. Number of failed starts. Total number of start requests. Queue entries grouped by server group. Each `GroupStartQueueEntry` provides the group ID and name, its start counts, and a `starts` list. A `GroupStartQueueItem` provides its ID, creation time, status, and failure reason. Its status is `PENDING`, `FAILED`, or `UNKNOWN`. ## Delete a group ```java theme={null} api.group().deleteGroup("group-uuid"); ``` Deactivate the group first so it cannot replace stopped instances. Stop its servers, wait for them to stop, then delete the group. ## Group model reference The following fields are available through `Group` getters. Unique group identifier. Group name. `SERVER`, `PROXY`, or `UNKNOWN_SERVER`. Minimum memory in MB. Maximum memory in MB. Player limit per server. Whether the group may create servers. Group priority. Host selection configuration. Scaling configuration. Blueprint or container image source. Lifecycle and manual workflows. Custom group properties. Group tags. Creation timestamp in ISO 8601 format. Last-update timestamp in ISO 8601 format. Minimum number of servers to maintain. Maximum number of servers the group may create. `SLOTS` is the dashboard's **Slots** mode and maintains free capacity. `PLAYERS` is the dashboard's **Servers** mode and starts servers from player utilization. Free player slots to maintain in `SLOTS` mode. Player utilization threshold between `0` and `1`. Scale-down settings. `SLOTS` can start and stop servers. `PLAYERS` only starts servers; it does not stop extra instances automatically. ## Group server types | Value | Description | | ---------------- | -------------------------------------------- | | `SERVER` | Game server, such as Paper or Spigot | | `PROXY` | Proxy server, such as Velocity or BungeeCord | | `UNKNOWN_SERVER` | Unknown server type returned by the API | # Persistent servers API Source: https://simplecloud.app/docs/en/developer/api/persistent-servers Create, query, update, and delete persistent servers ## Create a persistent server A persistent server keeps one server configuration and does not scale to multiple instances like a group. The examples use the shared `CloudApi` client created in [Installation](/docs/en/developer/installation) and belong inside your plugin's methods. This example creates `survival-1` with a new Paper blueprint. Because the persistent server is active, SimpleCloud starts its instance and replaces it after a stop. ```java theme={null} CreatePersistentServerRequest request = CreatePersistentServerRequest.builder() .name("survival-1") .type(GroupServerType.SERVER) .minMemory(2048) .maxMemory(4096) .maxPlayers(80) .createBlueprint(CreateBlueprintRequest.builder() .configurator("paper") .serverSoftware("paper") .minecraftVersion("1.21.11") .build()) .active(true) .serverhostId("serverhost-uuid") .tags(List.of("survival", "production")) .build(); api.persistentServer().createPersistentServer(request) .thenAccept(server -> System.out.println( "Created " + server.getName() + " with ID " + server.getPersistentServerId())); ``` To use an existing blueprint instead, replace `createBlueprint(...)` with a source: ```java theme={null} .source(SourceConfig.builder() .type(SourceType.BLUEPRINT) .blueprint("blueprint-uuid") .build()) ``` Set either `source` or `createBlueprint`, not both. Use up to 100 ASCII letters, digits, underscores, or hyphens (`[A-Za-z0-9_-]`). Persistent server names are unique within the network. Name matching is case-insensitive, so `Survival-1` and `survival-1` identify the same persistent server. Creating or renaming a persistent server to a case-only variation of an existing name returns `409 Conflict`. A persistent server and a group may share a name. `SERVER` or `PROXY`. Defaults to `SERVER`. Minimum memory in MB. Maximum memory in MB. Player limit. Defaults to `50`. Blueprint to create for this persistent server. Existing blueprint or container image to use. Do not set this together with `createBlueprint`. Whether SimpleCloud should keep an instance running. Defaults to `true`. Persistent server priority. ID of the assigned serverhost. Lifecycle and manual workflows. Custom properties. Tags used to organize and filter persistent servers. ## Find persistent servers Find one persistent server by name or ID: ```java theme={null} api.persistentServer().getPersistentServerByName("survival-1") .thenAccept(server -> System.out.println(server.getPersistentServerId())); api.persistentServer().getPersistentServerById("persistent-server-uuid") .thenAccept(server -> System.out.println(server.getName())); ``` Both methods complete exceptionally when no persistent server matches. Name lookups are case-insensitive. Use a query to filter the list: ```java theme={null} PersistentServerQuery query = PersistentServerQuery.create() .filterByActive(true) .filterByTags("survival", "production") .limit(20); api.persistentServer().getAllPersistentServers(query) .thenAccept(servers -> servers.forEach(server -> System.out.println(server.getName() + ": " + server.getPlayerCount()))); ``` The query can filter by tags, active state, and serverhost ID. Call `getAllPersistentServers()` without a query to return every persistent server. ## Update a persistent server Only fields set on `UpdatePersistentServerRequest` are changed: ```java theme={null} UpdatePersistentServerRequest update = UpdatePersistentServerRequest.builder() .maxMemory(6144) .maxPlayers(100) .build(); api.persistentServer() .updatePersistentServer("persistent-server-uuid", update) .thenAccept(server -> System.out.println("Updated " + server.getName())); ``` You can update the name, type, memory, player limit, active state, priority, assigned serverhost, source, workflows, properties, and tags. ## Manage properties Use the property methods to change custom properties without updating the rest of the configuration: ```java theme={null} api.persistentServer().updatePersistentServerProperties( "persistent-server-uuid", Map.of("gameMode", "SURVIVAL", "region", "eu-central") ).thenAccept(properties -> System.out.println("Properties: " + properties)); api.persistentServer() .deletePersistentServerProperty("persistent-server-uuid", "region") .thenAccept(properties -> System.out.println("Properties: " + properties)); ``` `updatePersistentServerProperties` merges the supplied values with the existing properties. You can also update one property or delete multiple properties. ## Delete a persistent server ```java theme={null} api.persistentServer() .deletePersistentServer("persistent-server-uuid") .thenRun(() -> System.out.println("Deleted persistent server")); ``` Deactivate the persistent server first, stop its instance, and delete the configuration after the instance stops. Its files remain on the serverhost. ## Persistent server model `PersistentServer` extends `ServerBase` and provides the following fields. Unique persistent server ID. Persistent server name. `SERVER`, `PROXY`, or `UNKNOWN_SERVER`. Minimum memory in MB. Maximum memory in MB. Player limit. Whether SimpleCloud should keep an instance running. Persistent server priority. Assigned serverhost ID. Current player count, or `0` when no instance is running. Blueprint or container image source. Lifecycle and manual workflows. Custom properties. Tags used for filtering and organization. Creation timestamp in ISO 8601 format. Last update timestamp in ISO 8601 format. Use `api.server()` to work with the running instance. Its `getPersistentServerId()` method links it back to this configuration. # Players API Source: https://simplecloud.app/docs/en/developer/api/players Look up players, inspect presence, transfer or kick them, and manage player data ## Look up a player The examples use the shared `CloudApi` client created in [Installation](/docs/en/developer/installation) and belong inside your plugin's methods. Prefer a player's UUID when you know it because usernames can change. Look up a player by UUID and check whether they are online before using their current server: ```java theme={null} api.player().get(playerId).thenAccept(player -> { if (player == null || !player.isOnline()) { logger.info("Player is offline"); return; } String serverName = player.getConnectedServerName(); logger.info(serverName == null ? "Player is connected through a proxy" : "Player is on " + serverName); }); ``` `get(UUID)` returns `null` when SimpleCloud has no stored player with that UUID. You can also look up a player by their case-insensitive username: ```java theme={null} api.player().get("Steve"); ``` A `CloudPlayer` contains the state recorded when you queried it. Fetch the player again when a later action depends on their current presence. ## List online players Use the online player list when you need the players themselves, or request only the count: ```java theme={null} api.player().getOnlinePlayers(); api.player().getOnlinePlayerCount(); ``` The list is empty and the count is `0` when no players are online. ## Inspect player data | Method | Value | | -------------------------- | -------------------------------------------- | | `getUniqueId()` | Player UUID | | `getName()` | Username | | `getDisplayName()` | Stored display name | | `isOnline()` | Whether the player was online when queried | | `getConnectedProxyName()` | Connected proxy name, or `null` | | `getConnectedServerName()` | Registered backend server name, or `null` | | `getSessionId()` | Active session ID, or `null` | | `getFirstSeen()` | First-seen ISO-8601 timestamp, or `null` | | `getLastSeen()` | Last-seen ISO-8601 timestamp, or `null` | | `getOnlineTimeSeconds()` | Accumulated online time | | `getProperties()` | Immutable custom properties, or an empty map | ## Connect a player Call `connect(...)` with the server name registered on the player's proxy, such as `lobby-1`. Do not pass the server UUID. Connecting players requires the `simplecloud-api` provider on the Velocity or BungeeCord proxy. | Result | Meaning | | ------------------- | ------------------------------------------------------------------------------------------------------------------- | | `SUCCESS` | The player connected to the target server. | | `SERVER_NOT_FOUND` | The proxy does not know the target server name. | | `ALREADY_CONNECTED` | The player is already connected to the target server. | | `PLAYER_NOT_FOUND` | Not currently returned by `connect(...)`; the transfer guide uses it when its player lookup finds no online player. | | `CONNECTION_FAILED` | The connection could not be completed, including when the player is no longer available. | See [Transfer a player to another server](/docs/en/developer/guides/player-transfer) for a complete transfer workflow. ## Kick a player Pass an Adventure component as the reason shown to the player: ```java theme={null} player.kick(Component.text("Server restarting")); ``` Kicking players requires the `simplecloud-api` provider on the Velocity or BungeeCord proxy. ## Send Adventure content `CloudPlayer` implements Adventure's `Audience`, so you can send messages, action bars, titles, sounds, boss bars, books, and player-list headers and footers. ```java theme={null} player.sendMessage(Component.text("Welcome!")); player.sendActionBar(Component.text("Combat mode enabled")); player.showTitle(Title.title( Component.text("Welcome"), Component.text("to the server") )); ``` Remote Adventure content requires the `simplecloud-api` provider on the player's Paper or Folia server. ## Manage online time and properties Player properties store custom string values for your plugins. | Task | Method | | ------------------------- | ----------------------------------------------------------------------------------------- | | Read online time | `getOnlineTimeSeconds(playerId)` | | Set online time | `setOnlineTimeSeconds(playerId, seconds)` | | Reset online time | `resetOnlineTime(playerId)` | | Add or remove time | `addOnlineTimeSeconds(playerId, seconds)` or `removeOnlineTimeSeconds(playerId, seconds)` | | Set one property | `updatePlayerProperty(playerId, key, value)` | | Set several properties | `updatePlayerProperties(playerId, properties)` | | Delete one property | `deletePlayerProperty(playerId, key)` | | Delete several properties | `deletePlayerProperties(playerId, keys)` | Online time must be between `0` and `Integer.MAX_VALUE` seconds. The add and remove helpers read the current value before writing the result, so concurrent changes can overwrite one another. Property updates merge the supplied values with the existing map, while delete methods remove only the specified keys. The merged properties must fit within 4 KB when encoded as JSON. # Servers API Source: https://simplecloud.app/docs/en/developer/api/servers Find, inspect, update, and stop running server instances ## Find available capacity The examples use the shared `CloudApi` client created in [Installation](/docs/en/developer/installation) and belong inside your plugin's methods. Use `ServerQuery` to find instances by source, state, host, or numerical ID. This example calculates the reported free slots across playable lobby servers: ```java theme={null} ServerQuery query = ServerQuery.create() .filterByServerGroupName("lobby") .filterByState(ServerState.AVAILABLE, ServerState.INGAME); api.server().getAllServers(query) .thenApply(servers -> servers.stream() .filter(server -> server.getPlayerCount() != null) .mapToInt(server -> Math.max( 0, server.getMaxPlayers() - server.getPlayerCount() )) .sum()) .thenAccept(capacity -> System.out.println("Lobby capacity: " + capacity)); ``` The result is a snapshot, not a reservation. If you use it to choose where a player should connect, keep the routing policy in your application and handle the connection result. See [Route players with autoscaling](/docs/en/developer/guides/server-management) for a complete routing workflow. Call `getAllServers()` without a query to return every instance, or use `getServersByGroup("lobby")` as a group-name shortcut. List methods return an empty list when nothing matches. Repeated calls to a multi-value filter add values to the query. Match one or more group IDs. Match one or more lifecycle states. Match instances running on one serverhost. Match the instance of one persistent server. Match `SERVER` or `PROXY` sources. Match one or more group or persistent server names. Match sources with any supplied tag. Match one or more numerical IDs. Sort by `created_at`, `updated_at`, `numerical_id`, or `state`. Use `asc` or `desc`. ## Find one server Look up an instance by its unique ID, or by its group name and numerical ID: ```java theme={null} api.server().getServerById("server-uuid") .thenAccept(server -> System.out.println(server.getState())); api.server().getServerByNumericalId("lobby", 1) .thenAccept(server -> System.out.println(server.getServerId())); ``` These lookups complete exceptionally when no matching server exists. ### Get the current server Code running inside a SimpleCloud-managed server can resolve its own instance: ```java theme={null} api.server().getCurrentServer() .thenAccept(server -> System.out.println(server.getServerId())); ``` `getCurrentServer()` uses the `SIMPLECLOUD_UNIQUE_ID` environment variable and completes exceptionally when the current process is not associated with an instance. ## Access the owning configuration Every instance belongs to either a group or a persistent server. `getServerBase()` provides their shared configuration, while `getGroup()` and `getPersistentServer()` expose source-specific fields. To change how instances are created, update the owning [group](/docs/en/developer/api/groups) or [persistent server](/docs/en/developer/api/persistent-servers) instead. ```java theme={null} api.server().getServerById("server-uuid") .thenAccept(server -> { if (server.isFromGroup()) { System.out.println("Group: " + server.getGroup().getName()); } else { System.out.println( "Persistent server: " + server.getPersistentServer().getName() ); } System.out.println( "Configured slots: " + server.getServerBase().getMaxPlayers() ); }); ``` Only one of `getGroup()` and `getPersistentServer()` is available for an instance. Avoid the deprecated `getServerGroup()`, which throws for persistent server instances. ## Update an instance `UpdateServerRequest` changes only the fields you set: ```java theme={null} UpdateServerRequest update = UpdateServerRequest.builder() .maxPlayers(64) .maxMemory(2048) .build(); api.server().updateServer("server-uuid", update) .thenAccept(server -> System.out.println("Updated slots: " + server.getMaxPlayers())); ``` The builder supports `state`, `properties`, `minMemory`, `maxMemory`, and `maxPlayers`. Changes apply to this instance, not its owning configuration. `playerCount` is a runtime observation reported by the serverhost and is read-only over the HTTP API; sending it in an update request is rejected as an unknown field. The platform normally reports `state`; only set it when your integration owns that reporting. ## Manage instance properties Properties attach application data to one instance. Updates merge with the existing map. ```java theme={null} api.server().updateServerProperties( "server-uuid", Map.of("gameMode", "competitive", "map", "castle") ); api.server().deleteServerProperty("server-uuid", "map"); ``` Use `updateServerProperty` to set one key and `deleteServerProperties` to remove several keys. Each method returns the resulting property map. ## Stop an instance ```java theme={null} api.server().stopServer("server-uuid") .thenRun(() -> System.out.println("Shutdown initiated")); ``` The future completes when SimpleCloud initiates the stop, not when cleanup finishes. Use [server state events](/docs/en/developer/api/events) if your plugin must observe the later lifecycle transitions. Stopping an instance does not disable its group or persistent server. SimpleCloud may create a replacement to maintain the source configuration. Change that configuration first when the server must stay offline. ## Server model Unique instance ID. Numerical ID within the source group or persistent server. Source group ID, or `null` for a persistent server instance. Source persistent server ID, or `null` for a group instance. Serverhost running the instance. Network that owns the instance. Assigned IP address, or `null` before one is available. Assigned port, or `null` before one is available. Minimum memory in MB. Maximum memory in MB. Current CPU usage percentage, or `null` when unavailable. Current memory usage in MB, or `null` when unavailable. Current connected player count, or `null` when unavailable. Player limit for the instance. Current lifecycle state. Creation timestamp in ISO 8601 format. Last update timestamp in ISO 8601 format. Last activity timestamp in ISO 8601 format, or `null` when unavailable. Instance properties, or `null` when none are available. Reserved accessor. The current implementation returns `null`; use the source configuration instead. Shared configuration from the source group or persistent server. Source group, or `null` for a persistent server instance. Source persistent server, or `null` for a group instance. ## Server states | State | Meaning | | --------------- | --------------------------------------------------- | | `UNKNOWN_STATE` | Unknown or unspecified. | | `PREPARING` | SimpleCloud is preparing the instance. | | `STARTING` | The server process is starting. | | `AVAILABLE` | Ready to accept connections. | | `INGAME` | Running with active players. | | `STOPPING` | Shutdown is in progress. | | `CLEANUP` | The process has stopped and cleanup is in progress. | # React to server availability Source: https://simplecloud.app/docs/en/developer/guides/event-handling Run your plugin logic when a server becomes available ## Listen for available servers The listener uses the `CloudApi` client your plugin already owns and notifies your application code when a server becomes available: ```java ServerAvailabilityListener.java theme={null} package com.example; import app.simplecloud.api.CloudApi; import app.simplecloud.api.event.Subscription; import app.simplecloud.api.server.ServerState; public final class ServerAvailabilityListener implements AutoCloseable { private final Subscription subscription; public ServerAvailabilityListener( CloudApi cloudApi, Runnable onServerAvailable ) { subscription = cloudApi.event().server().onStateChanged(event -> { if (event.getNewState() == ServerState.AVAILABLE) { onServerAvailable.run(); } }); } @Override public void close() { subscription.close(); } } ``` Create the listener when your plugin starts and connect it to the work that is waiting for an available server: ```java theme={null} serverAvailability = new ServerAvailabilityListener( cloudApi, () -> matchmaking.refreshAvailableServers() ); ``` Treat the callback as a signal to retry waiting work or refresh the destinations known to your routing system. Events only report changes that happen after you subscribe. If your plugin also needs the current state when it starts, load it separately through the [Servers API](/docs/en/developer/api/servers). If the callback changes Bukkit, Folia, Velocity, or BungeeCord state, schedule that platform-specific work through the platform's scheduler. ## Close the listener Close the listener when your plugin stops, before closing the shared `CloudApi` client: ```java theme={null} if (serverAvailability != null) { serverAvailability.close(); } ``` This stops future callbacks. The listener does not close the shared `CloudApi` client. See the [Events API reference](/docs/en/developer/api/events) for the other event categories and callback types. # Transfer a player to another server Source: https://simplecloud.app/docs/en/developer/guides/player-transfer Connect an online player to a known server and handle the result ## Transfer the player Before you begin, [install the Cloud API](/docs/en/developer/installation), require the `simplecloud-api` platform plugin, and create one shared `CloudApi` client. Install `simplecloud-api` on every proxy that may handle the player because that proxy performs the transfer. Pass the registered server name, such as `lobby-1`, rather than the UUID returned by `Server.getServerId()`. Look up the player by UUID, confirm they are online, and connect them to the registered server name: ```java PlayerTransferService.java theme={null} import app.simplecloud.api.CloudApi; import app.simplecloud.api.player.CloudPlayer; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.logging.Level; import java.util.logging.Logger; public final class PlayerTransferService { private final CloudApi api; private final Logger logger; public PlayerTransferService(CloudApi api, Logger logger) { this.api = api; this.logger = logger; } public CompletableFuture transfer( UUID playerId, String registeredServerName ) { return api.player().get(playerId).thenCompose(player -> { if (player == null || !player.isOnline()) { return CompletableFuture.completedFuture( CloudPlayer.ConnectResult.PLAYER_NOT_FOUND ); } return player.connect(registeredServerName); }); } public void transferToLobby(UUID playerId) { transfer(playerId, "lobby-1") .thenAccept(result -> { switch (result) { case SUCCESS, ALREADY_CONNECTED -> logger.info("Player is connected to lobby-1"); case SERVER_NOT_FOUND -> logger.warning("lobby-1 is not registered on the proxy"); case PLAYER_NOT_FOUND -> logger.info("Player is no longer online"); case CONNECTION_FAILED -> logger.warning("Could not connect player to lobby-1"); } }) .exceptionally(error -> { logger.log(Level.WARNING, "Could not transfer player", error); return null; }); } } ``` Create one `PlayerTransferService` from your plugin's shared `CloudApi` and logger. Call `transferToLobby(...)` from your command or matchmaking flow. The service returns `PLAYER_NOT_FOUND` when its lookup finds no online player. If the player disconnects after that check, `connect(...)` returns `CONNECTION_FAILED`. ## Connection results | Result | Meaning | | ------------------- | ---------------------------------------------------------- | | `SUCCESS` | The player connected to the destination. | | `ALREADY_CONNECTED` | The player is already connected to the destination. | | `SERVER_NOT_FOUND` | The supplied name is not registered on the player's proxy. | | `PLAYER_NOT_FOUND` | The lookup found no online player. | | `CONNECTION_FAILED` | The proxy could not complete the connection. | If your plugin needs to find an available destination first, see [Route players with autoscaling](/docs/en/developer/guides/server-management). # Route players with autoscaling Source: https://simplecloud.app/docs/en/developer/guides/server-management Send a player to an available server without managing group capacity yourself ## Route a player to a group Let SimpleCloud manage the number of servers in a group. This workflow only chooses from instances that are ready now. The following router finds playable servers in a group, ignores full instances, and attempts one connection. It returns `NoCapacity` when no suitable server is available and `ConnectionAttempted` with the result from `CloudPlayer.connect` otherwise. ```java GroupRouter.java theme={null} package com.example; import app.simplecloud.api.CloudApi; import app.simplecloud.api.player.CloudPlayer; import app.simplecloud.api.server.Server; import app.simplecloud.api.server.ServerQuery; import app.simplecloud.api.server.ServerState; import java.util.Comparator; import java.util.concurrent.CompletableFuture; public final class GroupRouter { private final CloudApi api; public GroupRouter(CloudApi api) { this.api = api; } public CompletableFuture routeToGroup( CloudPlayer player, String groupName ) { ServerQuery query = ServerQuery.create() .filterByServerGroupName(groupName) .filterByState(ServerState.AVAILABLE, ServerState.INGAME); return api.server().getAllServers(query).thenCompose(servers -> servers.stream() .filter(server -> server.getPlayerCount() != null) .filter(server -> server.getPlayerCount() < server.getMaxPlayers()) .min(Comparator .comparingInt((Server server) -> server.getPlayerCount()) .thenComparingInt(Server::getNumericalId)) .>map(server -> { String serverName = groupName + "-" + server.getNumericalId(); return player.connect(serverName) .thenApply(RouteResult.ConnectionAttempted::new); }) .orElseGet(() -> CompletableFuture.completedFuture( new RouteResult.NoCapacity() ))); } public sealed interface RouteResult { record NoCapacity() implements RouteResult {} record ConnectionAttempted( CloudPlayer.ConnectResult result ) implements RouteResult {} } } ``` `AVAILABLE` and `INGAME` servers can accept players. Sorting by player count spreads new connections across the group, while the numerical ID gives the selection a stable tie-breaker. The server name uses SimpleCloud's default `-` registration pattern, such as `lobby-3`. If you changed the registration pattern, build the name with that same pattern here. Handle `NoCapacity` by keeping the player in your queue or fallback lobby. For `ConnectionAttempted`, use the returned `ConnectResult` to confirm the connection or show an appropriate fallback. ## Next steps * Use the [Groups API](/docs/en/developer/api/groups) to create and configure groups. * Use the [event handling guide](/docs/en/developer/guides/event-handling) when your plugin should react as servers become available. * See the [Servers API](/docs/en/developer/api/servers) for server queries, models, and lifecycle actions. # Installation Source: https://simplecloud.app/docs/en/developer/installation Add the Cloud API to your Minecraft plugin ## Add the API dependency The Cloud API requires Java 21. Add the SimpleCloud and Buf repositories, then add the API with `compileOnly` in Gradle or `provided` in Maven: Do not shade the Cloud API into your plugin. The `simplecloud-api` platform plugin provides it at runtime, and bundling another copy can cause class-loading conflicts. Pin the dependency to the version you tested before releasing your plugin. ## Require the platform plugin Declare `simplecloud-api` as a required dependency so it loads before your plugin. SimpleCloud's default templates already include the matching platform plugin. If you use custom templates, keep it in the `plugins` directory. Add the dependency to `src/main/resources/paper-plugin.yml`: ```yaml paper-plugin.yml theme={null} name: my-plugin version: "1.0.0" main: com.example.MyPlugin api-version: "1.21" dependencies: server: simplecloud-api: load: BEFORE required: true join-classpath: true ``` Add the dependency to `src/main/resources/plugin.yml`: ```yaml plugin.yml theme={null} name: my-plugin version: "1.0.0" main: com.example.MyPlugin api-version: "1.21" folia-supported: true depend: - simplecloud-api ``` Add the dependency to `src/main/resources/plugin.yml`: ```yaml plugin.yml theme={null} name: my-plugin version: "1.0.0" main: com.example.MyPlugin api-version: "1.20" depend: - simplecloud-api ``` Add the dependency to the `@Plugin` annotation on your main class: ```java MyPlugin.java theme={null} import com.velocitypowered.api.plugin.Dependency; import com.velocitypowered.api.plugin.Plugin; @Plugin( id = "my-plugin", name = "My Plugin", version = "1.0.0", dependencies = {@Dependency(id = "simplecloud-api")} ) public final class MyPlugin { } ``` Add the dependency to `src/main/resources/plugin.yml`: ```yaml plugin.yml theme={null} name: my-plugin version: "1.0.0" main: com.example.MyPlugin depends: - simplecloud-api ``` ## Create one client Create a `CloudApi` instance when your plugin starts, reuse it for every request, and close it when your plugin stops. SimpleCloud provides the connection settings automatically. ```java MyPlugin.java theme={null} package com.example; import app.simplecloud.api.CloudApi; import org.bukkit.plugin.java.JavaPlugin; public final class MyPlugin extends JavaPlugin { private CloudApi cloudApi; @Override public void onEnable() { cloudApi = CloudApi.create(); } @Override public void onDisable() { if (cloudApi != null) { cloudApi.close(); } } } ``` Most API calls return `CompletableFuture`; compose them instead of blocking, and use your platform's scheduler before changing platform state from a callback. ### Velocity lifecycle On Velocity, create and close the same client from the proxy lifecycle events: ```java MyPlugin.java theme={null} private CloudApi cloudApi; @Subscribe public void onProxyInitialize(ProxyInitializeEvent event) { cloudApi = CloudApi.create(); } @Subscribe public void onProxyShutdown(ProxyShutdownEvent event) { if (cloudApi != null) { cloudApi.close(); } } ``` `CloudApi.create()` uses the connection settings supplied by SimpleCloud. If your plugin needs different request timeouts or cache behavior, pass a custom `CloudApiOptions` instance. ## Troubleshooting Confirm that your build contains both repositories shown above, then refresh dependencies with `./gradlew --refresh-dependencies` or `mvn -U package`. Check that: * The matching `simplecloud-api` platform plugin is installed and enabled. * Your plugin declares it as a required dependency. Paper plugins also need `join-classpath: true`. * Your build uses `compileOnly` or `provided` and does not shade the API. Confirm that SimpleCloud started the server and that the matching `simplecloud-api` platform plugin is enabled. # Cloud API Source: https://simplecloud.app/docs/en/developer/overview Build Minecraft plugins that work with your SimpleCloud network ## Choose where to begin Add the dependency and create a client for your plugin. Create groups, change their configuration, and request new servers. Find, inspect, update, and stop server instances. Manage servers that keep their identity across restarts. Look up players, send messages, and connect them to servers. Run code when groups, servers, persistent servers, or blueprints change. ## Build a common workflow Move an online player to another server and handle the result. Select available capacity without competing with SimpleCloud autoscaling. Subscribe to network changes for the lifetime of your plugin. # Configurators Source: https://simplecloud.app/docs/en/manual/configuration/configurators Customize software configuration files before a server starts ## Create a custom configurator The dashboard selects a built-in configurator when you create a group or persistent server. A standard setup needs no extra work. Create a custom configurator when the built-in one does not manage a setting you need. Use [templates](/docs/en/manual/setup/templates) when you only need to copy the same files to your servers. A custom configurator replaces the selected built-in configurator. Keep the built-in settings that your server needs, especially its port and proxy settings. This example extends the **Paper/Spigot Standalone** configurator with a difficulty and view distance. If your server connects through a proxy, start with the matching proxy configurator instead. On the serverhost, create `options/configurators/paper_survival.yml`: ```yaml options/configurators/paper_survival.yml theme={null} paths: - path: "server.properties" type: "PROPERTIES" data: server-ip: "0.0.0.0" server-port: %port% max-players: %max-players% online-mode: true difficulty: "hard" view-distance: 10 ``` Each `path` is relative to the server's own directory. The file can contain several path entries when you need to configure more than one file. Open the group or persistent server in the dashboard, then go to **Settings > Blueprint**. Under **Software Configuration**, select **Custom**, enter `paper_survival`, and save. Restart the group or persistent server. SimpleCloud applies the configurator to every server that uses its blueprint before that server starts. If the server can run on multiple serverhosts, add the configurator file to each one. ## Configurator reference Each entry under `paths` identifies a configuration file, its format, and the values to apply. | Type | File format | | ------------ | --------------- | | `YML` | YAML | | `JSON` | JSON | | `TOML` | TOML | | `PROPERTIES` | Java properties | | `TXT` | Plain text | Structured files keep values that are not specified in the configurator. `TXT` replaces the complete file. Use placeholders when a value depends on the server instance. | Placeholder | Value | | --------------------------- | ------------------------------- | | `%port%` | Assigned port | | `%group%` | Group or persistent server name | | `%numerical-id%` | Instance number | | `%type%` | Server or proxy type | | `%min-memory%` | Minimum memory in MB | | `%max-memory%` | Maximum memory in MB | | `%max-players%` | Player limit | | `%forwarding-secret%` | Proxy forwarding secret | | `%velocity-config-version%` | Velocity configuration version | Quote placeholders whose resulting value must be text: ```yaml theme={null} server-name: "%group%" server-port: %port% ``` Custom properties from the group or persistent server are also available as placeholders. For example, a property named `motd` can be used as `%motd%`. To insert a password, token, or another private value, use a [secret reference](/docs/en/manual/configuration/secrets) as the Configurator value: ```yaml theme={null} password: "{{ secrets.DATABASE_PASSWORD }}" ``` ## Troubleshooting Confirm that `options/configurators/{name}.yml` exists on every serverhost that can run the server. The custom name in the dashboard must match the filename without `.yml`. Restart the server first. If the value still does not change, check that `path` is relative to the server directory, `type` matches the file format, and the setting is nested correctly under `data`. Check the placeholder spelling and use percent syntax such as `%port%`. For a custom placeholder, add a property with the same name to the group or persistent server. Check the serverhost log for a configurator error. Common causes are invalid YAML, an unsupported `type`, or a value whose structure does not match the target file. # Secrets Source: https://simplecloud.app/docs/en/manual/configuration/secrets Keep passwords and tokens out of templates and workflow files ## Use a database password in a plugin configuration This example uses a template. SimpleCloud leaves the reference in the template and inserts the password into the running server's copy before the process starts. Open **[Settings > Secrets](https://dash.simplecloud.app/redirect?target=%2Fsettings%2Fsecrets)** in the dashboard and select **Add secret**. Enter `DATABASE_PASSWORD` as the key, enter the password as the value, then select **Encrypt & save**. At least one serverhost must be connected before you can add a secret. After saving, the dashboard shows the key but cannot display the value again. Open **Files**, select the serverhost, and edit the plugin configuration in the matching [template](/docs/en/manual/setup/templates). For example, place this file at `templates/lobby/plugins/DatabasePlugin/config.yml`: ```yaml templates/lobby/plugins/DatabasePlugin/config.yml theme={null} database: host: "db.internal.example" port: 3306 name: "minecraft" username: "simplecloud" password: "{{ secrets.DATABASE_PASSWORD }}" ``` Adapt the path and surrounding settings to your plugin. Keep the secret reference exactly as shown. For a persistent server that already has this file, stop the server and edit its existing configuration from the server's **Files** page instead. A template does not replace an existing persistent-server file. Start a new `lobby` server. If you edited a persistent server, start it again. SimpleCloud copies the template when needed, replaces the reference in the running file, and then starts the server process. Servers that are already running keep the value with which they started. Confirm that the plugin connects successfully. When you open the running file in the dashboard, the editor still shows `{{ secrets.DATABASE_PASSWORD }}` instead of the password. This is intentional. ## Use secrets in configurators and workflows The same `{{ secrets.KEY }}` reference works in a [Configurator](/docs/en/manual/configuration/configurators). Use it as a value, not as part of the target file path: ```yaml theme={null} paths: - path: "plugins/DatabasePlugin/config.yml" type: "YML" data: database: password: "{{ secrets.DATABASE_PASSWORD }}" ``` Workflow parameters can also use secrets. This upload step reads its bearer token at runtime, so the token does not appear in the [workflow file](/docs/en/manual/configuration/workflows): ```yaml theme={null} - name: upload-backup uses: simplecloud/upload with: from: "{{ runtime.server-dir }}/backups/latest.zip" to: "https://backups.example.com/upload" method: "PUT" authorization-bearer: "{{ secrets.BACKUP_TOKEN }}" ``` Create `BACKUP_TOKEN` under **Settings > Secrets** before running this workflow. The upload source must already exist. ## Rotate or delete a secret Open the action menu next to a key under **Settings > Secrets** and select **Rotate secret** to replace its value. The key stays the same, so you do not need to edit its references. Restart each affected server to apply the new value. During a rolling restart, old and new instances can temporarily use different values. Remove every reference before deleting a secret. A server does not start if one of its configuration files requires a missing secret. A workflow that uses a missing secret cannot receive its value. SimpleCloud creates and manages `VELOCITY_SECRET` for secure proxy forwarding. Do not rotate or delete it manually. A changed forwarding secret must reach the proxy and every backend server together, or connections between them will fail. ## How secrets are protected Every serverhost in the network can use every key. Use separate networks when values must not be shared between hosts. When you save a secret, the dashboard encrypts it in your browser with the network's public key. The controller stores the encrypted value and cannot decrypt it. The connected serverhosts share the corresponding private key and decrypt secrets in memory when a server or workflow needs them. During server startup, SimpleCloud runs the configured start workflows first. It then replaces secret references in copied or configured text files and starts the server process. The source template keeps its reference. SimpleCloud records only the managed file locations, not the secret values. That record lets later rotations update the same locations. The running server needs the real value, so SimpleCloud writes it to the running configuration file. Users and processes with direct access to that serverhost or server directory can read it. Secrets keep the value out of templates and workflow files. The controller stores only ciphertext, but the software using the secret receives the real value. Secret keys and values have these limits: * A key starts with a letter or underscore and contains up to 64 letters, numbers, underscores, or hyphens. The dashboard converts new keys to uppercase. * A value cannot be empty and can contain up to 16 KB. Whitespace and line breaks are preserved. * References are case-sensitive. Copy the reference shown under **Settings > Secrets** to avoid a mismatch. * Use references in text configuration files. Do not put them in JAR files, worlds, databases, or archives. ## Troubleshooting Start or reconnect a serverhost. The first connected serverhost registers the network's encryption key, after which the dashboard enables secret creation. Open **Settings > Secrets** and compare the key with the text inside `{{ secrets.KEY }}`. Keys are case-sensitive. Add the missing key or correct the reference before starting the server. Rotation does not change a process that is already running. Restart every server and rerun every manual workflow that should use the new value. The dashboard file editor and downloads replace managed plaintext with the reference before sending the file to your browser. Check the application behavior or its connection result instead of looking for the value in the editor. Check the serverhost log for `Missing secret` or `Failed to apply secrets`. Create the named key or remove its reference, then start the server again. If one required secret is missing, SimpleCloud leaves all secret-managed files unchanged. # Workflows Source: https://simplecloud.app/docs/en/manual/configuration/workflows Run file operations when a server starts, stops, or on demand ## Run the backup workflow Create `workflows/default/backup.yml` in your serverhost directory: ```yaml workflows/default/backup.yml theme={null} name: Backup Workflow steps: - name: copy-running-to-backup uses: simplecloud/copy with: from: "{{ runtime.server-dir }}" to: "{{ runtime.templates }}/.backup/{{ runtime.name }}/{{ time.now.date }}/{{ time.now.dateTime }}-{{ runtime.nice-id }}-{{ runtime.process-id }}" init-dir-if-missing: true ``` Restart the serverhost. SimpleCloud uses the file path as the workflow ID, so this workflow becomes `default/backup`. In the dashboard, open a server group or persistent server and go to **Settings > Workflows**. Under **Manual Workflows**, add `default/backup`. Start the server if it is not already running. Then open its actions menu and run `default/backup` to test the workflow. On the serverhost, open: ```text theme={null} templates/.backup///--/ ``` Confirm that the final directory contains the files you expected. Its timestamp and process ID keep separate backup runs apart. A workflow is available only on serverhosts that contain its file. If the affected servers can run on multiple serverhosts, add the same file to each one and restart them. The manual action copies files while the Minecraft server is running. Files that change during the copy, such as worlds and plugin data, may not form a consistent backup. For those files, add `default/backup` under **On Stop Workflows** and stop the server normally. Stop workflows run after the server process exits. Place `default/backup` before `internal/cleanup`. `internal/cleanup` removes a group server's running directory. Any workflow that reads that directory must run before cleanup. This workflow creates file copies but does not test restores or remove old backups. Verify that you can restore the data you need and manage retention for `templates/.backup/`. ## Understand the workflow file The backup workflow contains the same basic structure as every workflow: * `name` identifies the workflow in serverhost logs. * `steps` contains the operations in the order they run. * `name` inside a step identifies that step in logs. * `uses` selects the action. This workflow uses `simplecloud/copy`. * `with` contains the values required by the action. In this workflow, `from` points to the running server directory and `to` builds a unique backup path. If the source is missing, `init-dir-if-missing: true` creates an empty source directory instead of failing. Always verify that the resulting backup contains the expected files. ### Values used by the workflow Values inside `{{ ... }}` are replaced when the workflow runs. | Value | Result | | -------------------------- | -------------------------------------- | | `{{ runtime.server-dir }}` | Running server directory | | `{{ runtime.templates }}` | Serverhost template directory | | `{{ runtime.name }}` | Server group or persistent server name | | `{{ runtime.nice-id }}` | Running server name, such as `lobby-1` | | `{{ runtime.process-id }}` | Running process ID | | `{{ time.now.date }}` | Current date | | `{{ time.now.dateTime }}` | Current date and time | ## Adapt the backup workflow Use the backup workflow as a starting point: Copy `workflows/default/backup.yml` to a new path, such as `workflows/custom/world-backup.yml`. Give it a new `name`, then change the copy paths and exclusions for your task. Restart every serverhost that contains the new file. Add `custom/world-backup` under **Settings > Workflows**. A workflow ID is always its path below `workflows/`, without `.yml`. ### Change what gets copied The `simplecloud/copy` action accepts these settings under `with`: | Setting | Purpose | | --------------------- | ---------------------------------------------------------------------------------- | | `from` | File or directory to copy | | `to` | Destination for the copy | | `replace` | Whether to overwrite existing files; defaults to `true` | | `exclude` | Path or list of paths to leave out | | `init-dir-if-missing` | Whether to create the source directory when it does not exist; defaults to `false` | For example, add an `exclude` list to skip logs and caches while keeping the rest of the backup unchanged: ```yaml theme={null} with: from: "{{ runtime.server-dir }}" to: "{{ runtime.templates }}/.backup/{{ runtime.name }}/{{ time.now.date }}/{{ time.now.dateTime }}-{{ runtime.nice-id }}-{{ runtime.process-id }}" init-dir-if-missing: true exclude: - "logs/**" - "cache/**" ``` Patterns in `exclude` are relative to `from`. ## Available actions `simplecloud/copy` copies a file or directory from `from` to `to`. Use `replace` to control whether existing files are overwritten and `exclude` to skip matching paths. `simplecloud/compress` creates an archive and `simplecloud/decompress` extracts one. Both require `from` and `to`; `replace` is optional. The archive filename determines its format. `simplecloud/upload` sends the file in `from` to the URL in `to`. It uploads files, not directories. You can also set the HTTP `method` and an `authorization-bearer` value. Store long-lived access tokens under **Settings > Secrets** and set `authorization-bearer` to a [secret reference](/docs/en/manual/configuration/secrets), such as `"{{ secrets.BACKUP_TOKEN }}"`. `simplecloud/delete` removes the configured `path`. Use `min-age`, such as `7d`, to keep newer files. Delete paths are not limited to the server directory. Check the final path before running the workflow. `simplecloud/foreach` runs nested steps for each entry in `items`. Set `as` to the variable name used by the nested `steps`. ## Built-in workflows | Workflow | Purpose | | ------------------ | -------------------------------------------- | | `internal/setup` | Prepares the server directory before startup | | `internal/cleanup` | Cleans up files after the server stops | Keep `internal/setup` and `internal/cleanup` assigned unless you intentionally replace their behavior. ## Troubleshooting Workflow IDs are entered manually in the dashboard. Confirm the file exists on the serverhost, restart the serverhost, and add the ID again. Check that the ID matches the file path. For example, `custom/world-backup` must point to `workflows/custom/world-backup.yml`. Check the serverhost logs for `Backup Workflow` and `copy-running-to-backup`. For an automatic backup, also confirm that `default/backup` comes before `internal/cleanup`. # CLI Source: https://simplecloud.app/docs/en/manual/introduction/architecture/cli Set up and manage SimpleCloud from your terminal ## Install the CLI Run the installer on the machine that will host SimpleCloud: ```bash theme={null} curl -fsSL https://get.simplecloud.app | bash ``` Then check that the CLI is available: ```bash theme={null} sc --version ``` To set up the first serverhost from the dashboard, follow [Installation](/docs/en/manual/setup/installation). To complete the setup from the CLI, continue below. ## Set up your serverhost Start the setup wizard: ```bash theme={null} sc setup ``` The wizard signs you in, connects the machine to your network, and installs the serverhost. When it finishes, you can manage SimpleCloud from the CLI or dashboard. ## Manage SimpleCloud on this machine Use these commands to operate the local installation: | Task | Command | | --------------------------- | ---------------------- | | Start SimpleCloud | `sc start` | | Stop SimpleCloud | `sc stop` | | Restart SimpleCloud | `sc restart` | | Check its status | `sc status` | | View serverhost logs | `sc logs serverhost` | | Open the serverhost console | `sc attach serverhost` | Local commands such as `sc start` manage SimpleCloud on the current machine. Commands under `sc server` manage Minecraft servers in your network. ## Manage groups and servers Create a server group with the interactive wizard: ```bash theme={null} sc group create ``` You can then start a server and view the running servers: ```bash theme={null} sc group start lobby sc server list ``` Use these commands for common server tasks: ```bash theme={null} sc server info lobby 1 sc server logs lobby 1 --follow sc server stop lobby 1 ``` See [Server groups](/docs/en/manual/setup/server-groups) and [Servers](/docs/en/manual/setup/servers) for the complete workflows. ## Update SimpleCloud Upgrade the CLI and installed SimpleCloud components with one command: ```bash theme={null} sc upgrade ``` If an installed component needs to be downloaded again, run: ```bash theme={null} sc repair ``` ## Sign in Run `sc login` when you need to sign in again. Use `sc whoami` to check the current account and `sc logout` to sign out. ## Switch between networks The CLI saves each network as a context and sends network commands to the active one. Setup creates your first context automatically. ```bash theme={null} sc context list sc context use ``` Run `sc context add` to connect the CLI to another network. ## Add another serverhost On the new machine, install the CLI and run: ```bash theme={null} sc serverhost add ``` Follow [Multi-root setup](/docs/en/manual/setup/multi-root) for the complete process. ## Discover more commands The CLI also supports templates, persistent servers, multiple contexts, and advanced installation options. These workflows have their own guides, while the CLI's built-in help always shows the current command syntax: ```bash theme={null} sc --help sc group --help sc server --help sc persistent-server --help ``` Learn more in [Templates](/docs/en/manual/setup/templates) and [Persistent servers](/docs/en/manual/setup/persistent-servers). # Architecture Source: https://simplecloud.app/docs/en/manual/introduction/architecture/overview Understand how the dashboard, CLI, controller, and serverhost work together ## The three parts you use The web interface for configuring your network and viewing servers, logs, and status. The terminal interface for setting up serverhosts and managing the same network without the dashboard. The background service that prepares and runs Minecraft servers on its machine. The hosted controller coordinates these parts and stores the network state. You do not install or operate it yourself. ## How they work together 1. Install a serverhost on every machine whose resources you want SimpleCloud to use. 2. Configure groups and persistent servers in the dashboard or CLI. 3. SimpleCloud starts the requested Minecraft servers on a suitable serverhost and reports their status and logs. The dashboard and CLI change the same network, so choose whichever interface fits the task. The serverhost does not replace either interface. It runs the Minecraft servers you configure through them. When you add another machine, install another serverhost. SimpleCloud can then use both machines to run your network. ## Next steps Connect your first machine and start using the dashboard. Run replaceable server instances from shared settings and files. Run one named server that keeps its files across restarts. # Serverhost Source: https://simplecloud.app/docs/en/manual/introduction/architecture/serverhost Connect a machine that SimpleCloud can use to run Minecraft servers ## What a serverhost does A serverhost is a machine that runs Minecraft servers for your SimpleCloud network. Install one on each machine whose CPU and memory you want SimpleCloud to use. The serverhost runs in the background. You manage Minecraft servers and choose which serverhosts may run them through the dashboard. A serverhost: * Prepares Minecraft server files from your templates * Starts and stops Minecraft servers * Applies the software, plugins, memory, and other settings you configure * Sends server status, logs, and resource usage to SimpleCloud ## Add a serverhost In the dashboard, open **Settings > Server Hosts** and select **Add Host**. Configure the host, then run the generated setup command on the machine you want to add. The command installs SimpleCloud, connects the serverhost to your network, and starts it. For prerequisites and the complete setup process, follow the [installation guide](/docs/en/manual/setup/installation). Use **Settings > Server Hosts** to view and change a host's settings. Choose which hosts may run servers when you configure a server group. ## Check or control a serverhost Use the CLI when you need to start, stop, update, or troubleshoot the serverhost itself. Run these commands from the SimpleCloud installation directory: ```bash theme={null} # Show whether the serverhost is running sc status serverhost # Read recent serverhost logs sc logs serverhost --lines 200 # Start or stop the serverhost sc start serverhost sc stop serverhost # Restart it and install an available update sc restart serverhost --update ``` ### What happens to running Minecraft servers When you stop or restart a serverhost, the CLI asks whether it should also stop the Minecraft servers running on that machine. * Choose **Yes** when taking the machine offline or when the Minecraft servers must stop too. * Choose **No** for short serverhost maintenance if the Minecraft servers should remain online. The serverhost reconnects to them after it starts again. Do not shut down or reboot the machine while Minecraft servers are still running. Stop them first so they can save their data cleanly. ## Troubleshoot a serverhost If a serverhost is offline or a server cannot start, check that: * The serverhost is online. * It has enough free memory for the server. * The required Java version is installed. * The group is allowed to use that serverhost. Use `sc logs serverhost --lines 200` for more information. You can also review the affected Minecraft server's logs in the dashboard. ## Use multiple serverhosts With multiple serverhosts, SimpleCloud can distribute servers across the machines allowed by each group. This adds capacity, but the machines do not share a filesystem. * Keep templates, workflows, and configurator files synchronized so a server can start correctly on any eligible host. * While a server is running, its files and logs exist only on the serverhost that started it. * A persistent server's files stay on its assigned serverhost. Changing its serverhost does not move those files. Follow the [multi-root setup guide](/docs/en/manual/setup/multi-root) to add another machine and synchronize the shared files. ## Related pages * [Templates](/docs/en/manual/setup/templates) explains how server files are prepared. * [Configurators](/docs/en/manual/configuration/configurators) explains automatic configuration changes. * [Workflows](/docs/en/manual/configuration/workflows) explains advanced preparation and cleanup steps. # FAQ Source: https://simplecloud.app/docs/en/manual/introduction/faq Answers to common questions about setting up and using SimpleCloud SimpleCloud helps you set up and manage a Minecraft server network from one dashboard or the `sc` command. Read the [SimpleCloud overview](/docs/en/manual/introduction/overview) to learn how it organizes your network. Start with the [installation guide](/docs/en/manual/setup/installation). It takes you from signing in to the dashboard to connecting your first serverhost. Use a **server group** when every server should share the same setup and its local files do not need to survive replacement. Groups work well for lobbies, minigames, and proxies. Use a **persistent server** for one named server that keeps its files, such as an SMP, Skyblock, or build server. Compare the options in [Server groups](/docs/en/manual/setup/server-groups) and [Persistent servers](/docs/en/manual/setup/persistent-servers). Your serverhost can run on Linux or macOS. Linux is recommended for production, while macOS is useful for local testing. Windows serverhosts are not supported yet. You can use the web dashboard from a different device. See the [installation guide](/docs/en/manual/setup/installation) for the system requirements. Choose one of the software options offered by the dashboard. If it is not listed, choose **Custom** and fill in the required fields. Follow the creation steps for a [server group](/docs/en/manual/setup/server-groups#create-a-server-group) or a [persistent server](/docs/en/manual/setup/persistent-servers#create-a-persistent-server). Basic setup does not require advanced technical knowledge. You should be comfortable opening a terminal and running the command provided by the dashboard. More advanced customization may require familiarity with your Minecraft server software. Join the [SimpleCloud Discord](https://discord.simplecloud.app) for community help. # Overview Source: https://simplecloud.app/docs/en/manual/introduction/overview Run and manage your Minecraft server network from one dashboard or the SimpleCloud CLI SimpleCloud logo and brand artwork ## Get started Open the SimpleCloud Dashboard and sign in. Its setup wizard gives you the command that installs SimpleCloud on your first machine and connects it to your network. Connect your first machine and create your first server. ## Choose how your servers work * A **server group** creates replaceable servers from shared settings and files. Use groups for proxies, lobbies, and game modes that may need multiple identical servers or automatic scaling. * A **persistent server** is one named server that keeps its own world and files. Use it for a long-running server such as an SMP or build server. * A **serverhost** is a machine on which SimpleCloud runs your Minecraft servers. Add another serverhost when you want to use another machine. ## Learn the essentials Create servers that share a configuration. Create a server that keeps its world and files. Manage and monitor your network in the browser. Manage your network from the terminal. # Philosophy Source: https://simplecloud.app/docs/en/manual/introduction/philosophy The principles and values that guide how we build SimpleCloud ## Who we are We are not a company. We are a group of Minecraft enthusiasts building SimpleCloud together in our free time. These principles guide our decisions across the product. ## Guiding principles ### Simplicity takes effort Making SimpleCloud simple to use requires work behind the scenes. We hide unnecessary complexity behind clear interfaces and ask whether a server administrator can understand a feature without first learning how its internals work. ### User experience comes first Before we build a feature, we ask how a server administrator would naturally use it. This sometimes means choosing a practical workflow over a technically elegant one. If a feature works but is confusing, we improve the feature instead of expecting users to work around it. ### Continuous improvement We do more than add features. We revisit existing workflows, fix problems, and use community feedback to decide what needs attention. We prefer improving the product over documenting avoidable workarounds. ### Built by volunteers SimpleCloud is developed by volunteers in their free time. We build what we believe in, without commercial pressure or investor deadlines. This lets us focus on quality and give features the time they need. We are not bound by deadlines or feature checklists. If something needs more work, it gets more work. ### The brand matters to us SimpleCloud is a Minecraft project, but we still care about creating a cohesive brand. Its visual identity is part of what makes the project enjoyable for us, and we treat it with the same care as the product itself. ## What this means for you * Features ship when they are ready, not because a roadmap deadline arrived. * Fixing problems takes priority over adding features for their own sake. * Community feedback helps shape the direction of SimpleCloud. * We write documentation that we would want to use ourselves. # Sponsors Source: https://simplecloud.app/docs/en/manual/introduction/sponsors Organizations that support SimpleCloud and its open-source development Depot logo Depot logo Depot supports SimpleCloud through its OSS Sponsorship Program by providing access to Depot CI. This gives our team faster build and caching infrastructure for our CI workflows. Mintlify logo Mintlify logo Mintlify supports SimpleCloud through its open-source program by providing the documentation platform and hosting behind this site. This helps us make SimpleCloud easier to learn and use. We are grateful to Depot and Mintlify for supporting SimpleCloud and open-source software. # Updates Source: https://simplecloud.app/docs/en/manual/introduction/updates Keep the SimpleCloud CLI and serverhost up to date ## Update the CLI The CLI tells you when a new version is available but does not update automatically. To install the latest release, run: ```bash theme={null} sc upgrade cli ``` The command replaces the CLI with the latest release. It does not restart the serverhost or any Minecraft servers. Run `sc --version` afterward to confirm the installed version. ## Automatic serverhost updates SimpleCloud automatically assigns the latest release to each serverhost. When the assigned version differs from the installed version, the serverhost downloads the update and restarts itself. The restart affects only the serverhost process. Minecraft servers keep running because they use separate processes. Automatic updates do not update the CLI, Minecraft server software, or plugins. Update those separately. ## Update the serverhost now You normally do not need to update the serverhost yourself. To install an available update immediately, run this command from your SimpleCloud installation directory: ```bash theme={null} sc restart --update ``` This command updates and restarts the serverhost. Run it during a maintenance window. SimpleCloud asks whether it should also stop the Minecraft servers running on this serverhost, unless you saved this choice earlier. After the command completes, confirm that the serverhost is running: ```bash theme={null} sc status serverhost ``` If the serverhost does not start, inspect its logs: ```bash theme={null} sc logs serverhost ``` Fix the reported problem, then run `sc start serverhost` to start it again. ## Other update options Use `sc upgrade` to update the CLI and all installed SimpleCloud components, or `sc upgrade serverhost` to download only the serverhost update. ```bash theme={null} sc upgrade sc upgrade serverhost ``` These commands do not restart running components. Restart the serverhost when you are ready to use its new version. To test or roll back a release, download the version you want: ```bash theme={null} sc upgrade serverhost@ ``` The command does not restart the serverhost. Run `sc restart serverhost` when you are ready to use the selected version. If the CLI installation is not writable by your user, run `sudo sc upgrade cli`. If the installation is damaged but already current, reinstall it with: ```bash theme={null} sc upgrade cli --cli-force ``` When the CLI is several releases behind, it may require an update before other commands can run. # Cloud Command Source: https://simplecloud.app/docs/en/manual/plugin/cloud-command Use SimpleCloud's in-game proxy commands for groups, servers, and players ## Supported software | Software | Plugin Support | | ---------- | -------------- | | Velocity | Yes | | BungeeCord | Yes | | Gate | Planned | ## Install the plugin Download Cloud Command from [GitHub](https://github.com/simplecloudapp/command-plugin/releases) and place it in the proxy template's `plugins/` folder. Standard SimpleCloud templates already include `simplecloud-api`; add it through the target's **Plugins** setting or the CLI if you use a custom template. Start a matching proxy once. Cloud Command creates `plugins/simplecloud-command/messages.yml` in the running proxy directory. For a group proxy, copy `plugins/simplecloud-command/messages.yml` from the running proxy to the same path in its template before stopping it. Files left only in a temporary proxy directory disappear when that proxy stops. See [Templates](/docs/en/manual/setup/templates) for the complete workflow. Give yourself `simplecloud.command.use`, join through the proxy, and run `/cloud`. The help menu lists the subcommands you have permission to use. ## Commands The root command is available as `/cloud`, `/sc`, and `/simplecloud`. ### Groups | Command | Description | | ------------------------------------ | --------------------------------------------------------------- | | `/cloud group list` | List all groups | | `/cloud group info ` | Show group type, memory, player limit, and running server count | | `/cloud group start [count]` | Request one or more new servers for a group | | `/cloud group stop [id]` | Stop all running servers in a group, or one numerical ID | ### Servers | Command | Description | | --------------------------------- | -------------------------------------------------- | | `/cloud server list [group]` | List running servers, optionally filtered by group | | `/cloud server info ` | Show state, memory, and players for one server | | `/cloud server start ` | Request one new server for a group | | `/cloud server stop ` | Stop one running server | ### Players Use `group` for a server group target and `ps` for a persistent server target. | Command | Description | | ------------------------------------------------------ | ----------------------------------------------- | | `/cloud player list ` | List players on a group or persistent server | | `/cloud player info ` | Show player connection details | | `/cloud player send ` | Send one player to a target | | `/cloud player sendall ` | Send every online player to a target | | `/cloud player sendfrom ` | Send players from one source server to a target | | `/cloud player message ` | Send a plain text message to a player | ### Reload | Command | Description | | --------------- | --------------------------------------- | | `/cloud reload` | Run the command plugin's reload command | `/cloud reload` rereads `plugins/simplecloud-command/messages.yml` from the running proxy. Restart the proxy if you edited the template copy instead. ## Permissions | Permission | Description | | ------------------------------------ | --------------------------------------------------- | | `simplecloud.command.use` | Use the root command and view available subcommands | | `simplecloud.command.group.list` | Use `/cloud group list` | | `simplecloud.command.group.info` | Use `/cloud group info` | | `simplecloud.command.group.start` | Use `/cloud group start` | | `simplecloud.command.group.stop` | Use `/cloud group stop` | | `simplecloud.command.server.list` | Use `/cloud server list` | | `simplecloud.command.server.info` | Use `/cloud server info` | | `simplecloud.command.server.start` | Use `/cloud server start` | | `simplecloud.command.server.stop` | Use `/cloud server stop` | | `simplecloud.command.player.list` | Use `/cloud player list` | | `simplecloud.command.player.info` | Use `/cloud player info` | | `simplecloud.command.player.send` | Use player transfer commands | | `simplecloud.command.player.message` | Use `/cloud player message` | | `simplecloud.command.reload` | Use `/cloud reload` | The help menu only shows commands for permissions the sender has. Cloud Command help menu ## Troubleshooting Confirm that `simplecloud-api` is installed and enabled on the same proxy. Cloud Command declares it as a required dependency. Grant the matching permission. The help menu hides subcommands the sender cannot use. Edit `plugins/simplecloud-command/messages.yml` in the proxy template, or copy the tested file back to the template before a temporary group proxy stops. # Notify Source: https://simplecloud.app/docs/en/manual/plugin/notify Send server and group state notifications to staff across your proxy network ## Supported software | Software | Plugin Support | | ---------- | -------------- | | Velocity | Yes | | BungeeCord | Yes | ## Install the plugin Download Notify from [GitHub](https://github.com/simplecloudapp/notify-plugin/releases) and place it in the proxy template's `plugins/` folder. Standard SimpleCloud templates already include `simplecloud-api`; add it through the target's **Plugins** setting or the CLI if you use a custom template. Start a matching proxy once. Notify creates `plugins/simplecloud-notify/messages.yml` in the running proxy directory. For a group proxy, copy `plugins/simplecloud-notify/messages.yml` from the running proxy to the same path in its template before stopping it. Changes that exist only in a temporary running directory disappear when that proxy stops. See [Templates](/docs/en/manual/setup/templates) for the complete workflow. Run `/scnotify reload config` after editing the file on a running proxy. If you edited the template copy, restart the proxy instead. A successful reload prints `Notify configuration was reloaded.` ## Notifications Notify subscribes to the Cloud API event stream and can send messages for: * Server state changes to `STARTING`, `AVAILABLE`, and `STOPPING` * Server stopped events * Group created events * Group deleted events Set a notification message to `null` to disable that specific notification. Set the whole `notifications.server` or `notifications.group` section to `null` to disable that category. Staff can also disable notifications for themselves with `/scnotify disable` and turn them back on with `/scnotify enable`. Notify stores this choice in the player's SimpleCloud properties, so it follows the player across proxies. Notifications are enabled by default. ## Configuration The generated `messages.yml` contains message text, reusable variables, and formatting options. Notify uses [MiniMessage syntax](https://docs.papermc.io/adventure/minimessage/) for text formatting. ```yaml theme={null} version: "1" format: date: "dd.MM.yyyy HH:mm:ss" variables: prefix: "" notifications: hover: server: |- <#E2E8F0>Server information
<#94A3B8>Time<#475569>: <#E2E8F0>