> ## Documentation Index
> Fetch the complete documentation index at: https://simplecloud.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Groups API

> Create, query, update, and delete server groups

A group describes a set of servers that share the same software, resources, and scaling behavior. Use `api.group()` to manage groups or request another server for a group.

## Create a group

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.

<Accordion title="CreateGroupRequest fields">
  <ParamField body="name" type="string" required>
    Group name. Up to 100 characters of ASCII letters, digits, underscores, and hyphens (`[A-Za-z0-9_-]`). Must be unique within the network, case-insensitive — `Lobby` and `lobby` are treated as the same name. A group and a persistent server may share a name. Creating or renaming to a name that only differs by case from an existing group returns `409 Conflict`.
  </ParamField>

  <ParamField body="type" type="GroupServerType">
    `SERVER` for game servers or `PROXY` for proxies. Defaults to `SERVER`.
  </ParamField>

  <ParamField body="minMemory" type="integer | null">
    Minimum memory in MB.
  </ParamField>

  <ParamField body="maxMemory" type="integer | null">
    Maximum memory in MB.
  </ParamField>

  <ParamField body="maxPlayers" type="integer">
    Player limit per server. Defaults to `50`.
  </ParamField>

  <ParamField body="active" type="boolean">
    Whether the group may create servers. Defaults to `true`.
  </ParamField>

  <ParamField body="priority" type="integer | null">
    Group priority.
  </ParamField>

  <ParamField body="deployment" type="DeploymentConfig | null">
    Host selection settings.
  </ParamField>

  <ParamField body="scaling" type="ScalingConfig | null">
    Minimum and maximum servers and scaling behavior.
  </ParamField>

  <ParamField body="source" type="SourceConfig | null">
    Existing blueprint or container image used by the group.
  </ParamField>

  <ParamField body="createBlueprint" type="CreateBlueprintRequest | null">
    Blueprint to create with the group.
  </ParamField>

  <ParamField body="workflows" type="WorkflowsConfig | null">
    Lifecycle and manual workflows.
  </ParamField>

  <ParamField body="properties" type="Map<String, Object> | null">
    Custom group properties.
  </ParamField>

  <ParamField body="tags" type="List<String> | null">
    Tags used to organize and filter groups.
  </ParamField>
</Accordion>

## 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<String, Object> 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.

<Accordion title="Start queue fields">
  `GroupStartQueue` contains totals across every group and a list of `GroupStartQueueEntry` objects.

  <ResponseField name="count" type="integer" required>
    Number of group entries.
  </ResponseField>

  <ResponseField name="queuedStarts" type="integer" required>
    Number of pending starts.
  </ResponseField>

  <ResponseField name="failedStarts" type="integer" required>
    Number of failed starts.
  </ResponseField>

  <ResponseField name="totalStarts" type="integer" required>
    Total number of start requests.
  </ResponseField>

  <ResponseField name="items" type="List<GroupStartQueueEntry>" required>
    Queue entries grouped by server group.
  </ResponseField>

  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`.
</Accordion>

## Delete a group

```java theme={null}
api.group().deleteGroup("group-uuid");
```

<Warning>
  Deactivate the group first so it cannot replace stopped instances. Stop its servers, wait for them to stop, then delete the group.
</Warning>

## Group model reference

The following fields are available through `Group` getters.

<ResponseField name="serverGroupId" type="string" required>
  Unique group identifier.
</ResponseField>

<ResponseField name="name" type="string" required>
  Group name.
</ResponseField>

<ResponseField name="type" type="GroupServerType" required>
  `SERVER`, `PROXY`, or `UNKNOWN_SERVER`.
</ResponseField>

<ResponseField name="minMemory" type="integer | null">
  Minimum memory in MB.
</ResponseField>

<ResponseField name="maxMemory" type="integer | null">
  Maximum memory in MB.
</ResponseField>

<ResponseField name="maxPlayers" type="integer | null">
  Player limit per server.
</ResponseField>

<ResponseField name="active" type="boolean | null">
  Whether the group may create servers.
</ResponseField>

<ResponseField name="priority" type="integer | null">
  Group priority.
</ResponseField>

<ResponseField name="deployment" type="DeploymentConfig | null">
  Host selection configuration.
</ResponseField>

<ResponseField name="scaling" type="ScalingConfig | null">
  Scaling configuration.
</ResponseField>

<ResponseField name="source" type="SourceConfig | null">
  Blueprint or container image source.
</ResponseField>

<ResponseField name="workflows" type="WorkflowsConfig | null">
  Lifecycle and manual workflows.
</ResponseField>

<ResponseField name="properties" type="Map<String, Object> | null">
  Custom group properties.
</ResponseField>

<ResponseField name="tags" type="List<String> | null">
  Group tags.
</ResponseField>

<ResponseField name="createdAt" type="string" required>
  Creation timestamp in ISO 8601 format.
</ResponseField>

<ResponseField name="updatedAt" type="string" required>
  Last-update timestamp in ISO 8601 format.
</ResponseField>

<Accordion title="ScalingConfig fields">
  <ResponseField name="minServers" type="integer" required>
    Minimum number of servers to maintain.
  </ResponseField>

  <ResponseField name="maxServers" type="integer" required>
    Maximum number of servers the group may create.
  </ResponseField>

  <ResponseField name="scalingMode" type="ScalingMode | null">
    `SLOTS` maintains free capacity. `PLAYERS` scales from player utilization.
  </ResponseField>

  <ResponseField name="availableSlots" type="integer" required>
    Free player slots to maintain in `SLOTS` mode.
  </ResponseField>

  <ResponseField name="playerThreshold" type="number" required>
    Player utilization threshold between `0` and `1`.
  </ResponseField>

  <ResponseField name="scaleDown" type="ScaleDownConfig | null">
    Scale-down settings.
  </ResponseField>

  <Note>
    Group create and update operations support `SLOTS` and `PLAYERS` scaling modes.
  </Note>
</Accordion>

## 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      |
