PlanyDocs
API reference

PlayputeService

api.plany.cloud:443Regional25 methods

Create and run game servers that cost nothing while nobody is playing. Pick a game and a region and get an address players can connect to; an idle server can go to sleep and is woken in seconds by the next player who connects. Scale a fleet of identical servers with a game server group, capture a set-up server as a schematic so new ones start in seconds, run on spare capacity at a discount with spot, and hand ready servers to matches with AllocateGameServer.

CreateGameServer

Long-running
plany.playpute.v1.PlayputeService/CreateGameServer

Creates a game server and boots it.

Long-running: placement, boot, install and launch take minutes for a modded game. The operation completes when the server is accepting players.

Parameters

  • parentstringRequired
  • game_serverGameServerRequired
    Show child attributes
    • gamestringRequired

      The game to run. Must be launchable — a branch node has no build.

    • namestringIdentifier

      projects/{project}/locations/{location}/gameServers/{game_server}.

      Project- and region-scoped, like every resource that consumes capacity: it runs somewhere specific, and it is billed to the project that owns it.

    • display_namestring
    • settingsmap<string, string>

      Overrides for the game's declared settings, by key.

    • machine_typestring

      The size to run at, by machine type id — standard-4, highmem-2.

      Empty takes the smallest type that meets the game's own declared minimum, and a type below that minimum is refused, because a server too small for its game boots, installs, and is killed for memory at the first player. ListMachineTypes is the catalogue. Changing it takes effect on the next start.

    • Run on spare capacity at a discount, and accept being reclaimed with two minutes' notice. Pro plan only. See SpotConfig.

      Changing it takes effect on the next start.

      Show child attributes
      • enabledbool

        Run on spot capacity.

      • on_demand_fallbackbool

        Start on demand, at the on-demand rate, when no spot capacity is free.

        Without it a start with no spot capacity waits for some and fails after a minute, which is right for a server that is only worth running cheaply and wrong for one players are waiting on. A server that fell back stays on demand until it next stops; SpotStatus.running_on_spot says which it is.

      • notice_signalstring

        A signal to send the game's process when a notice arrives, e.g. SIGUSR1.

        Empty sends nothing, and that is the default for a reason: the default action of most signals is to terminate, so a signal a game does not handle would stop it two minutes early. Name one only when the game handles it. SIGTERM and SIGKILL are refused — the stop that follows the notice sends the game's own stop signal already.

    • labelsmap<string, string>
    • service_accountstring

      The identity this server acts as.

      Leave it empty and Playpute creates one per server, allowed to touch this server and nothing else — the right default, since a server runs your players' mods.

      Set it to a service account you own and the server acts as that instead. That is for a fleet: grant one service account a role elsewhere, attach it to twenty servers, and those twenty can use it while the rest of the account cannot.

      Attaching one requires iam.serviceAccounts.actAs on that service account, not merely permission to create a server — otherwise anybody who could create a server could act as anybody.

    • ssh_public_keysrepeated stringInput only

      SSH keys allowed to log in to this server, for debugging.

      They take effect only on a server booted from an image that includes an SSH server, and are read when the server boots, so a key added later needs a restart. Input only: the keys are not returned when the server is read.

    • imagestringInput only

      The image to boot, by id. Empty uses Plany's current default, which is what almost every server should do.

      An id from Plany's own published images; a server cannot boot an image of your own.

    • ephemeralbool

      Keep nothing. The world and the disks go when the server does.

      The right shape for a match rather than a world: a minigame round has nothing worth carrying into the next one, and an ephemeral server saves the storage and the time of keeping it.

      An ephemeral server never sleeps, because there is nothing to wake into, so sleep_after_idle is refused on one.

      Immutable after creation: the guarantee is about data that was never kept, so it cannot be turned off afterwards.

    • exposureExposure

      Whether players outside the project can reach this server.

      Immutable after creation: it decides whether a listener and a public address exist at all, and flipping it on a running server would change the address players were given.

      EXPOSURE_PUBLICEXPOSURE_PROJECT_INTERNAL
    • schematicstring

      The schematic this server's disk was copied from, if any.

      What makes a scaled fleet viable: the build is already unpacked, the install script has already run and the world already exists, so a member reaches RUNNING in seconds where a cold boot is minutes.

      A copy, not an attachment. The schematic is read once into a fresh disk and never referenced again, which is why deleting one does not disturb a server started from it — and why two members from one schematic diverge immediately rather than sharing anything.

    • Secrets this server can read: database passwords, API keys, RCON passwords, a licence key a game wants in a file.

      Each attachment names a secret in the same project and region and says how the server sees it. The value is never stored on the server's configuration — the server fetches it when it starts, as its own identity — so nothing you can read back from the server reveals it.

      Changing this takes effect on the next start. A running server keeps what it read when it started.

      Show child attributes
      • secretstringRequired

        projects/{project}/locations/{location}/secrets/{secret}, optionally with /versions/{version}.

        Unqualified is the ordinary case and resolves to the latest enabled version, so a rotation reaches this server on its next start with nothing to edit. Pin a version when a server must not follow a rotation — which is rare, and worth being deliberate about, because the pin outlives the memory of why it was made.

      • environment_variablestringRequired

        The environment variable the server sees the secret as, e.g. RCON_PASSWORD.

        Required, and must be a valid variable name — upper case letters, digits and underscores, not starting with a digit. It is not derived from the secret's id, because stripe-live-key is not a variable name.

        The value has to be valid UTF-8 to be used this way. A secret holding binary data is refused when the server starts; use file_path for one.

      • file_pathstring

        Also write the value to a file at this path, relative to the build root.

        For the things that will not go in an environment variable: a service account JSON, a TLS key, a licence file a game reads by path. Optional, and when it is set the environment variable is still exported, because a value that is available two ways is easier to use than one with a rule about when it is which.

        Written 0600 and owned by the game user, and deliberately not preserved across restarts the way a plany.game.v1.ConfigFile can be: this is the platform's copy of a value the platform holds, so the file is rewritten every launch and a rotation cannot leave a stale one behind.

    • sleep_after_idleDuration

      Put the server to sleep after this long with nobody on it.

      Sleep is hibernation: the server's memory is captured, its host released, and the next player's connection — or an allocation — restores it in seconds with everything it held in memory. Compute is not charged while it sleeps.

      The counterpart of idle_shutdown_minutes, and different in the one way that matters: that stops a server a customer forgot about, and this is the platform doing what "pay when played" means for a server somebody wants kept ready. A server the game has marked ALLOCATED or RESERVED never sleeps, because it is somebody's match.

      Idle is measured from the connection proxy's view of the server — no connections and no players — and a server whose presence could not be read is not idle. Refused on an ephemeral server, which cannot hibernate. Zero keeps it awake.

    • vpcstringImmutable

      The private network this server is on. Empty is the project's default network in the server's region.

      Decided by the server, never by its game: a game is a catalogue entry shared by every project that runs it, and a network written there would be one project's network named in everybody's servers. Requires vpc.vpcs.use on the network, which must be in the server's own project and region.

      Immutable. A server that changed network would change address under the players connected to it, and the connection proxy in front of it is the proxy for that network — players reach a server through the proxy on the network it is on, so each network a project uses has a proxy of its own.

    • network_tagsrepeated string

      Network tags on this server's interface, which firewall rules on its network can target. Lowercase letters, digits and hyphens.

  • game_server_idstring
  • request_idstring

Returns

An Operation that resolves to GameServer.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "projects//locations/",
"game_server": {
"display_name": "My server",
"game": "games/my-game"
}
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/CreateGameServer
Example response
{
"name": "projects//locations//gameServers/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"spot_status": {
"running_on_spot": false,
"termination_time": "2026-10-04T12:00:00Z",
"last_reclaim_time": "2026-10-04T12:00:00Z",
"preserving_disk": false,
"notice": "300s"
},
"state": "STATE_PROVISIONING",
"state_message": "",
"error": {},
"endpoints": [
{
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
}
],
"instance": "",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_active_time": "2026-10-04T12:00:00Z",
"service_account": "accounts//serviceAccounts/my-service-account",
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"schematic": "projects//locations//schematics/my-schematic",
"group": "projects//locations//gameServerGroups/",
"draining": false,
"secrets": [
{
"secret": "projects//locations//secrets/",
"environment_variable": "",
"file_path": ""
}
],
"sdk": {
"state": "STATE_READY",
"labels": {
"key": ""
},
"annotations": {
"key": ""
},
"reserved_until": "2026-10-04T12:00:00Z",
"allocate_time": "2026-10-04T12:00:00Z",
"health_time": "2026-10-04T12:00:00Z",
"version": "0",
"update_time": "2026-10-04T12:00:00Z"
},
"sleep_after_idle": "300s",
"managed_by": "",
"install_complete_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\""
}

GetGameServer

Read
plany.playpute.v1.PlayputeService/GetGameServer

Parameters

  • namestringRequired

Returns

GameServer.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//gameServers/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/GetGameServer
Example response
{
"name": "projects//locations//gameServers/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"spot_status": {
"running_on_spot": false,
"termination_time": "2026-10-04T12:00:00Z",
"last_reclaim_time": "2026-10-04T12:00:00Z",
"preserving_disk": false,
"notice": "300s"
},
"state": "STATE_PROVISIONING",
"state_message": "",
"error": {},
"endpoints": [
{
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
}
],
"instance": "",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_active_time": "2026-10-04T12:00:00Z",
"service_account": "accounts//serviceAccounts/my-service-account",
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"schematic": "projects//locations//schematics/my-schematic",
"group": "projects//locations//gameServerGroups/",
"draining": false,
"secrets": [
{
"secret": "projects//locations//secrets/",
"environment_variable": "",
"file_path": ""
}
],
"sdk": {
"state": "STATE_READY",
"labels": {
"key": ""
},
"annotations": {
"key": ""
},
"reserved_until": "2026-10-04T12:00:00Z",
"allocate_time": "2026-10-04T12:00:00Z",
"health_time": "2026-10-04T12:00:00Z",
"version": "0",
"update_time": "2026-10-04T12:00:00Z"
},
"sleep_after_idle": "300s",
"managed_by": "",
"install_complete_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\""
}

ListGameServers

Read
plany.playpute.v1.PlayputeService/ListGameServers

Parameters

  • parentstringRequired
  • page_sizeint32
  • page_tokenstring
  • filterstring

Returns

ListGameServersResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "projects//locations/",
"page_size": 50
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/ListGameServers
Example response
{
"game_servers": [
{
"name": "projects//locations//gameServers/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"spot_status": {
"running_on_spot": false,
"termination_time": "2026-10-04T12:00:00Z",
"last_reclaim_time": "2026-10-04T12:00:00Z",
"preserving_disk": false,
"notice": "300s"
},
"state": "STATE_PROVISIONING",
"state_message": "",
"error": {},
"endpoints": [
{
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
}
],
"instance": "",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_active_time": "2026-10-04T12:00:00Z",
"service_account": "accounts//serviceAccounts/my-service-account",
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"schematic": "projects//locations//schematics/my-schematic",
"group": "projects//locations//gameServerGroups/",
"draining": false,
"secrets": [
{
"secret": "projects//locations//secrets/",
"environment_variable": "",
"file_path": ""
}
],
"sdk": {
"state": "STATE_READY",
"labels": {
"key": ""
},
"annotations": {
"key": ""
},
"reserved_until": "2026-10-04T12:00:00Z",
"allocate_time": "2026-10-04T12:00:00Z",
"health_time": "2026-10-04T12:00:00Z",
"version": "0",
"update_time": "2026-10-04T12:00:00Z"
},
"sleep_after_idle": "300s",
"managed_by": "",
"install_complete_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\""
}
],
"next_page_token": ""
}

UpdateGameServer

Long-running
plany.playpute.v1.PlayputeService/UpdateGameServer

Parameters

  • game_serverGameServerRequired
    Show child attributes
    • gamestringRequired

      The game to run. Must be launchable — a branch node has no build.

    • namestringIdentifier

      projects/{project}/locations/{location}/gameServers/{game_server}.

      Project- and region-scoped, like every resource that consumes capacity: it runs somewhere specific, and it is billed to the project that owns it.

    • display_namestring
    • settingsmap<string, string>

      Overrides for the game's declared settings, by key.

    • machine_typestring

      The size to run at, by machine type id — standard-4, highmem-2.

      Empty takes the smallest type that meets the game's own declared minimum, and a type below that minimum is refused, because a server too small for its game boots, installs, and is killed for memory at the first player. ListMachineTypes is the catalogue. Changing it takes effect on the next start.

    • Run on spare capacity at a discount, and accept being reclaimed with two minutes' notice. Pro plan only. See SpotConfig.

      Changing it takes effect on the next start.

      Show child attributes
      • enabledbool

        Run on spot capacity.

      • on_demand_fallbackbool

        Start on demand, at the on-demand rate, when no spot capacity is free.

        Without it a start with no spot capacity waits for some and fails after a minute, which is right for a server that is only worth running cheaply and wrong for one players are waiting on. A server that fell back stays on demand until it next stops; SpotStatus.running_on_spot says which it is.

      • notice_signalstring

        A signal to send the game's process when a notice arrives, e.g. SIGUSR1.

        Empty sends nothing, and that is the default for a reason: the default action of most signals is to terminate, so a signal a game does not handle would stop it two minutes early. Name one only when the game handles it. SIGTERM and SIGKILL are refused — the stop that follows the notice sends the game's own stop signal already.

    • labelsmap<string, string>
    • service_accountstring

      The identity this server acts as.

      Leave it empty and Playpute creates one per server, allowed to touch this server and nothing else — the right default, since a server runs your players' mods.

      Set it to a service account you own and the server acts as that instead. That is for a fleet: grant one service account a role elsewhere, attach it to twenty servers, and those twenty can use it while the rest of the account cannot.

      Attaching one requires iam.serviceAccounts.actAs on that service account, not merely permission to create a server — otherwise anybody who could create a server could act as anybody.

    • ssh_public_keysrepeated stringInput only

      SSH keys allowed to log in to this server, for debugging.

      They take effect only on a server booted from an image that includes an SSH server, and are read when the server boots, so a key added later needs a restart. Input only: the keys are not returned when the server is read.

    • imagestringInput only

      The image to boot, by id. Empty uses Plany's current default, which is what almost every server should do.

      An id from Plany's own published images; a server cannot boot an image of your own.

    • ephemeralbool

      Keep nothing. The world and the disks go when the server does.

      The right shape for a match rather than a world: a minigame round has nothing worth carrying into the next one, and an ephemeral server saves the storage and the time of keeping it.

      An ephemeral server never sleeps, because there is nothing to wake into, so sleep_after_idle is refused on one.

      Immutable after creation: the guarantee is about data that was never kept, so it cannot be turned off afterwards.

    • exposureExposure

      Whether players outside the project can reach this server.

      Immutable after creation: it decides whether a listener and a public address exist at all, and flipping it on a running server would change the address players were given.

      EXPOSURE_PUBLICEXPOSURE_PROJECT_INTERNAL
    • schematicstring

      The schematic this server's disk was copied from, if any.

      What makes a scaled fleet viable: the build is already unpacked, the install script has already run and the world already exists, so a member reaches RUNNING in seconds where a cold boot is minutes.

      A copy, not an attachment. The schematic is read once into a fresh disk and never referenced again, which is why deleting one does not disturb a server started from it — and why two members from one schematic diverge immediately rather than sharing anything.

    • Secrets this server can read: database passwords, API keys, RCON passwords, a licence key a game wants in a file.

      Each attachment names a secret in the same project and region and says how the server sees it. The value is never stored on the server's configuration — the server fetches it when it starts, as its own identity — so nothing you can read back from the server reveals it.

      Changing this takes effect on the next start. A running server keeps what it read when it started.

      Show child attributes
      • secretstringRequired

        projects/{project}/locations/{location}/secrets/{secret}, optionally with /versions/{version}.

        Unqualified is the ordinary case and resolves to the latest enabled version, so a rotation reaches this server on its next start with nothing to edit. Pin a version when a server must not follow a rotation — which is rare, and worth being deliberate about, because the pin outlives the memory of why it was made.

      • environment_variablestringRequired

        The environment variable the server sees the secret as, e.g. RCON_PASSWORD.

        Required, and must be a valid variable name — upper case letters, digits and underscores, not starting with a digit. It is not derived from the secret's id, because stripe-live-key is not a variable name.

        The value has to be valid UTF-8 to be used this way. A secret holding binary data is refused when the server starts; use file_path for one.

      • file_pathstring

        Also write the value to a file at this path, relative to the build root.

        For the things that will not go in an environment variable: a service account JSON, a TLS key, a licence file a game reads by path. Optional, and when it is set the environment variable is still exported, because a value that is available two ways is easier to use than one with a rule about when it is which.

        Written 0600 and owned by the game user, and deliberately not preserved across restarts the way a plany.game.v1.ConfigFile can be: this is the platform's copy of a value the platform holds, so the file is rewritten every launch and a rotation cannot leave a stale one behind.

    • sleep_after_idleDuration

      Put the server to sleep after this long with nobody on it.

      Sleep is hibernation: the server's memory is captured, its host released, and the next player's connection — or an allocation — restores it in seconds with everything it held in memory. Compute is not charged while it sleeps.

      The counterpart of idle_shutdown_minutes, and different in the one way that matters: that stops a server a customer forgot about, and this is the platform doing what "pay when played" means for a server somebody wants kept ready. A server the game has marked ALLOCATED or RESERVED never sleeps, because it is somebody's match.

      Idle is measured from the connection proxy's view of the server — no connections and no players — and a server whose presence could not be read is not idle. Refused on an ephemeral server, which cannot hibernate. Zero keeps it awake.

    • vpcstringImmutable

      The private network this server is on. Empty is the project's default network in the server's region.

      Decided by the server, never by its game: a game is a catalogue entry shared by every project that runs it, and a network written there would be one project's network named in everybody's servers. Requires vpc.vpcs.use on the network, which must be in the server's own project and region.

      Immutable. A server that changed network would change address under the players connected to it, and the connection proxy in front of it is the proxy for that network — players reach a server through the proxy on the network it is on, so each network a project uses has a proxy of its own.

    • network_tagsrepeated string

      Network tags on this server's interface, which firewall rules on its network can target. Lowercase letters, digits and hyphens.

  • update_maskFieldMaskRequired
  • request_idstring

Returns

An Operation that resolves to GameServer.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"game_server": {
"display_name": "My server",
"game": "games/my-game"
},
"update_mask": "display_name"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/UpdateGameServer
Example response
{
"name": "projects//locations//gameServers/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"spot_status": {
"running_on_spot": false,
"termination_time": "2026-10-04T12:00:00Z",
"last_reclaim_time": "2026-10-04T12:00:00Z",
"preserving_disk": false,
"notice": "300s"
},
"state": "STATE_PROVISIONING",
"state_message": "",
"error": {},
"endpoints": [
{
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
}
],
"instance": "",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_active_time": "2026-10-04T12:00:00Z",
"service_account": "accounts//serviceAccounts/my-service-account",
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"schematic": "projects//locations//schematics/my-schematic",
"group": "projects//locations//gameServerGroups/",
"draining": false,
"secrets": [
{
"secret": "projects//locations//secrets/",
"environment_variable": "",
"file_path": ""
}
],
"sdk": {
"state": "STATE_READY",
"labels": {
"key": ""
},
"annotations": {
"key": ""
},
"reserved_until": "2026-10-04T12:00:00Z",
"allocate_time": "2026-10-04T12:00:00Z",
"health_time": "2026-10-04T12:00:00Z",
"version": "0",
"update_time": "2026-10-04T12:00:00Z"
},
"sleep_after_idle": "300s",
"managed_by": "",
"install_complete_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\""
}

DeleteGameServer

Long-running
plany.playpute.v1.PlayputeService/DeleteGameServer

Parameters

  • namestringRequired
  • etagstring
  • request_idstring

Returns

An Operation that resolves to Empty.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//gameServers/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/DeleteGameServer
Example response
{}

StartGameServer

Long-running
plany.playpute.v1.PlayputeService/StartGameServer

Parameters

  • namestringRequired
  • request_idstring

Returns

An Operation that resolves to GameServer.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//gameServers/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/StartGameServer
Example response
{
"name": "projects//locations//gameServers/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"spot_status": {
"running_on_spot": false,
"termination_time": "2026-10-04T12:00:00Z",
"last_reclaim_time": "2026-10-04T12:00:00Z",
"preserving_disk": false,
"notice": "300s"
},
"state": "STATE_PROVISIONING",
"state_message": "",
"error": {},
"endpoints": [
{
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
}
],
"instance": "",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_active_time": "2026-10-04T12:00:00Z",
"service_account": "accounts//serviceAccounts/my-service-account",
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"schematic": "projects//locations//schematics/my-schematic",
"group": "projects//locations//gameServerGroups/",
"draining": false,
"secrets": [
{
"secret": "projects//locations//secrets/",
"environment_variable": "",
"file_path": ""
}
],
"sdk": {
"state": "STATE_READY",
"labels": {
"key": ""
},
"annotations": {
"key": ""
},
"reserved_until": "2026-10-04T12:00:00Z",
"allocate_time": "2026-10-04T12:00:00Z",
"health_time": "2026-10-04T12:00:00Z",
"version": "0",
"update_time": "2026-10-04T12:00:00Z"
},
"sleep_after_idle": "300s",
"managed_by": "",
"install_complete_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\""
}

StopGameServer

Long-running
plany.playpute.v1.PlayputeService/StopGameServer

Stops a server, keeping its world.

Parameters

  • namestringRequired
  • forcebool

    Skip the clean shutdown. Game servers write world state on exit, so this risks losing player progress — it exists for a server that has hung.

  • request_idstring

Returns

An Operation that resolves to GameServer.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//gameServers/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/StopGameServer
Example response
{
"name": "projects//locations//gameServers/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"spot_status": {
"running_on_spot": false,
"termination_time": "2026-10-04T12:00:00Z",
"last_reclaim_time": "2026-10-04T12:00:00Z",
"preserving_disk": false,
"notice": "300s"
},
"state": "STATE_PROVISIONING",
"state_message": "",
"error": {},
"endpoints": [
{
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
}
],
"instance": "",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_active_time": "2026-10-04T12:00:00Z",
"service_account": "accounts//serviceAccounts/my-service-account",
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"schematic": "projects//locations//schematics/my-schematic",
"group": "projects//locations//gameServerGroups/",
"draining": false,
"secrets": [
{
"secret": "projects//locations//secrets/",
"environment_variable": "",
"file_path": ""
}
],
"sdk": {
"state": "STATE_READY",
"labels": {
"key": ""
},
"annotations": {
"key": ""
},
"reserved_until": "2026-10-04T12:00:00Z",
"allocate_time": "2026-10-04T12:00:00Z",
"health_time": "2026-10-04T12:00:00Z",
"version": "0",
"update_time": "2026-10-04T12:00:00Z"
},
"sleep_after_idle": "300s",
"managed_by": "",
"install_complete_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\""
}

RestartGameServer

Long-running
plany.playpute.v1.PlayputeService/RestartGameServer

Parameters

  • namestringRequired
  • request_idstring

Returns

An Operation that resolves to GameServer.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//gameServers/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/RestartGameServer
Example response
{
"name": "projects//locations//gameServers/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"spot_status": {
"running_on_spot": false,
"termination_time": "2026-10-04T12:00:00Z",
"last_reclaim_time": "2026-10-04T12:00:00Z",
"preserving_disk": false,
"notice": "300s"
},
"state": "STATE_PROVISIONING",
"state_message": "",
"error": {},
"endpoints": [
{
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
}
],
"instance": "",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_active_time": "2026-10-04T12:00:00Z",
"service_account": "accounts//serviceAccounts/my-service-account",
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"schematic": "projects//locations//schematics/my-schematic",
"group": "projects//locations//gameServerGroups/",
"draining": false,
"secrets": [
{
"secret": "projects//locations//secrets/",
"environment_variable": "",
"file_path": ""
}
],
"sdk": {
"state": "STATE_READY",
"labels": {
"key": ""
},
"annotations": {
"key": ""
},
"reserved_until": "2026-10-04T12:00:00Z",
"allocate_time": "2026-10-04T12:00:00Z",
"health_time": "2026-10-04T12:00:00Z",
"version": "0",
"update_time": "2026-10-04T12:00:00Z"
},
"sleep_after_idle": "300s",
"managed_by": "",
"install_complete_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\""
}

ListMachineTypes

Read
plany.playpute.v1.PlayputeService/ListMachineTypes

Lists the sizes a game server can run at, each with this region's spot record beside it.

Parameters

  • parentstringRequired

    projects/{project}/locations/{location}.

Returns

ListMachineTypesResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "projects//locations/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/ListMachineTypes
Example response
{
"machine_types": [
{
"name": "projects//locations//machineTypes/my-machine-type",
"display_name": "My server",
"family": "",
"vcpus": 0,
"memory_bytes": "0",
"spot": {
"available_now": false,
"availability_7d": 0,
"reclaims_per_day_7d": 0,
"sample_time": "2026-10-04T12:00:00Z"
}
}
]
}

GetMachineType

Read
plany.playpute.v1.PlayputeService/GetMachineType

Parameters

  • namestringRequired

Returns

MachineType.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//machineTypes/my-machine-type"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/GetMachineType
Example response
{
"name": "projects//locations//machineTypes/my-machine-type",
"display_name": "My server",
"family": "",
"vcpus": 0,
"memory_bytes": "0",
"spot": {
"available_now": false,
"availability_7d": 0,
"reclaims_per_day_7d": 0,
"sample_time": "2026-10-04T12:00:00Z"
}
}

QuerySpotHistory

Read
plany.playpute.v1.PlayputeService/QuerySpotHistory

Reads a machine type's spot record over an interval: how often a spot server of that type could have been placed, and how often one was reclaimed.

Hourly buckets over at most thirty days, which is also how long the record is kept. A bucket with no samples says so rather than reading as zero.

Parameters

  • machine_typestringRequired
  • intervalInterval

    The interval to read. Unset reads the last seven days; an interval reaching further back than thirty days is refused, because nothing older is kept and an answer padded with empty buckets would look like a record.

Returns

QuerySpotHistoryResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"machine_type": "projects//locations//machineTypes/my-machine-type"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/QuerySpotHistory
Example response
{
"points": [
{
"interval": {
"start_time": "2026-10-01T00:00:00Z",
"end_time": "2026-10-04T00:00:00Z"
},
"availability": 0,
"reclaims": "0",
"running_hours": 0,
"measured": false
}
]
}

CreateGameServerSchematic

Long-running
plany.playpute.v1.PlayputeService/CreateGameServerSchematic

Captures a running game server as a fast-start template.

Long-running: copying a server's disk takes minutes for one with an installed world. The server keeps running throughout — capturing a world you have already set up is the ordinary case.

Parameters

  • parentstringRequired

    projects/{project}/locations/{location}.

  • game_serverstringRequired

    The running server to capture. Must be in this parent.

  • schematic_idstring
  • display_namestring
  • labelsmap<string, string>
  • request_idstring

Returns

An Operation that resolves to GameServerSchematic.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "",
"game_server": "projects//locations//gameServers/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/CreateGameServerSchematic
Example response
{
"name": "projects//locations//schematics/my-schematic",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"source_game_server": "",
"state": "STATE_PENDING",
"error": {},
"size_bytes": "0",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"ready_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

GetGameServerSchematic

Read
plany.playpute.v1.PlayputeService/GetGameServerSchematic

Parameters

  • namestringRequired

Returns

GameServerSchematic.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//schematics/my-schematic"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/GetGameServerSchematic
Example response
{
"name": "projects//locations//schematics/my-schematic",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"source_game_server": "",
"state": "STATE_PENDING",
"error": {},
"size_bytes": "0",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"ready_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

ListGameServerSchematics

Read
plany.playpute.v1.PlayputeService/ListGameServerSchematics

Parameters

  • parentstringRequired

    projects/{project}/locations/{location}.

  • page_sizeint32
  • page_tokenstring

Returns

ListGameServerSchematicsResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "",
"page_size": 50
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/ListGameServerSchematics
Example response
{
"schematics": [
{
"name": "projects//locations//schematics/my-schematic",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"source_game_server": "",
"state": "STATE_PENDING",
"error": {},
"size_bytes": "0",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"ready_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}
],
"next_page_token": ""
}

DeleteGameServerSchematic

plany.playpute.v1.PlayputeService/DeleteGameServerSchematic

Deletes a schematic and the disk behind it.

Servers already started from it are unaffected. A schematic is copied into a fresh disk at boot rather than attached, so a running server holds no reference to it — which is the difference between this and deleting a volume, and why there is no in-use guard.

Parameters

  • namestringRequired

Returns

Empty.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//schematics/my-schematic"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/DeleteGameServerSchematic
Example response
{}

CreateGameServerGroup

Long-running
plany.playpute.v1.PlayputeService/CreateGameServerGroup

Creates a group and, unless warmup_duration is zero or a schematic was supplied, the warm-up server it captures its schematic from.

Long-running because the warm-up is: a server is created, left to install and generate its world for the declared duration, captured, and deleted. The warm-up server is not billed — it exists so the customer's members do not each pay for that install, and charging for it would be charging for the platform's own optimisation.

The operation completes when the group is ACTIVE and scaling. Members are created by the group's own loop and not by this call, so an operation that has completed does not mean a server is running — min_size decides that.

Parameters

  • parentstringRequired

    projects/{project}/locations/{location}.

  • game_server_groupGameServerGroupRequired
    Show child attributes
    • gamestringRequired

      The game every member runs.

    • policyScalingPolicyRequired
      Show child attributes
      • max_sizeint32Required
      • min_sizeint32

        Members never to go below, and never to go above.

        A minimum of zero is legitimate and is what a group for an off-peak game wants: no players, no servers, no bill. The first player then pays a boot, which is what the schematic is for.

      • target_player_percentdouble

        Hold members at this fraction of their player capacity. 1..100.

        The headline signal for a minigame: "keep servers 70% full" is the sentence a customer says. Needs the game to declare how many players a server holds; without that this term sits out rather than guessing.

      • min_free_player_slotsint32

        Keep at least this many player slots free across the whole group, so a party arriving together finds room without waiting for a boot.

        Additive to the percentage rather than an alternative — they answer different questions, and a group that sets both gets whichever needs more.

      • scale_on_waiting_connectionsbool

        Add members when connections are open against servers nobody is playing on.

        The only leading signal available: every other term here reacts to load that has already landed, and this one is somebody who could not get in. It needs no capacity and no sample, so it works for a game the platform knows nothing about.

      • target_cpu_percentdouble

        Hold the group's mean CPU at this percentage of each member's allocation. 1..100.

      • scale_out_cooldownDuration

        How long after growing before the group may grow again.

        A member takes tens of seconds to accept its first player, and every pass inside that window sees the same load on the same members. Without this a group creates one member per pass until the first finishes booting.

      • scale_in_patienceDuration

        How long a member must have been empty before it may be removed.

        Longer than the cooldown by default and by intent. Scaling in on a momentary zero is the failure that matters here: presence is derived from the game's own log lines, which can be late or missed, so a server between two rounds reads as empty for a few seconds. Growing late is a queue; shrinking early is a disconnection, and only the first is fixed by waiting.

      • max_scale_out_batchint32

        Most members to add or remove in one pass.

      • max_scale_in_batchint32
      • drain_timeoutDuration

        How long a drained member is given to empty before it is removed anyway.

        A drain is not a disconnection: the member stops being sent new players and keeps the ones it has. Somebody who never leaves would otherwise hold a member forever, so there is a deadline — long enough that a match finishes inside it.

      • buffer_sizeint32

        Keep this many members READY and unallocated, on top of those allocated.

        Agones' FleetAutoscaler buffer, and the shape a lobby needs: "always two servers accepting players, however many are mid-match". Reads the SDK state the game reports, so it needs a game that calls Ready() and Allocate() — for one that does not, every member is unallocated and the term asks only for the buffer itself.

        A sleeping READY member counts: it can be allocated. That is what makes a buffer cheap while nobody plays.

        Combined with the other terms by maximum, like all of them, and bounded by min_size and max_size.

      • buffer_percentdouble

        The buffer as a percentage of the group's size. 1..100. The larger of this and buffer_size when both are set.

    • namestringIdentifier

      projects/{p}/locations/{l}/gameServerGroups/{g}.

    • display_namestring
    • buildstring

      The build every member runs.

      Pinned like a game server's, and for a stronger reason: members are created and destroyed continuously, so a group that resolved the game's current build per member would put two versions of a customer's game in one fleet, with players matched across them by accident.

      Updatable, and changing it is a rollout, never a mixture by accident. The group goes on creating members on the old build while a warm-up bakes the new one (pending_build), switches when the capture lands, and then replaces outdated members within rollout — never one the game has marked ALLOCATED, which is somebody's match and finishes on the build it started on.

    • settingsmap<string, string>

      Settings handed to every member, exactly as GameServer.settings.

    • machine_typestring

      The machine type every member runs at, as GameServer.machine_type. Empty takes the smallest type that meets the game's minimum.

      Updatable, and a change reaches a member the next time it starts; it is not a rollout, because a size is not what a match is played on.

    • Run members on spot capacity, as GameServer.spot. Pro plan only.

      A fleet is where spot is most useful — a minigame server reclaimed between rounds costs nobody anything — and it composes with scaling in one way worth knowing: a reclaimed member counts as not running, so a group that needs it creates or starts another. With on_demand_fallback that one is on demand when spot has nothing free, which is what keeps a fleet at size while the region is busy.

      Show child attributes
      • enabledbool

        Run on spot capacity.

      • on_demand_fallbackbool

        Start on demand, at the on-demand rate, when no spot capacity is free.

        Without it a start with no spot capacity waits for some and fails after a minute, which is right for a server that is only worth running cheaply and wrong for one players are waiting on. A server that fell back stays on demand until it next stops; SpotStatus.running_on_spot says which it is.

      • notice_signalstring

        A signal to send the game's process when a notice arrives, e.g. SIGUSR1.

        Empty sends nothing, and that is the default for a reason: the default action of most signals is to terminate, so a signal a game does not handle would stop it two minutes early. Name one only when the game handles it. SIGTERM and SIGKILL are refused — the stop that follows the notice sends the game's own stop signal already.

    • ephemeralbool

      Whether members keep their data.

      Almost always true for the workload a group is for: a match has nothing worth carrying into the next one, and a member that hibernated would write its whole RAM to object storage on the way out of a world nobody will read.

      It also changes what scaling in means. An ephemeral member is deleted when it is drained; a durable one is stopped, keeps its disks, and is started again when the group grows.

    • exposureExposure

      Whether players can reach members directly.

      PROJECT_INTERNAL is the right default for a scaled fleet and the reason the field exists: members behind a matchmaker or a lobby are dialled from inside the project, and giving each one a public listener would be an entry point nobody intended and a proxy charge per member. The choice is the customer's, because a fleet of servers players do pick from a list is just as real a shape.

      EXPOSURE_PUBLICEXPOSURE_PROJECT_INTERNAL
    • warmup_durationDuration

      How long a warm-up server runs before it is captured as the schematic.

      The one number that decides how fast this group scales. A member started from a schematic skips the download, the install and the world generation — seconds instead of minutes — and what makes the schematic worth having is that the capture happened after all of that finished.

      So this is "how long does your game take to be ready to play", and getting it wrong is visible in one direction only: too long wastes a few minutes once, and too short captures a server mid-install, which every member then starts from.

      Zero skips the warm-up entirely and members boot cold. That is the right choice for a game that starts in seconds anyway, and the only choice for one whose first run must not be cloned.

    • schematicstring

      The schematic members are started from.

      Set by the group when its warm-up capture lands, or supplied at creation to reuse one that already exists — which is the faster path and the one a customer takes for their second group of the same game.

      Empty means members boot cold, which is correct rather than broken: a group whose capture failed still scales, just slowly, and stopping it from scaling would turn a performance problem into an outage.

    • labelsmap<string, string>
    • vpcstringImmutable

      The private network every member is on, and the warm-up server before them. Empty is the project's default network in the group's region.

      On the group rather than on each member because a member is the group's to create: two members on different networks would be one fleet that cannot reach itself. Requires vpc.vpcs.use on the network. Immutable, for the reason GameServer.vpc is.

    • network_tagsrepeated string

      Network tags on every member's interface, and the warm-up's, which firewall rules on the group's network can target. Lowercase letters, digits and hyphens.

    • How members are replaced when build changes.

      Show child attributes
      • STRATEGY_ROLLING_UPDATESTRATEGY_RECREATE
      • max_surgeint32

        Members above the desired size a rolling update may create, as a count or as a percentage of the desired size. The larger of the two when both are set; 25% when neither is.

      • max_surge_percentint32
      • max_unavailableint32

        Members below the desired size a rolling update may leave the group at, as a count or a percentage. 25% when neither is set.

      • max_unavailable_percentint32
    • sleep_after_idleDuration

      Put members to sleep after this long with nobody on them. See GameServer.sleep_after_idle, which every member is created with.

      A sleeping member still counts toward the group's size and, if the game said it is READY, toward its buffer: it can be allocated or connected to, and either wakes it. That is the point of keeping it rather than removing it. Refused on an ephemeral group, whose members cannot hibernate.

    • member_labelsmap<string, string>

      Labels every member carries, and what an allocation selects on.

      Not labels, which describe the group itself. Changing these reaches members created afterwards; existing members keep what they were created with, as a pod keeps its labels when a template changes.

  • game_server_group_idstring
  • request_idstring

Returns

An Operation that resolves to GameServerGroup.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "projects//locations/",
"game_server_group": {
"display_name": "My server",
"game": "games/my-game",
"policy": {
"max_size": 0
}
}
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/CreateGameServerGroup
Example response
{
"name": "projects//locations//gameServerGroups/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"policy": {
"min_size": 0,
"max_size": 0,
"target_player_percent": 0,
"min_free_player_slots": 0,
"scale_on_waiting_connections": false,
"target_cpu_percent": 0,
"scale_out_cooldown": "300s",
"scale_in_patience": "300s",
"max_scale_out_batch": 0,
"max_scale_in_batch": 0,
"drain_timeout": "300s",
"buffer_size": 0,
"buffer_percent": 0
},
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"warmup_duration": "300s",
"schematic": "projects//locations//schematics/my-schematic",
"state": "STATE_WARMING_UP",
"state_message": "",
"error": {},
"current_size": 0,
"desired_size": 0,
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_scale_out_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\"",
"managed_by": "",
"pending_build": "builds/my-build",
"rollout": {
"strategy": "STRATEGY_ROLLING_UPDATE",
"max_surge": 0,
"max_surge_percent": 0,
"max_unavailable": 0,
"max_unavailable_percent": 0
},
"sleep_after_idle": "300s",
"member_labels": {
"key": ""
},
"outdated_size": 0,
"ready_size": 0,
"allocated_size": 0,
"sleeping_size": 0,
"pending_game": "games/my-game"
}

GetGameServerGroup

Read
plany.playpute.v1.PlayputeService/GetGameServerGroup

Parameters

  • namestringRequired

Returns

GameServerGroup.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//gameServerGroups/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/GetGameServerGroup
Example response
{
"name": "projects//locations//gameServerGroups/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"policy": {
"min_size": 0,
"max_size": 0,
"target_player_percent": 0,
"min_free_player_slots": 0,
"scale_on_waiting_connections": false,
"target_cpu_percent": 0,
"scale_out_cooldown": "300s",
"scale_in_patience": "300s",
"max_scale_out_batch": 0,
"max_scale_in_batch": 0,
"drain_timeout": "300s",
"buffer_size": 0,
"buffer_percent": 0
},
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"warmup_duration": "300s",
"schematic": "projects//locations//schematics/my-schematic",
"state": "STATE_WARMING_UP",
"state_message": "",
"error": {},
"current_size": 0,
"desired_size": 0,
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_scale_out_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\"",
"managed_by": "",
"pending_build": "builds/my-build",
"rollout": {
"strategy": "STRATEGY_ROLLING_UPDATE",
"max_surge": 0,
"max_surge_percent": 0,
"max_unavailable": 0,
"max_unavailable_percent": 0
},
"sleep_after_idle": "300s",
"member_labels": {
"key": ""
},
"outdated_size": 0,
"ready_size": 0,
"allocated_size": 0,
"sleeping_size": 0,
"pending_game": "games/my-game"
}

ListGameServerGroups

Read
plany.playpute.v1.PlayputeService/ListGameServerGroups

Parameters

  • parentstringRequired

    projects/{project}/locations/{location}, or projects/-/locations/{l} for every project's groups in a location — internal callers only, and what the scaling loop itself uses.

  • page_sizeint32
  • page_tokenstring

Returns

ListGameServerGroupsResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "",
"page_size": 50
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/ListGameServerGroups
Example response
{
"game_server_groups": [
{
"name": "projects//locations//gameServerGroups/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"policy": {
"min_size": 0,
"max_size": 0,
"target_player_percent": 0,
"min_free_player_slots": 0,
"scale_on_waiting_connections": false,
"target_cpu_percent": 0,
"scale_out_cooldown": "300s",
"scale_in_patience": "300s",
"max_scale_out_batch": 0,
"max_scale_in_batch": 0,
"drain_timeout": "300s",
"buffer_size": 0,
"buffer_percent": 0
},
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"warmup_duration": "300s",
"schematic": "projects//locations//schematics/my-schematic",
"state": "STATE_WARMING_UP",
"state_message": "",
"error": {},
"current_size": 0,
"desired_size": 0,
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_scale_out_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\"",
"managed_by": "",
"pending_build": "builds/my-build",
"rollout": {
"strategy": "STRATEGY_ROLLING_UPDATE",
"max_surge": 0,
"max_surge_percent": 0,
"max_unavailable": 0,
"max_unavailable_percent": 0
},
"sleep_after_idle": "300s",
"member_labels": {
"key": ""
},
"outdated_size": 0,
"ready_size": 0,
"allocated_size": 0,
"sleeping_size": 0,
"pending_game": "games/my-game"
}
],
"next_page_token": ""
}

UpdateGameServerGroup

plany.playpute.v1.PlayputeService/UpdateGameServerGroup

Updates a group's policy, its build, or pauses and resumes its scaling.

game, ephemeral and exposure decide what a member is, and members already exist, so they are refused. build is the exception and is a rollout rather than an edit — see GameServerGroup.build.

A managed group is refused: change the manifest that created it.

Parameters

  • game_server_groupGameServerGroupRequired
    Show child attributes
    • gamestringRequired

      The game every member runs.

    • policyScalingPolicyRequired
      Show child attributes
      • max_sizeint32Required
      • min_sizeint32

        Members never to go below, and never to go above.

        A minimum of zero is legitimate and is what a group for an off-peak game wants: no players, no servers, no bill. The first player then pays a boot, which is what the schematic is for.

      • target_player_percentdouble

        Hold members at this fraction of their player capacity. 1..100.

        The headline signal for a minigame: "keep servers 70% full" is the sentence a customer says. Needs the game to declare how many players a server holds; without that this term sits out rather than guessing.

      • min_free_player_slotsint32

        Keep at least this many player slots free across the whole group, so a party arriving together finds room without waiting for a boot.

        Additive to the percentage rather than an alternative — they answer different questions, and a group that sets both gets whichever needs more.

      • scale_on_waiting_connectionsbool

        Add members when connections are open against servers nobody is playing on.

        The only leading signal available: every other term here reacts to load that has already landed, and this one is somebody who could not get in. It needs no capacity and no sample, so it works for a game the platform knows nothing about.

      • target_cpu_percentdouble

        Hold the group's mean CPU at this percentage of each member's allocation. 1..100.

      • scale_out_cooldownDuration

        How long after growing before the group may grow again.

        A member takes tens of seconds to accept its first player, and every pass inside that window sees the same load on the same members. Without this a group creates one member per pass until the first finishes booting.

      • scale_in_patienceDuration

        How long a member must have been empty before it may be removed.

        Longer than the cooldown by default and by intent. Scaling in on a momentary zero is the failure that matters here: presence is derived from the game's own log lines, which can be late or missed, so a server between two rounds reads as empty for a few seconds. Growing late is a queue; shrinking early is a disconnection, and only the first is fixed by waiting.

      • max_scale_out_batchint32

        Most members to add or remove in one pass.

      • max_scale_in_batchint32
      • drain_timeoutDuration

        How long a drained member is given to empty before it is removed anyway.

        A drain is not a disconnection: the member stops being sent new players and keeps the ones it has. Somebody who never leaves would otherwise hold a member forever, so there is a deadline — long enough that a match finishes inside it.

      • buffer_sizeint32

        Keep this many members READY and unallocated, on top of those allocated.

        Agones' FleetAutoscaler buffer, and the shape a lobby needs: "always two servers accepting players, however many are mid-match". Reads the SDK state the game reports, so it needs a game that calls Ready() and Allocate() — for one that does not, every member is unallocated and the term asks only for the buffer itself.

        A sleeping READY member counts: it can be allocated. That is what makes a buffer cheap while nobody plays.

        Combined with the other terms by maximum, like all of them, and bounded by min_size and max_size.

      • buffer_percentdouble

        The buffer as a percentage of the group's size. 1..100. The larger of this and buffer_size when both are set.

    • namestringIdentifier

      projects/{p}/locations/{l}/gameServerGroups/{g}.

    • display_namestring
    • buildstring

      The build every member runs.

      Pinned like a game server's, and for a stronger reason: members are created and destroyed continuously, so a group that resolved the game's current build per member would put two versions of a customer's game in one fleet, with players matched across them by accident.

      Updatable, and changing it is a rollout, never a mixture by accident. The group goes on creating members on the old build while a warm-up bakes the new one (pending_build), switches when the capture lands, and then replaces outdated members within rollout — never one the game has marked ALLOCATED, which is somebody's match and finishes on the build it started on.

    • settingsmap<string, string>

      Settings handed to every member, exactly as GameServer.settings.

    • machine_typestring

      The machine type every member runs at, as GameServer.machine_type. Empty takes the smallest type that meets the game's minimum.

      Updatable, and a change reaches a member the next time it starts; it is not a rollout, because a size is not what a match is played on.

    • Run members on spot capacity, as GameServer.spot. Pro plan only.

      A fleet is where spot is most useful — a minigame server reclaimed between rounds costs nobody anything — and it composes with scaling in one way worth knowing: a reclaimed member counts as not running, so a group that needs it creates or starts another. With on_demand_fallback that one is on demand when spot has nothing free, which is what keeps a fleet at size while the region is busy.

      Show child attributes
      • enabledbool

        Run on spot capacity.

      • on_demand_fallbackbool

        Start on demand, at the on-demand rate, when no spot capacity is free.

        Without it a start with no spot capacity waits for some and fails after a minute, which is right for a server that is only worth running cheaply and wrong for one players are waiting on. A server that fell back stays on demand until it next stops; SpotStatus.running_on_spot says which it is.

      • notice_signalstring

        A signal to send the game's process when a notice arrives, e.g. SIGUSR1.

        Empty sends nothing, and that is the default for a reason: the default action of most signals is to terminate, so a signal a game does not handle would stop it two minutes early. Name one only when the game handles it. SIGTERM and SIGKILL are refused — the stop that follows the notice sends the game's own stop signal already.

    • ephemeralbool

      Whether members keep their data.

      Almost always true for the workload a group is for: a match has nothing worth carrying into the next one, and a member that hibernated would write its whole RAM to object storage on the way out of a world nobody will read.

      It also changes what scaling in means. An ephemeral member is deleted when it is drained; a durable one is stopped, keeps its disks, and is started again when the group grows.

    • exposureExposure

      Whether players can reach members directly.

      PROJECT_INTERNAL is the right default for a scaled fleet and the reason the field exists: members behind a matchmaker or a lobby are dialled from inside the project, and giving each one a public listener would be an entry point nobody intended and a proxy charge per member. The choice is the customer's, because a fleet of servers players do pick from a list is just as real a shape.

      EXPOSURE_PUBLICEXPOSURE_PROJECT_INTERNAL
    • warmup_durationDuration

      How long a warm-up server runs before it is captured as the schematic.

      The one number that decides how fast this group scales. A member started from a schematic skips the download, the install and the world generation — seconds instead of minutes — and what makes the schematic worth having is that the capture happened after all of that finished.

      So this is "how long does your game take to be ready to play", and getting it wrong is visible in one direction only: too long wastes a few minutes once, and too short captures a server mid-install, which every member then starts from.

      Zero skips the warm-up entirely and members boot cold. That is the right choice for a game that starts in seconds anyway, and the only choice for one whose first run must not be cloned.

    • schematicstring

      The schematic members are started from.

      Set by the group when its warm-up capture lands, or supplied at creation to reuse one that already exists — which is the faster path and the one a customer takes for their second group of the same game.

      Empty means members boot cold, which is correct rather than broken: a group whose capture failed still scales, just slowly, and stopping it from scaling would turn a performance problem into an outage.

    • labelsmap<string, string>
    • vpcstringImmutable

      The private network every member is on, and the warm-up server before them. Empty is the project's default network in the group's region.

      On the group rather than on each member because a member is the group's to create: two members on different networks would be one fleet that cannot reach itself. Requires vpc.vpcs.use on the network. Immutable, for the reason GameServer.vpc is.

    • network_tagsrepeated string

      Network tags on every member's interface, and the warm-up's, which firewall rules on the group's network can target. Lowercase letters, digits and hyphens.

    • How members are replaced when build changes.

      Show child attributes
      • STRATEGY_ROLLING_UPDATESTRATEGY_RECREATE
      • max_surgeint32

        Members above the desired size a rolling update may create, as a count or as a percentage of the desired size. The larger of the two when both are set; 25% when neither is.

      • max_surge_percentint32
      • max_unavailableint32

        Members below the desired size a rolling update may leave the group at, as a count or a percentage. 25% when neither is set.

      • max_unavailable_percentint32
    • sleep_after_idleDuration

      Put members to sleep after this long with nobody on them. See GameServer.sleep_after_idle, which every member is created with.

      A sleeping member still counts toward the group's size and, if the game said it is READY, toward its buffer: it can be allocated or connected to, and either wakes it. That is the point of keeping it rather than removing it. Refused on an ephemeral group, whose members cannot hibernate.

    • member_labelsmap<string, string>

      Labels every member carries, and what an allocation selects on.

      Not labels, which describe the group itself. Changing these reaches members created afterwards; existing members keep what they were created with, as a pod keeps its labels when a template changes.

  • update_maskFieldMask

Returns

GameServerGroup.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"game_server_group": {
"display_name": "My server",
"game": "games/my-game",
"policy": {
"max_size": 0
}
}
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/UpdateGameServerGroup
Example response
{
"name": "projects//locations//gameServerGroups/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"policy": {
"min_size": 0,
"max_size": 0,
"target_player_percent": 0,
"min_free_player_slots": 0,
"scale_on_waiting_connections": false,
"target_cpu_percent": 0,
"scale_out_cooldown": "300s",
"scale_in_patience": "300s",
"max_scale_out_batch": 0,
"max_scale_in_batch": 0,
"drain_timeout": "300s",
"buffer_size": 0,
"buffer_percent": 0
},
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"warmup_duration": "300s",
"schematic": "projects//locations//schematics/my-schematic",
"state": "STATE_WARMING_UP",
"state_message": "",
"error": {},
"current_size": 0,
"desired_size": 0,
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_scale_out_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\"",
"managed_by": "",
"pending_build": "builds/my-build",
"rollout": {
"strategy": "STRATEGY_ROLLING_UPDATE",
"max_surge": 0,
"max_surge_percent": 0,
"max_unavailable": 0,
"max_unavailable_percent": 0
},
"sleep_after_idle": "300s",
"member_labels": {
"key": ""
},
"outdated_size": 0,
"ready_size": 0,
"allocated_size": 0,
"sleeping_size": 0,
"pending_game": "games/my-game"
}

DeleteGameServerGroup

Long-running
plany.playpute.v1.PlayputeService/DeleteGameServerGroup

Deletes a group and every member it created.

Members go first and they are drained, not killed: a group deleted while people are playing gives them the length of drain_timeout to finish.

Parameters

  • namestringRequired
  • etagstring
  • request_idstring

Returns

An Operation that resolves to Empty.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//gameServerGroups/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/DeleteGameServerGroup
Example response
{}

ListProxyRoutes

Read
plany.playpute.v1.PlayputeService/ListProxyRoutes

Parameters

  • parentstringRequired

    projects/{project}/locations/{location}.

  • page_sizeint32
  • page_tokenstring

Returns

ListProxyRoutesResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "",
"page_size": 50
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/ListProxyRoutes
Example response
{
"proxy_routes": [
{
"name": "projects//locations//gameServers//proxyRoutes/my-proxy-route",
"game_server": "projects//locations//gameServers/",
"game": "games/my-game",
"port_name": "",
"listen_host": "",
"listen_port": 0,
"protocol": "",
"target_port": 0,
"billable": false,
"proxy": "",
"create_time": "2026-10-04T12:00:00Z"
}
],
"next_page_token": ""
}

WakeGameServer

plany.playpute.v1.PlayputeService/WakeGameServer

Reports that somebody is trying to play a server, and returns where to send them.

Called by Plany's connection proxy when a connection arrives for a server. If the server is running, the answer is its address; if it is not, this starts it and the caller asks again. Idempotent: a client that times out and retries, or twenty friends connecting at once, is one start.

You do not normally call this: connecting to the server's proxied address does it for you.

Parameters

  • namestringRequired
  • port_namestringRequired

    The game's port name the connection arrived on, e.g. "game". Determines which endpoint comes back — a game with a query port has two, and sending a player to the wrong one is a connection that establishes and then does nothing.

  • client_addressstring

    The connecting player's address, for logs. Never used to decide anything: it is whatever the proxy saw, and a wake is authorized by the proxy being an internal caller, not by who is connecting.

  • probe_onlybool

    Ask where the server is without starting it.

    A stopped server answers with its state and a retry_after exactly as it would otherwise, and stays stopped. Used so that server browsers and port scanners probing a sleeping server do not wake it; only sustained traffic does.

Returns

WakeGameServerResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//gameServers/",
"port_name": ""
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/WakeGameServer
Example response
{
"state": "STATE_PROVISIONING",
"ready": false,
"upstream": {
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
},
"retry_after": "300s"
}

AllocateGameServer

plany.playpute.v1.PlayputeService/AllocateGameServer

Hands a READY game server to a match.

Picks one server matching the selectors, tried in order, and moves it to ALLOCATED atomically — two allocations can never take the same server. Agones' GameServerAllocation, with a Plany project and region in place of a cluster and namespace.

An awake server is preferred to a sleeping one, and a sleeping one is allocated and woken in the same call. The answer does not wait for the wake: the server's address is reachable while it sleeps, and players' connections are held until it is up.

Nothing matching is RESOURCE_EXHAUSTED, as Agones' allocator answers, so a matchmaker already written for Agones handles it unchanged.

Parameters

  • parentstringRequired

    projects/{project}/locations/{location}.

  • Tried in order; the first that matches a server wins. Empty matches any READY server in the project and region that uses the SDK.

    Show child attributes
    • match_labelsmap<string, string>

      Every one of these must equal a label on the server — its own labels or its SDK labels.

    • match_expressionsrepeated LabelRequirement

      Kubernetes' set-based requirements, all of which must hold.

      Show child attributes
      • keystringRequired
      • OPERATOR_INOPERATOR_NOT_INOPERATOR_EXISTSOPERATOR_DOES_NOT_EXIST
      • valuesrepeated string
    • READY (the default) or ALLOCATED — the second is Agones' re-allocation of a server that is already in use and has room, which is how a lobby is joined.

      STATE_READYSTATE_ALLOCATEDSTATE_RESERVEDSTATE_SHUTDOWNSTATE_UNHEALTHY
  • SCHEDULING_PACKEDSCHEDULING_DISTRIBUTED
  • labelsmap<string, string>

    Written onto the chosen server's SDK labels and annotations, where the game reads them through WatchGameServer — how a matchmaker tells a server which match it is.

  • annotationsmap<string, string>

Returns

AllocateGameServerResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "projects//locations/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/AllocateGameServer
Example response
{
"game_server": {
"name": "projects//locations//gameServers/",
"display_name": "My server",
"game": "games/my-game",
"build": "builds/my-build",
"settings": {
"key": ""
},
"resources": {},
"machine_type": "",
"spot": {
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
},
"spot_status": {
"running_on_spot": false,
"termination_time": "2026-10-04T12:00:00Z",
"last_reclaim_time": "2026-10-04T12:00:00Z",
"preserving_disk": false,
"notice": "300s"
},
"state": "STATE_PROVISIONING",
"state_message": "",
"error": {},
"endpoints": [
{
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
}
],
"instance": "",
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_active_time": "2026-10-04T12:00:00Z",
"service_account": "accounts//serviceAccounts/my-service-account",
"ephemeral": false,
"exposure": "EXPOSURE_PUBLIC",
"schematic": "projects//locations//schematics/my-schematic",
"group": "projects//locations//gameServerGroups/",
"draining": false,
"secrets": [
{
"secret": "projects//locations//secrets/",
"environment_variable": "",
"file_path": ""
}
],
"sdk": {
"state": "STATE_READY",
"labels": {
"key": ""
},
"annotations": {
"key": ""
},
"reserved_until": "2026-10-04T12:00:00Z",
"allocate_time": "2026-10-04T12:00:00Z",
"health_time": "2026-10-04T12:00:00Z",
"version": "0",
"update_time": "2026-10-04T12:00:00Z"
},
"sleep_after_idle": "300s",
"managed_by": "",
"install_complete_time": "2026-10-04T12:00:00Z",
"vpc": "projects//locations//vpcs/",
"network_tags": [
""
],
"etag": "W/\"1\""
},
"endpoints": [
{
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
}
],
"woken": false
}

UpdateGameServerSdk

plany.playpute.v1.PlayputeService/UpdateGameServerSdk

Reports an Agones SDK call made by the game inside a server.

Called from inside the server, as the server's own identity, and only for that server. A game using the Agones SDK does this through the SDK; you do not call it directly.

Parameters

Returns

SdkStatus.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//gameServers/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/UpdateGameServerSdk
Example response
{
"state": "STATE_READY",
"labels": {
"key": ""
},
"annotations": {
"key": ""
},
"reserved_until": "2026-10-04T12:00:00Z",
"allocate_time": "2026-10-04T12:00:00Z",
"health_time": "2026-10-04T12:00:00Z",
"version": "0",
"update_time": "2026-10-04T12:00:00Z"
}

WatchGameServerSdk

Server streaming
plany.playpute.v1.PlayputeService/WatchGameServerSdk

Streams a server's SDK status to the server itself, now and on every change.

How an allocation reaches a game waiting in the Agones SDK's WatchGameServer. A game using the Agones SDK does this through the SDK; you do not call it directly.

Parameters

  • namestringRequired

Returns

SdkStatus, as a stream.

grpcurl
grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//gameServers/"
}' \
api.plany.cloud:443 plany.playpute.v1.PlayputeService/WatchGameServerSdk
Example response
{
"state": "STATE_READY",
"labels": {
"key": ""
},
"annotations": {
"key": ""
},
"reserved_until": "2026-10-04T12:00:00Z",
"allocate_time": "2026-10-04T12:00:00Z",
"health_time": "2026-10-04T12:00:00Z",
"version": "0",
"update_time": "2026-10-04T12:00:00Z"
}

The Endpoint object

Endpoint is an address players connect to.

Attributes

  • namestring

    Matches the game's plany.game.v1.PortMapping name, e.g. "game".

  • hoststring
  • portint32
  • protocolstring

    "tcp" or "udp".

  • addressstring

    Ready-to-paste form, e.g. "play.example.com:25565". Populated because every console and support conversation ends up building this string anyway, and building it in one place avoids three subtly different ones.

  • proxiedbool

    Whether this address is Plany's proxy rather than the server itself.

    A proxied address is reachable while the server is stopped or asleep, and connecting to it starts the server — so it is the one to give to players. A player's first connection after a sleep waits a few seconds while the server comes back.

Endpoint
{
"name": "",
"host": "",
"port": 0,
"protocol": "",
"address": "",
"proxied": false
}

The GameServerSelector object

GameServerSelector matches game servers for an allocation.

Attributes

  • match_labelsmap<string, string>

    Every one of these must equal a label on the server — its own labels or its SDK labels.

  • match_expressionsrepeated LabelRequirement

    Kubernetes' set-based requirements, all of which must hold.

    Show child attributes
    • keystringRequired
    • OPERATOR_INOPERATOR_NOT_INOPERATOR_EXISTSOPERATOR_DOES_NOT_EXIST
    • valuesrepeated string
  • READY (the default) or ALLOCATED — the second is Agones' re-allocation of a server that is already in use and has room, which is how a lobby is joined.

    STATE_READYSTATE_ALLOCATEDSTATE_RESERVEDSTATE_SHUTDOWNSTATE_UNHEALTHY
GameServerSelector
{
"match_labels": {
"key": ""
},
"match_expressions": [
{
"key": "",
"operator": "OPERATOR_IN",
"values": [
""
]
}
],
"state": "STATE_READY"
}

The LabelRequirement object

LabelRequirement is a set-based label selector term.

Attributes

  • keystringRequired
  • OPERATOR_INOPERATOR_NOT_INOPERATOR_EXISTSOPERATOR_DOES_NOT_EXIST
  • valuesrepeated string
LabelRequirement
{
"key": "",
"operator": "OPERATOR_IN",
"values": [
""
]
}

The OperationMetadata object

OperationMetadata is the metadata on every Playpute long-running operation.

Attributes

  • create_timeTimestamp
  • end_timeTimestamp
  • targetstring
  • verbstring
  • status_messagestring
  • requested_cancellationbool
  • api_versionstring
OperationMetadata
{
"create_time": "2026-10-04T12:00:00Z",
"end_time": "2026-10-04T12:00:00Z",
"target": "",
"verb": "",
"status_message": "",
"requested_cancellation": false,
"api_version": ""
}

The ProxyRoute object

projects//locations//gameServers//proxyRoutes/{{proxy_route}}

ProxyRoute is one address players connect to, in front of a game server.

It is the answer to the question the product could not otherwise ask: a server that is hibernated has no host, no address and nothing listening, so "somebody wants to play" cannot be observed on the server itself. A route is a listener that outlives the server behind it. A connection arriving on it is the signal, and forwarding that same connection once the server is up is what makes the signal free of charge to the player — they connected, they waited, they are in.

A route is created per public port a game declares, because a player types one address and the game decides which port it means. RCON is not proxied: a route is reachable by anyone who can reach the proxy, and waking a server on a connection to its administrative console would let a stranger both start a customer's server and reach its shell prompt.

Internal. Customers never name a route — they see its address on GameServer.endpoints, marked proxied.

Attributes

  • namestringIdentifier

    projects/{p}/locations/{l}/gameServers/{s}/proxyRoutes/{port_name}.

    The last segment is the game's own port name — "game", "query" — rather than a generated id, so a route is addressable from the thing that produced it and a re-allocation cannot leave two routes for one port.

  • game_serverstringOutput only
  • gamestringOutput only

    The game being served.

  • port_namestringOutput only

    The game's plany.game.v1.PortMapping name this route fronts, e.g. "game".

  • listen_hoststringOutput only

    Where the proxy listens, and what players are told to connect to.

  • listen_portint32Output only
  • protocolstringOutput only

    "tcp" or "udp". A game declaring both gets two routes: they are two listeners on two sockets, and a UDP session has no relationship to a TCP connection on the same number.

  • target_portint32Output only

    The port the game listens on inside the server. Not the port the proxy listens on: a shared address cannot give every server 25565, so the two differ and the proxy translates.

  • billableboolOutput only

    Whether this route is charged for.

    False for a game Plany publishes, true for a customer's own. Waking a Minecraft server costs Plany the same either way; the difference is what the platform is selling. A pre-configured game is the product, and its proxy is part of the price of the server. A customer's own game is a platform capability being used to host something Plany did not build, and charging for it is what stops the listener pool being free infrastructure for arbitrary traffic.

  • proxystringOutput only

    The connection proxy this route is a listener on.

    Every route on one network shares one, and it is what listen_port is unique within — which is why two projects, or two networks of one project, can both use 25565.

  • create_timeTimestampOutput only
ProxyRoute
{
"name": "projects//locations//gameServers//proxyRoutes/my-proxy-route",
"game_server": "projects//locations//gameServers/",
"game": "games/my-game",
"port_name": "",
"listen_host": "",
"listen_port": 0,
"protocol": "",
"target_port": 0,
"billable": false,
"proxy": "",
"create_time": "2026-10-04T12:00:00Z"
}

The RolloutPolicy object

RolloutPolicy is how a group replaces members running an old build.

Agones' Fleet.spec.strategy, and the same defaults: a rolling replacement, a quarter of the group at a time in each direction.

Attributes

  • STRATEGY_ROLLING_UPDATESTRATEGY_RECREATE
  • max_surgeint32

    Members above the desired size a rolling update may create, as a count or as a percentage of the desired size. The larger of the two when both are set; 25% when neither is.

  • max_surge_percentint32
  • max_unavailableint32

    Members below the desired size a rolling update may leave the group at, as a count or a percentage. 25% when neither is set.

  • max_unavailable_percentint32
RolloutPolicy
{
"strategy": "STRATEGY_ROLLING_UPDATE",
"max_surge": 0,
"max_surge_percent": 0,
"max_unavailable": 0,
"max_unavailable_percent": 0
}

The ScalingPolicy object

ScalingPolicy is what a group scales on.

Every target is a number to hold, never a threshold to cross, because a threshold answers "should I scale" and a target answers "to what" — and only the second can be satisfied in one step. A group that adds one member per pass while a threshold stays crossed takes as many passes as it needs members, with players queueing for all of them.

Zero means the term is off. Not "target zero", which read literally is an instruction to grow forever.

Terms combine by maximum: every one answers "how many members does this load need", and the largest answer is taken. Satisfying a smaller one would leave the larger term unsatisfied and the next pass would grow again anyway.

Attributes

  • max_sizeint32Required
  • min_sizeint32

    Members never to go below, and never to go above.

    A minimum of zero is legitimate and is what a group for an off-peak game wants: no players, no servers, no bill. The first player then pays a boot, which is what the schematic is for.

  • target_player_percentdouble

    Hold members at this fraction of their player capacity. 1..100.

    The headline signal for a minigame: "keep servers 70% full" is the sentence a customer says. Needs the game to declare how many players a server holds; without that this term sits out rather than guessing.

  • min_free_player_slotsint32

    Keep at least this many player slots free across the whole group, so a party arriving together finds room without waiting for a boot.

    Additive to the percentage rather than an alternative — they answer different questions, and a group that sets both gets whichever needs more.

  • scale_on_waiting_connectionsbool

    Add members when connections are open against servers nobody is playing on.

    The only leading signal available: every other term here reacts to load that has already landed, and this one is somebody who could not get in. It needs no capacity and no sample, so it works for a game the platform knows nothing about.

  • target_cpu_percentdouble

    Hold the group's mean CPU at this percentage of each member's allocation. 1..100.

  • scale_out_cooldownDuration

    How long after growing before the group may grow again.

    A member takes tens of seconds to accept its first player, and every pass inside that window sees the same load on the same members. Without this a group creates one member per pass until the first finishes booting.

  • scale_in_patienceDuration

    How long a member must have been empty before it may be removed.

    Longer than the cooldown by default and by intent. Scaling in on a momentary zero is the failure that matters here: presence is derived from the game's own log lines, which can be late or missed, so a server between two rounds reads as empty for a few seconds. Growing late is a queue; shrinking early is a disconnection, and only the first is fixed by waiting.

  • max_scale_out_batchint32

    Most members to add or remove in one pass.

  • max_scale_in_batchint32
  • drain_timeoutDuration

    How long a drained member is given to empty before it is removed anyway.

    A drain is not a disconnection: the member stops being sent new players and keeps the ones it has. Somebody who never leaves would otherwise hold a member forever, so there is a deadline — long enough that a match finishes inside it.

  • buffer_sizeint32

    Keep this many members READY and unallocated, on top of those allocated.

    Agones' FleetAutoscaler buffer, and the shape a lobby needs: "always two servers accepting players, however many are mid-match". Reads the SDK state the game reports, so it needs a game that calls Ready() and Allocate() — for one that does not, every member is unallocated and the term asks only for the buffer itself.

    A sleeping READY member counts: it can be allocated. That is what makes a buffer cheap while nobody plays.

    Combined with the other terms by maximum, like all of them, and bounded by min_size and max_size.

  • buffer_percentdouble

    The buffer as a percentage of the group's size. 1..100. The larger of this and buffer_size when both are set.

ScalingPolicy
{
"min_size": 0,
"max_size": 0,
"target_player_percent": 0,
"min_free_player_slots": 0,
"scale_on_waiting_connections": false,
"target_cpu_percent": 0,
"scale_out_cooldown": "300s",
"scale_in_patience": "300s",
"max_scale_out_batch": 0,
"max_scale_in_batch": 0,
"drain_timeout": "300s",
"buffer_size": 0,
"buffer_percent": 0
}

The SecretAttachment object

SecretAttachment makes one secret readable by one game server.

The secret appears as an environment variable, and the same variable can be substituted into config files and the launch command as ${VAR}. So a Minecraft server's RCON password is one attachment: RCON_PASSWORD in the environment, and rcon.password=${RCON_PASSWORD} in server.properties.

Attaching does not copy the value. It allows this server to read that one secret, and stops the secret being deleted while it is attached. Rotating a secret is adding a new version and restarting the server.

Attributes

  • secretstringRequired

    projects/{project}/locations/{location}/secrets/{secret}, optionally with /versions/{version}.

    Unqualified is the ordinary case and resolves to the latest enabled version, so a rotation reaches this server on its next start with nothing to edit. Pin a version when a server must not follow a rotation — which is rare, and worth being deliberate about, because the pin outlives the memory of why it was made.

  • environment_variablestringRequired

    The environment variable the server sees the secret as, e.g. RCON_PASSWORD.

    Required, and must be a valid variable name — upper case letters, digits and underscores, not starting with a digit. It is not derived from the secret's id, because stripe-live-key is not a variable name.

    The value has to be valid UTF-8 to be used this way. A secret holding binary data is refused when the server starts; use file_path for one.

  • file_pathstring

    Also write the value to a file at this path, relative to the build root.

    For the things that will not go in an environment variable: a service account JSON, a TLS key, a licence file a game reads by path. Optional, and when it is set the environment variable is still exported, because a value that is available two ways is easier to use than one with a rule about when it is which.

    Written 0600 and owned by the game user, and deliberately not preserved across restarts the way a plany.game.v1.ConfigFile can be: this is the platform's copy of a value the platform holds, so the file is rewritten every launch and a rotation cannot leave a stale one behind.

SecretAttachment
{
"secret": "projects//locations//secrets/",
"environment_variable": "",
"file_path": ""
}

The SpotAvailability object

SpotAvailability summarises a machine type's spot record in one region.

Deliberately never a count of free machines. How much spare capacity a region holds is Plany's fleet size read back through a side door; what a customer needs is whether they can have one and how often it will be taken away, and both are answerable as a fraction.

Attributes

  • available_nowbool

    Whether a spot server of this type could be placed right now.

    A reading, not a promise: spare capacity is whatever on-demand servers are not using, and the next on-demand create may take it.

  • availability_7ddouble

    The fraction of the last seven days in which a spot server of this type could have been placed, 0 to 1.

  • reclaims_per_day_7ddouble

    How often a running spot server of this type was reclaimed over the last seven days, as reclaims per server-day. 0.1 means one reclaim every ten days of running, on average.

  • sample_timeTimestamp

    When the record was last sampled. Unset when this region has never recorded anything for the type — which is not the same as zero availability, and a console must not draw it as such.

SpotAvailability
{
"available_now": false,
"availability_7d": 0,
"reclaims_per_day_7d": 0,
"sample_time": "2026-10-04T12:00:00Z"
}

The SpotConfig object

SpotConfig asks for a game server to run on spare capacity.

What spot is

Spot is spare capacity, sold at 60% off. The price of the discount is that it can be taken back: when an on-demand server needs the room, a spot server on it is given two minutes' notice and then stopped.

The notice reaches the game three ways, and a game may use any of them:

  • The metadata service. GET http://169.254.169.254/metadata/spot/instance-action answers 404 until a notice exists and then {"action":"stop","time":"<RFC 3339>"}. Poll it every few seconds.
  • The Agones SDK. WatchGameServer delivers the annotation plany.cloud/spot-termination-time with the same RFC 3339 time.
  • A process signal, if notice_signal names one.

What a reclaim keeps

Everything on disk. A reclaimed server stops with its disk kept, and its next start brings that disk to wherever there is room — so a start just after a reclaim is slower than usual, and nothing on disk is lost. Memory is not kept: a reclaimed server boots from scratch.

Who can have it

Accounts on the Pro plan. Spot is refused on any other plan, and a server whose account has since left Pro starts on demand.

Attributes

  • enabledbool

    Run on spot capacity.

  • on_demand_fallbackbool

    Start on demand, at the on-demand rate, when no spot capacity is free.

    Without it a start with no spot capacity waits for some and fails after a minute, which is right for a server that is only worth running cheaply and wrong for one players are waiting on. A server that fell back stays on demand until it next stops; SpotStatus.running_on_spot says which it is.

  • notice_signalstring

    A signal to send the game's process when a notice arrives, e.g. SIGUSR1.

    Empty sends nothing, and that is the default for a reason: the default action of most signals is to terminate, so a signal a game does not handle would stop it two minutes early. Name one only when the game handles it. SIGTERM and SIGKILL are refused — the stop that follows the notice sends the game's own stop signal already.

SpotConfig
{
"enabled": false,
"on_demand_fallback": false,
"notice_signal": ""
}

The SpotHistoryPoint object

SpotHistoryPoint is one bucket of a machine type's spot record.

Attributes

  • intervalInterval
  • availabilitydouble

    The fraction of this bucket in which a spot server of the type could have been placed. Unset (with measured false) for a bucket the platform took no samples in.

  • reclaimsint64

    Spot servers of this type reclaimed during the bucket.

  • running_hoursdouble

    Server-hours of spot running of this type during the bucket. What makes reclaims a rate rather than a count: two reclaims among two servers and two among two hundred are different records.

  • measuredbool

    Whether any sample landed in this bucket. A gap is "not measured", never "unavailable".

SpotHistoryPoint
{
"interval": {
"start_time": "2026-10-01T00:00:00Z",
"end_time": "2026-10-04T00:00:00Z"
},
"availability": 0,
"reclaims": "0",
"running_hours": 0,
"measured": false
}

The SpotStatus object

SpotStatus is what spot is doing for a server right now.

Attributes

  • running_on_spotboolOutput only

    Whether the current run is on spot capacity. False for a server that fell back to on demand, and for one that is not running.

  • termination_timeTimestampOutput only

    When the current run will be stopped, once a notice has been given.

  • last_reclaim_timeTimestampOutput only

    When this server was last reclaimed.

  • preserving_diskboolOutput only

    Whether the disk of a reclaimed server is still being captured. A start is refused as retryable until it finishes, because starting before it would boot a server without its world.

  • noticeDurationOutput only

    How long the notice was, for a console that wants to draw a countdown.

SpotStatus
{
"running_on_spot": false,
"termination_time": "2026-10-04T12:00:00Z",
"last_reclaim_time": "2026-10-04T12:00:00Z",
"preserving_disk": false,
"notice": "300s"
}

The UpdateGameServerSdkRequest.Empty object

The empty message, named here so an action with no argument is still a distinct arm of the oneof.

Attributes

No parameters.

UpdateGameServerSdkRequest.Empty
{}

The UpdateGameServerSdkRequest.KeyValue object

Attributes

  • keystring
  • valuestring
UpdateGameServerSdkRequest.KeyValue
{
"key": "",
"value": ""
}

AllocateGameServerResponse

AllocateGameServerResponse is the server a match was given.

  • game_serverGameServer
    Show child attributes
    • gamestringRequired

      The game to run. Must be launchable — a branch node has no build.

    • namestringIdentifier

      projects/{project}/locations/{location}/gameServers/{game_server}.

      Project- and region-scoped, like every resource that consumes capacity: it runs somewhere specific, and it is billed to the project that owns it.

    • display_namestring
    • buildstringOutput only

      Resolved at create time and never re-resolved.

      A game's build moves on; a running server's must not. Pinning it here means an update to "Minecraft Forge 1.20.4" cannot silently change what a customer's server is running under their players' feet.

    • settingsmap<string, string>

      Overrides for the game's declared settings, by key.

    • resourcesResourceRequirementsOutput only

      What the server runs with: the machine type's vCPUs and memory, and the game's declared disk.

      Output only. A size is chosen by naming a machine_type; this field used to take any vCPU count and any amount of memory, and a create or update that sets it is refused with a pointer to machine_type. See MachineType for why sizes are named now.

      Show child attributes
    • machine_typestring

      The size to run at, by machine type id — standard-4, highmem-2.

      Empty takes the smallest type that meets the game's own declared minimum, and a type below that minimum is refused, because a server too small for its game boots, installs, and is killed for memory at the first player. ListMachineTypes is the catalogue. Changing it takes effect on the next start.

    • Run on spare capacity at a discount, and accept being reclaimed with two minutes' notice. Pro plan only. See SpotConfig.

      Changing it takes effect on the next start.

      Show child attributes
      • enabledbool

        Run on spot capacity.

      • on_demand_fallbackbool

        Start on demand, at the on-demand rate, when no spot capacity is free.

        Without it a start with no spot capacity waits for some and fails after a minute, which is right for a server that is only worth running cheaply and wrong for one players are waiting on. A server that fell back stays on demand until it next stops; SpotStatus.running_on_spot says which it is.

      • notice_signalstring

        A signal to send the game's process when a notice arrives, e.g. SIGUSR1.

        Empty sends nothing, and that is the default for a reason: the default action of most signals is to terminate, so a signal a game does not handle would stop it two minutes early. Name one only when the game handles it. SIGTERM and SIGKILL are refused — the stop that follows the notice sends the game's own stop signal already.

    • spot_statusSpotStatusOutput only

      What spot is doing for this server right now.

      Show child attributes
      • running_on_spotboolOutput only

        Whether the current run is on spot capacity. False for a server that fell back to on demand, and for one that is not running.

      • termination_timeTimestampOutput only

        When the current run will be stopped, once a notice has been given.

      • last_reclaim_timeTimestampOutput only

        When this server was last reclaimed.

      • preserving_diskboolOutput only

        Whether the disk of a reclaimed server is still being captured. A start is refused as retryable until it finishes, because starting before it would boot a server without its world.

      • noticeDurationOutput only

        How long the notice was, for a console that wants to draw a countdown.

    • stateGameServer.StateOutput only
      STATE_PROVISIONINGSTATE_STARTINGSTATE_RUNNINGSTATE_STOPPEDSTATE_STOPPINGSTATE_FAILEDSTATE_DELETING
    • state_messagestringOutput only
    • errorStatusOutput only
    • endpointsrepeated EndpointOutput only

      How to reach it. Empty until the server is running and has an address.

      A port may appear twice: once as Plany's proxy and once as the server's own address, distinguished by proxied. Give players the proxied one: it is reachable while the server is stopped, and connecting to it starts the server.

      Proxied entries come first, so endpoints[0] is the address to hand out.

      Show child attributes
      • namestring

        Matches the game's plany.game.v1.PortMapping name, e.g. "game".

      • hoststring
      • portint32
      • protocolstring

        "tcp" or "udp".

      • addressstring

        Ready-to-paste form, e.g. "play.example.com:25565". Populated because every console and support conversation ends up building this string anyway, and building it in one place avoids three subtly different ones.

      • proxiedbool

        Whether this address is Plany's proxy rather than the server itself.

        A proxied address is reachable while the server is stopped or asleep, and connecting to it starts the server — so it is the one to give to players. A player's first connection after a sleep waits a few seconds while the server comes back.

    • instancestringOutput only

      An identifier Plany support may ask for when investigating a server. Output only; nothing in the API acts on it.

    • labelsmap<string, string>
    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • last_active_timeTimestampOutput only

      When it last had a player. Drives idle shutdown, and is the field activity billing will read.

    • service_accountstring

      The identity this server acts as.

      Leave it empty and Playpute creates one per server, allowed to touch this server and nothing else — the right default, since a server runs your players' mods.

      Set it to a service account you own and the server acts as that instead. That is for a fleet: grant one service account a role elsewhere, attach it to twenty servers, and those twenty can use it while the rest of the account cannot.

      Attaching one requires iam.serviceAccounts.actAs on that service account, not merely permission to create a server — otherwise anybody who could create a server could act as anybody.

    • ssh_public_keysrepeated stringInput only

      SSH keys allowed to log in to this server, for debugging.

      They take effect only on a server booted from an image that includes an SSH server, and are read when the server boots, so a key added later needs a restart. Input only: the keys are not returned when the server is read.

    • imagestringInput only

      The image to boot, by id. Empty uses Plany's current default, which is what almost every server should do.

      An id from Plany's own published images; a server cannot boot an image of your own.

    • ephemeralbool

      Keep nothing. The world and the disks go when the server does.

      The right shape for a match rather than a world: a minigame round has nothing worth carrying into the next one, and an ephemeral server saves the storage and the time of keeping it.

      An ephemeral server never sleeps, because there is nothing to wake into, so sleep_after_idle is refused on one.

      Immutable after creation: the guarantee is about data that was never kept, so it cannot be turned off afterwards.

    • exposureExposure

      Whether players outside the project can reach this server.

      Immutable after creation: it decides whether a listener and a public address exist at all, and flipping it on a running server would change the address players were given.

      EXPOSURE_PUBLICEXPOSURE_PROJECT_INTERNAL
    • schematicstring

      The schematic this server's disk was copied from, if any.

      What makes a scaled fleet viable: the build is already unpacked, the install script has already run and the world already exists, so a member reaches RUNNING in seconds where a cold boot is minutes.

      A copy, not an attachment. The schematic is read once into a fresh disk and never referenced again, which is why deleting one does not disturb a server started from it — and why two members from one schematic diverge immediately rather than sharing anything.

    • groupstringOutput only

      The group that created and owns this server, if any.

      Output-only and not settable: a server does not join a group, a group creates it. The distinction matters because the group's loop deletes what it owns, and a server that could name a group it was not created by would be a way to have somebody else'"'"'s fleet delete your server.

      A member deleted by hand comes back. Its size is the group'"'"'s to decide, so removing one is a decision the next pass overrules.

    • drainingboolOutput only

      Whether this server is draining: serving the players it has and being sent no new ones, on its way out.

      Its own field rather than a state, because a draining server is still RUNNING in every way that matters — it holds players, it bills, it serves. Folding it into state would make every consumer that switches on state handle a case that behaves identically to RUNNING, and the one that forgot would stop showing a server people are on.

    • Secrets this server can read: database passwords, API keys, RCON passwords, a licence key a game wants in a file.

      Each attachment names a secret in the same project and region and says how the server sees it. The value is never stored on the server's configuration — the server fetches it when it starts, as its own identity — so nothing you can read back from the server reveals it.

      Changing this takes effect on the next start. A running server keeps what it read when it started.

      Show child attributes
      • secretstringRequired

        projects/{project}/locations/{location}/secrets/{secret}, optionally with /versions/{version}.

        Unqualified is the ordinary case and resolves to the latest enabled version, so a rotation reaches this server on its next start with nothing to edit. Pin a version when a server must not follow a rotation — which is rare, and worth being deliberate about, because the pin outlives the memory of why it was made.

      • environment_variablestringRequired

        The environment variable the server sees the secret as, e.g. RCON_PASSWORD.

        Required, and must be a valid variable name — upper case letters, digits and underscores, not starting with a digit. It is not derived from the secret's id, because stripe-live-key is not a variable name.

        The value has to be valid UTF-8 to be used this way. A secret holding binary data is refused when the server starts; use file_path for one.

      • file_pathstring

        Also write the value to a file at this path, relative to the build root.

        For the things that will not go in an environment variable: a service account JSON, a TLS key, a licence file a game reads by path. Optional, and when it is set the environment variable is still exported, because a value that is available two ways is easier to use than one with a rule about when it is which.

        Written 0600 and owned by the game user, and deliberately not preserved across restarts the way a plany.game.v1.ConfigFile can be: this is the platform's copy of a value the platform holds, so the file is rewritten every launch and a rotation cannot leave a stale one behind.

    • sdkSdkStatusOutput only

      What the game has told the platform about itself through the Agones SDK.

      Every game server runs the SDK server, whether or not it came from an Agones manifest, so a customer's own game can call Ready() and Allocate() the way an Agones game does. A game that never calls it has an empty sdk, and nothing reads one: allocation, the buffer term and idle sleep all treat an unset state as "not using the SDK" rather than as not ready.

      Separate from state for the reason activity is. state is what the machine is doing and the platform decides it; this is what the game says it is doing, and a RUNNING server is READY, ALLOCATED or neither.

      Show child attributes
      • stateSdkStatus.StateOutput only
        STATE_READYSTATE_ALLOCATEDSTATE_RESERVEDSTATE_SHUTDOWNSTATE_UNHEALTHY
      • labelsmap<string, string>Output only

        Labels and annotations the game and its allocations wrote.

        SetLabel("mode", "ranked") is stored as agones.dev/sdk-mode, which is Agones' own prefix and what a selector written for Agones asks for. An allocation's metadata is stored as given. Kept apart from GameServer.labels, which the customer or the manifest owns: a game writing its own labels must not be able to rewrite the ones its fleet selects on.

      • annotationsmap<string, string>Output only
      • reserved_untilTimestampOutput only

        When a RESERVED server returns to READY.

      • allocate_timeTimestampOutput only

        When it was last allocated.

      • health_timeTimestampOutput only

        When the game last sent Health().

      • versionint64Output only

        Increases on every change. Reported to the game as the Agones resource_version.

      • update_timeTimestampOutput only
    • sleep_after_idleDuration

      Put the server to sleep after this long with nobody on it.

      Sleep is hibernation: the server's memory is captured, its host released, and the next player's connection — or an allocation — restores it in seconds with everything it held in memory. Compute is not charged while it sleeps.

      The counterpart of idle_shutdown_minutes, and different in the one way that matters: that stops a server a customer forgot about, and this is the platform doing what "pay when played" means for a server somebody wants kept ready. A server the game has marked ALLOCATED or RESERVED never sleeps, because it is somebody's match.

      Idle is measured from the connection proxy's view of the server — no connections and no players — and a server whose presence could not be read is not idle. Refused on an ephemeral server, which cannot hibernate. Zero keeps it awake.

    • managed_bystringOutput only

      The product that created and owns this server, if it was not you.

      autopilot.agones.plany.cloud for a server Agones Autopilot created from a manifest. Change such a server by changing the manifest: Playpute's own update and delete refuse it.

    • install_complete_timeTimestampOutput only

      When the server finished installing its build — for a container build, the image pulled and unpacked; for any other, the build downloaded and its install script run.

    • vpcstringImmutable

      The private network this server is on. Empty is the project's default network in the server's region.

      Decided by the server, never by its game: a game is a catalogue entry shared by every project that runs it, and a network written there would be one project's network named in everybody's servers. Requires vpc.vpcs.use on the network, which must be in the server's own project and region.

      Immutable. A server that changed network would change address under the players connected to it, and the connection proxy in front of it is the proxy for that network — players reach a server through the proxy on the network it is on, so each network a project uses has a proxy of its own.

    • network_tagsrepeated string

      Network tags on this server's interface, which firewall rules on its network can target. Lowercase letters, digits and hyphens.

    • etagstringOutput only
  • Where players connect: the proxied endpoints, which are reachable whether or not the server is awake yet.

    Show child attributes
    • namestring

      Matches the game's plany.game.v1.PortMapping name, e.g. "game".

    • hoststring
    • portint32
    • protocolstring

      "tcp" or "udp".

    • addressstring

      Ready-to-paste form, e.g. "play.example.com:25565". Populated because every console and support conversation ends up building this string anyway, and building it in one place avoids three subtly different ones.

    • proxiedbool

      Whether this address is Plany's proxy rather than the server itself.

      A proxied address is reachable while the server is stopped or asleep, and connecting to it starts the server — so it is the one to give to players. A player's first connection after a sleep waits a few seconds while the server comes back.

  • wokenbool

    Whether the allocation woke a sleeping server. Players connecting now wait a few seconds for the restore; nothing about the address changes.

GameServer

GameServer is one running copy of a game.

It is the product's unit: you pick a game and a region, and get something players can connect to.

  • gamestringRequired

    The game to run. Must be launchable — a branch node has no build.

  • namestringIdentifier

    projects/{project}/locations/{location}/gameServers/{game_server}.

    Project- and region-scoped, like every resource that consumes capacity: it runs somewhere specific, and it is billed to the project that owns it.

  • display_namestring
  • buildstringOutput only

    Resolved at create time and never re-resolved.

    A game's build moves on; a running server's must not. Pinning it here means an update to "Minecraft Forge 1.20.4" cannot silently change what a customer's server is running under their players' feet.

  • settingsmap<string, string>

    Overrides for the game's declared settings, by key.

  • resourcesResourceRequirementsOutput only

    What the server runs with: the machine type's vCPUs and memory, and the game's declared disk.

    Output only. A size is chosen by naming a machine_type; this field used to take any vCPU count and any amount of memory, and a create or update that sets it is refused with a pointer to machine_type. See MachineType for why sizes are named now.

    Show child attributes
    • cpuCpuSpecRequired
      Show child attributes
      • vcpusint32Required

        Number of virtual CPUs the workload sees. Required, must be at least 1.

      • reserved_millisint64

        CPU time reserved on the host, in millicores (1000 = one full core).

        Must be <= vcpus * 1000. Zero means "reserve the full vcpus * 1000", i.e. no oversubscription. Below that, the VM is burstable and the difference is the burst headroom.

      • limit_millisint64

        Hard ceiling on host CPU time, in millicores, enforced by the agent via cgroup cpu.max. Zero means the ceiling is vcpus * 1000. Set this below vcpus * 1000 to cap a burstable VM that would otherwise consume all idle capacity on the node.

      • architectureCpuArchitecture
        CPU_ARCHITECTURE_X86_64CPU_ARCHITECTURE_ARM64
      • required_featuresrepeated string

        CPUID feature flags the workload requires, lowercase as they appear in /proc/cpuinfo — e.g. "avx2", "aes". Placement rejects nodes lacking any of them. Anti-cheat and DRM in game servers occasionally depend on these.

      • dedicated_coresbool

        Pin each vCPU to a distinct physical core and let no other workload share those cores. Removes noisy-neighbour jitter for latency-sensitive tick loops, at the cost of a dedicated-core price.

      • isolate_smt_siblingsbool

        Require SMT siblings of the pinned cores to stay idle. Only meaningful with dedicated_cores; used for workloads that are sensitive to hyperthread contention or that need side-channel isolation.

    • memoryMemorySpecRequired
      Show child attributes
      • size_bytesint64Required

        Memory the workload sees, in bytes. Required.

      • reserved_bytesint64

        Memory guaranteed to the workload, in bytes. Must be no more than size_bytes. Zero means all of size_bytes is guaranteed.

        Reserving less than size_bytes requires balloon_enabled, so unused memory can be reclaimed when it is needed elsewhere.

      • balloon_enabledbool

        Allow memory the workload is not using to be reclaimed. Required when reserved_bytes is less than size_bytes.

      • hugepagesbool

        Back the workload's memory with 2 MiB pages. Noticeably faster for memory-heavy servers — large voxel worlds, big entity counts — but can only be placed where such memory is available.

      • hotplug_max_bytesint64

        Allow memory to grow to this size while running, without a restart. Zero disables it. Must be at least size_bytes when set.

      • sharedbool

        Allow identical memory pages to be shared with other workloads on the same machine. Saves memory when many servers run the same game, at some CPU cost and with weaker isolation between them.

    • Block devices, in attachment order. Exactly one must set boot unless the workload boots from an initramfs alone.

      Show child attributes
      • disk_idstringRequired

        Identifier for this disk within the workload, e.g. "root" or "world-data". Must be unique within it.

      • sourceDiskSpec.SourceRequired
      • size_bytesint64

        Size of the device. Required for a blank disk; for an image or snapshot source, zero means "the source's own size" and any larger value grows the filesystem on first boot.

      • DISK_TYPE_LOCAL_NVMEDISK_TYPE_NETWORK_SSDDISK_TYPE_NETWORK_SSD_HIGH_IOPS
      • read_onlybool

        Attach read-only. Several instances may share one read-only volume, which is how a common asset bundle is mounted into many game servers at once.

      • bootbool

        Marks the disk the workload boots from. Exactly one disk may set this.

      • delete_on_instance_deletebool

        Delete the underlying storage when the instance is deleted. Always true in effect for LOCAL_NVME.

      • direct_iobool

        Use direct IO (O_DIRECT), bypassing the host page cache. Lowers memory pressure on the node and makes latency more predictable, at the cost of losing host-side caching.

    • Show child attributes
      • interface_idstringRequired

        Stable identifier within the instance, e.g. "eth0".

      • networkstring

        Private network to attach to, as a resource name. Empty means the project's default network in this location.

      • private_ipv4string

        Requested private IPv4 address. Empty allocates one from the subnet.

      • PUBLIC_ADDRESS_MODE_NONEPUBLIC_ADDRESS_MODE_SHARED_IPV4PUBLIC_ADDRESS_MODE_DEDICATED_IPV4PUBLIC_ADDRESS_MODE_IPV6
      • NETWORK_TIER_STANDARDNETWORK_TIER_PREMIUM
      • mac_addressstring

        The interface's MAC address. Empty generates one. Pinning it matters for game licences tied to a MAC.

      • multi_queuebool

        Enable multi-queue virtio-net with one queue pair per vCPU. Raises packet throughput for servers handling many concurrent clients.

      • tagsrepeated string

        Network tags, which firewall rules on this interface's network target.

        Per interface rather than per instance because a rule belongs to one network, and an instance with an interface on each of two networks is answerable to two sets of rules. Lowercase letters, digits and hyphens, up to 63 characters each.

      • deny_inboundbool

        Refuse every inbound connection on this interface, whatever the network's firewall rules say. Replies to connections the workload opened still arrive.

        For an interface that exists so a workload can reach a network rather than be reached on it — a sandbox connected to one of your networks, for example.

      • no_default_routebool

        Send no internet traffic and no DNS through this interface: only the network's own range is reached through it. Without this, a workload with two interfaces could send its internet traffic out of either.

    • placementPlacementSpec
      Show child attributes
      • zonesrepeated string

        Zones the instance may land in, as location ids ("eu-west-2a"). Empty means any zone in the region. More than one entry is a preference list in priority order, not a hard set.

      • required_node_selectorsrepeated NodeSelectorRequirement

        Hard node requirements. A node must satisfy every entry.

      • preferred_node_selectorsrepeated NodeSelectorRequirement

        Soft node preferences. Nodes satisfying more of these score higher, but none of them can make placement fail.

      • placement_groupstring

        Group this workload belongs to, scoped to the project. Workloads sharing a group are spread out or packed together according to policy.

      • PLACEMENT_POLICY_PACKPLACEMENT_POLICY_SPREADPLACEMENT_POLICY_STRICT_SPREAD_NODEPLACEMENT_POLICY_STRICT_SPREAD_ZONE
      • capacity_classstring

        Class of capacity to draw from. Leave empty to let Plany choose, which is right for almost every workload.

      • disallow_preemptiblebool

        Refuse to place onto pre-emptible (spot) capacity. Spot is materially cheaper and fine for a dev server, but wrong for a ranked match in progress.

      • nodestring

        Pin to one node by resource name. Bypasses scoring entirely; intended for debugging and for rescheduling a VM back onto the node holding its local disk.

    • schedulingSchedulingSpec
      Show child attributes
      • ON_HOST_MAINTENANCE_MIGRATEON_HOST_MAINTENANCE_TERMINATE
      • RESTART_POLICY_NEVERRESTART_POLICY_ALWAYSRESTART_POLICY_ON_FAILURE
      • preemptiblebool

        Run as spot: on spare capacity, at the spot rate, reclaimable with two minutes' notice when an on-demand workload needs the room.

      • preemption_noticeDuration

        Warning given before a spot reclaim, readable at /metadata/spot/instance-action on the metadata service. The notice is always two minutes; leave this unset.

      • max_run_durationDuration

        Stop the instance automatically once it has run this long. Zero means no limit. This is the guard rail that stops a forgotten dev server draining a hobby account's credit overnight.

      • termination_grace_periodDuration

        Time between the shutdown signal and a forced stop, so a game server can save its world. Zero uses the default of thirty seconds.

      • preemptible_fallbackbool

        With preemptible: place as an ordinary on-demand workload when no spare capacity fits, rather than waiting for some. The allocation says which happened, and it is what the instance is billed at.

  • machine_typestring

    The size to run at, by machine type id — standard-4, highmem-2.

    Empty takes the smallest type that meets the game's own declared minimum, and a type below that minimum is refused, because a server too small for its game boots, installs, and is killed for memory at the first player. ListMachineTypes is the catalogue. Changing it takes effect on the next start.

  • Run on spare capacity at a discount, and accept being reclaimed with two minutes' notice. Pro plan only. See SpotConfig.

    Changing it takes effect on the next start.

    Show child attributes
    • enabledbool

      Run on spot capacity.

    • on_demand_fallbackbool

      Start on demand, at the on-demand rate, when no spot capacity is free.

      Without it a start with no spot capacity waits for some and fails after a minute, which is right for a server that is only worth running cheaply and wrong for one players are waiting on. A server that fell back stays on demand until it next stops; SpotStatus.running_on_spot says which it is.

    • notice_signalstring

      A signal to send the game's process when a notice arrives, e.g. SIGUSR1.

      Empty sends nothing, and that is the default for a reason: the default action of most signals is to terminate, so a signal a game does not handle would stop it two minutes early. Name one only when the game handles it. SIGTERM and SIGKILL are refused — the stop that follows the notice sends the game's own stop signal already.

  • spot_statusSpotStatusOutput only

    What spot is doing for this server right now.

    Show child attributes
    • running_on_spotboolOutput only

      Whether the current run is on spot capacity. False for a server that fell back to on demand, and for one that is not running.

    • termination_timeTimestampOutput only

      When the current run will be stopped, once a notice has been given.

    • last_reclaim_timeTimestampOutput only

      When this server was last reclaimed.

    • preserving_diskboolOutput only

      Whether the disk of a reclaimed server is still being captured. A start is refused as retryable until it finishes, because starting before it would boot a server without its world.

    • noticeDurationOutput only

      How long the notice was, for a console that wants to draw a countdown.

  • stateGameServer.StateOutput only
    STATE_PROVISIONINGSTATE_STARTINGSTATE_RUNNINGSTATE_STOPPEDSTATE_STOPPINGSTATE_FAILEDSTATE_DELETING
  • state_messagestringOutput only
  • errorStatusOutput only
  • endpointsrepeated EndpointOutput only

    How to reach it. Empty until the server is running and has an address.

    A port may appear twice: once as Plany's proxy and once as the server's own address, distinguished by proxied. Give players the proxied one: it is reachable while the server is stopped, and connecting to it starts the server.

    Proxied entries come first, so endpoints[0] is the address to hand out.

    Show child attributes
    • namestring

      Matches the game's plany.game.v1.PortMapping name, e.g. "game".

    • hoststring
    • portint32
    • protocolstring

      "tcp" or "udp".

    • addressstring

      Ready-to-paste form, e.g. "play.example.com:25565". Populated because every console and support conversation ends up building this string anyway, and building it in one place avoids three subtly different ones.

    • proxiedbool

      Whether this address is Plany's proxy rather than the server itself.

      A proxied address is reachable while the server is stopped or asleep, and connecting to it starts the server — so it is the one to give to players. A player's first connection after a sleep waits a few seconds while the server comes back.

  • instancestringOutput only

    An identifier Plany support may ask for when investigating a server. Output only; nothing in the API acts on it.

  • labelsmap<string, string>
  • create_timeTimestampOutput only
  • update_timeTimestampOutput only
  • last_active_timeTimestampOutput only

    When it last had a player. Drives idle shutdown, and is the field activity billing will read.

  • service_accountstring

    The identity this server acts as.

    Leave it empty and Playpute creates one per server, allowed to touch this server and nothing else — the right default, since a server runs your players' mods.

    Set it to a service account you own and the server acts as that instead. That is for a fleet: grant one service account a role elsewhere, attach it to twenty servers, and those twenty can use it while the rest of the account cannot.

    Attaching one requires iam.serviceAccounts.actAs on that service account, not merely permission to create a server — otherwise anybody who could create a server could act as anybody.

  • ssh_public_keysrepeated stringInput only

    SSH keys allowed to log in to this server, for debugging.

    They take effect only on a server booted from an image that includes an SSH server, and are read when the server boots, so a key added later needs a restart. Input only: the keys are not returned when the server is read.

  • imagestringInput only

    The image to boot, by id. Empty uses Plany's current default, which is what almost every server should do.

    An id from Plany's own published images; a server cannot boot an image of your own.

  • ephemeralbool

    Keep nothing. The world and the disks go when the server does.

    The right shape for a match rather than a world: a minigame round has nothing worth carrying into the next one, and an ephemeral server saves the storage and the time of keeping it.

    An ephemeral server never sleeps, because there is nothing to wake into, so sleep_after_idle is refused on one.

    Immutable after creation: the guarantee is about data that was never kept, so it cannot be turned off afterwards.

  • exposureExposure

    Whether players outside the project can reach this server.

    Immutable after creation: it decides whether a listener and a public address exist at all, and flipping it on a running server would change the address players were given.

    EXPOSURE_PUBLICEXPOSURE_PROJECT_INTERNAL
  • schematicstring

    The schematic this server's disk was copied from, if any.

    What makes a scaled fleet viable: the build is already unpacked, the install script has already run and the world already exists, so a member reaches RUNNING in seconds where a cold boot is minutes.

    A copy, not an attachment. The schematic is read once into a fresh disk and never referenced again, which is why deleting one does not disturb a server started from it — and why two members from one schematic diverge immediately rather than sharing anything.

  • groupstringOutput only

    The group that created and owns this server, if any.

    Output-only and not settable: a server does not join a group, a group creates it. The distinction matters because the group's loop deletes what it owns, and a server that could name a group it was not created by would be a way to have somebody else'"'"'s fleet delete your server.

    A member deleted by hand comes back. Its size is the group'"'"'s to decide, so removing one is a decision the next pass overrules.

  • drainingboolOutput only

    Whether this server is draining: serving the players it has and being sent no new ones, on its way out.

    Its own field rather than a state, because a draining server is still RUNNING in every way that matters — it holds players, it bills, it serves. Folding it into state would make every consumer that switches on state handle a case that behaves identically to RUNNING, and the one that forgot would stop showing a server people are on.

  • Secrets this server can read: database passwords, API keys, RCON passwords, a licence key a game wants in a file.

    Each attachment names a secret in the same project and region and says how the server sees it. The value is never stored on the server's configuration — the server fetches it when it starts, as its own identity — so nothing you can read back from the server reveals it.

    Changing this takes effect on the next start. A running server keeps what it read when it started.

    Show child attributes
    • secretstringRequired

      projects/{project}/locations/{location}/secrets/{secret}, optionally with /versions/{version}.

      Unqualified is the ordinary case and resolves to the latest enabled version, so a rotation reaches this server on its next start with nothing to edit. Pin a version when a server must not follow a rotation — which is rare, and worth being deliberate about, because the pin outlives the memory of why it was made.

    • environment_variablestringRequired

      The environment variable the server sees the secret as, e.g. RCON_PASSWORD.

      Required, and must be a valid variable name — upper case letters, digits and underscores, not starting with a digit. It is not derived from the secret's id, because stripe-live-key is not a variable name.

      The value has to be valid UTF-8 to be used this way. A secret holding binary data is refused when the server starts; use file_path for one.

    • file_pathstring

      Also write the value to a file at this path, relative to the build root.

      For the things that will not go in an environment variable: a service account JSON, a TLS key, a licence file a game reads by path. Optional, and when it is set the environment variable is still exported, because a value that is available two ways is easier to use than one with a rule about when it is which.

      Written 0600 and owned by the game user, and deliberately not preserved across restarts the way a plany.game.v1.ConfigFile can be: this is the platform's copy of a value the platform holds, so the file is rewritten every launch and a rotation cannot leave a stale one behind.

  • sdkSdkStatusOutput only

    What the game has told the platform about itself through the Agones SDK.

    Every game server runs the SDK server, whether or not it came from an Agones manifest, so a customer's own game can call Ready() and Allocate() the way an Agones game does. A game that never calls it has an empty sdk, and nothing reads one: allocation, the buffer term and idle sleep all treat an unset state as "not using the SDK" rather than as not ready.

    Separate from state for the reason activity is. state is what the machine is doing and the platform decides it; this is what the game says it is doing, and a RUNNING server is READY, ALLOCATED or neither.

    Show child attributes
    • stateSdkStatus.StateOutput only
      STATE_READYSTATE_ALLOCATEDSTATE_RESERVEDSTATE_SHUTDOWNSTATE_UNHEALTHY
    • labelsmap<string, string>Output only

      Labels and annotations the game and its allocations wrote.

      SetLabel("mode", "ranked") is stored as agones.dev/sdk-mode, which is Agones' own prefix and what a selector written for Agones asks for. An allocation's metadata is stored as given. Kept apart from GameServer.labels, which the customer or the manifest owns: a game writing its own labels must not be able to rewrite the ones its fleet selects on.

    • annotationsmap<string, string>Output only
    • reserved_untilTimestampOutput only

      When a RESERVED server returns to READY.

    • allocate_timeTimestampOutput only

      When it was last allocated.

    • health_timeTimestampOutput only

      When the game last sent Health().

    • versionint64Output only

      Increases on every change. Reported to the game as the Agones resource_version.

    • update_timeTimestampOutput only
  • sleep_after_idleDuration

    Put the server to sleep after this long with nobody on it.

    Sleep is hibernation: the server's memory is captured, its host released, and the next player's connection — or an allocation — restores it in seconds with everything it held in memory. Compute is not charged while it sleeps.

    The counterpart of idle_shutdown_minutes, and different in the one way that matters: that stops a server a customer forgot about, and this is the platform doing what "pay when played" means for a server somebody wants kept ready. A server the game has marked ALLOCATED or RESERVED never sleeps, because it is somebody's match.

    Idle is measured from the connection proxy's view of the server — no connections and no players — and a server whose presence could not be read is not idle. Refused on an ephemeral server, which cannot hibernate. Zero keeps it awake.

  • managed_bystringOutput only

    The product that created and owns this server, if it was not you.

    autopilot.agones.plany.cloud for a server Agones Autopilot created from a manifest. Change such a server by changing the manifest: Playpute's own update and delete refuse it.

  • install_complete_timeTimestampOutput only

    When the server finished installing its build — for a container build, the image pulled and unpacked; for any other, the build downloaded and its install script run.

  • vpcstringImmutable

    The private network this server is on. Empty is the project's default network in the server's region.

    Decided by the server, never by its game: a game is a catalogue entry shared by every project that runs it, and a network written there would be one project's network named in everybody's servers. Requires vpc.vpcs.use on the network, which must be in the server's own project and region.

    Immutable. A server that changed network would change address under the players connected to it, and the connection proxy in front of it is the proxy for that network — players reach a server through the proxy on the network it is on, so each network a project uses has a proxy of its own.

  • network_tagsrepeated string

    Network tags on this server's interface, which firewall rules on its network can target. Lowercase letters, digits and hyphens.

  • etagstringOutput only

GameServerGroup

GameServerGroup is a fleet of identical game servers that grows and shrinks with demand.

The shape a minigame needs: a lobby fills and more servers arrive, a round ends and they go away. Everything about a member — the game, the build, the resources, whether it keeps data, whether players can reach it directly — is declared once here, so members never differ from each other.

Members are ordinary game servers

A member is a GameServer with group set, and every call that works on a server works on it: it can be read and its logs listed. What is different is deleting one by hand — it is recreated, because the group decides its own size.

The group itself is free

A group adds no charge of its own. Its members are billed as any other game server, and its schematic as storage.

  • gamestringRequired

    The game every member runs.

  • policyScalingPolicyRequired
    Show child attributes
    • max_sizeint32Required
    • min_sizeint32

      Members never to go below, and never to go above.

      A minimum of zero is legitimate and is what a group for an off-peak game wants: no players, no servers, no bill. The first player then pays a boot, which is what the schematic is for.

    • target_player_percentdouble

      Hold members at this fraction of their player capacity. 1..100.

      The headline signal for a minigame: "keep servers 70% full" is the sentence a customer says. Needs the game to declare how many players a server holds; without that this term sits out rather than guessing.

    • min_free_player_slotsint32

      Keep at least this many player slots free across the whole group, so a party arriving together finds room without waiting for a boot.

      Additive to the percentage rather than an alternative — they answer different questions, and a group that sets both gets whichever needs more.

    • scale_on_waiting_connectionsbool

      Add members when connections are open against servers nobody is playing on.

      The only leading signal available: every other term here reacts to load that has already landed, and this one is somebody who could not get in. It needs no capacity and no sample, so it works for a game the platform knows nothing about.

    • target_cpu_percentdouble

      Hold the group's mean CPU at this percentage of each member's allocation. 1..100.

    • scale_out_cooldownDuration

      How long after growing before the group may grow again.

      A member takes tens of seconds to accept its first player, and every pass inside that window sees the same load on the same members. Without this a group creates one member per pass until the first finishes booting.

    • scale_in_patienceDuration

      How long a member must have been empty before it may be removed.

      Longer than the cooldown by default and by intent. Scaling in on a momentary zero is the failure that matters here: presence is derived from the game's own log lines, which can be late or missed, so a server between two rounds reads as empty for a few seconds. Growing late is a queue; shrinking early is a disconnection, and only the first is fixed by waiting.

    • max_scale_out_batchint32

      Most members to add or remove in one pass.

    • max_scale_in_batchint32
    • drain_timeoutDuration

      How long a drained member is given to empty before it is removed anyway.

      A drain is not a disconnection: the member stops being sent new players and keeps the ones it has. Somebody who never leaves would otherwise hold a member forever, so there is a deadline — long enough that a match finishes inside it.

    • buffer_sizeint32

      Keep this many members READY and unallocated, on top of those allocated.

      Agones' FleetAutoscaler buffer, and the shape a lobby needs: "always two servers accepting players, however many are mid-match". Reads the SDK state the game reports, so it needs a game that calls Ready() and Allocate() — for one that does not, every member is unallocated and the term asks only for the buffer itself.

      A sleeping READY member counts: it can be allocated. That is what makes a buffer cheap while nobody plays.

      Combined with the other terms by maximum, like all of them, and bounded by min_size and max_size.

    • buffer_percentdouble

      The buffer as a percentage of the group's size. 1..100. The larger of this and buffer_size when both are set.

  • namestringIdentifier

    projects/{p}/locations/{l}/gameServerGroups/{g}.

  • display_namestring
  • buildstring

    The build every member runs.

    Pinned like a game server's, and for a stronger reason: members are created and destroyed continuously, so a group that resolved the game's current build per member would put two versions of a customer's game in one fleet, with players matched across them by accident.

    Updatable, and changing it is a rollout, never a mixture by accident. The group goes on creating members on the old build while a warm-up bakes the new one (pending_build), switches when the capture lands, and then replaces outdated members within rollout — never one the game has marked ALLOCATED, which is somebody's match and finishes on the build it started on.

  • settingsmap<string, string>

    Settings handed to every member, exactly as GameServer.settings.

  • resourcesResourceRequirementsOutput only

    What each member gets. Uniform across the fleet by construction.

    Output only: resolved from machine_type and the game's disk, exactly as GameServer.resources is.

    Show child attributes
    • cpuCpuSpecRequired
      Show child attributes
      • vcpusint32Required

        Number of virtual CPUs the workload sees. Required, must be at least 1.

      • reserved_millisint64

        CPU time reserved on the host, in millicores (1000 = one full core).

        Must be <= vcpus * 1000. Zero means "reserve the full vcpus * 1000", i.e. no oversubscription. Below that, the VM is burstable and the difference is the burst headroom.

      • limit_millisint64

        Hard ceiling on host CPU time, in millicores, enforced by the agent via cgroup cpu.max. Zero means the ceiling is vcpus * 1000. Set this below vcpus * 1000 to cap a burstable VM that would otherwise consume all idle capacity on the node.

      • architectureCpuArchitecture
        CPU_ARCHITECTURE_X86_64CPU_ARCHITECTURE_ARM64
      • required_featuresrepeated string

        CPUID feature flags the workload requires, lowercase as they appear in /proc/cpuinfo — e.g. "avx2", "aes". Placement rejects nodes lacking any of them. Anti-cheat and DRM in game servers occasionally depend on these.

      • dedicated_coresbool

        Pin each vCPU to a distinct physical core and let no other workload share those cores. Removes noisy-neighbour jitter for latency-sensitive tick loops, at the cost of a dedicated-core price.

      • isolate_smt_siblingsbool

        Require SMT siblings of the pinned cores to stay idle. Only meaningful with dedicated_cores; used for workloads that are sensitive to hyperthread contention or that need side-channel isolation.

    • memoryMemorySpecRequired
      Show child attributes
      • size_bytesint64Required

        Memory the workload sees, in bytes. Required.

      • reserved_bytesint64

        Memory guaranteed to the workload, in bytes. Must be no more than size_bytes. Zero means all of size_bytes is guaranteed.

        Reserving less than size_bytes requires balloon_enabled, so unused memory can be reclaimed when it is needed elsewhere.

      • balloon_enabledbool

        Allow memory the workload is not using to be reclaimed. Required when reserved_bytes is less than size_bytes.

      • hugepagesbool

        Back the workload's memory with 2 MiB pages. Noticeably faster for memory-heavy servers — large voxel worlds, big entity counts — but can only be placed where such memory is available.

      • hotplug_max_bytesint64

        Allow memory to grow to this size while running, without a restart. Zero disables it. Must be at least size_bytes when set.

      • sharedbool

        Allow identical memory pages to be shared with other workloads on the same machine. Saves memory when many servers run the same game, at some CPU cost and with weaker isolation between them.

    • Block devices, in attachment order. Exactly one must set boot unless the workload boots from an initramfs alone.

      Show child attributes
      • disk_idstringRequired

        Identifier for this disk within the workload, e.g. "root" or "world-data". Must be unique within it.

      • sourceDiskSpec.SourceRequired
      • size_bytesint64

        Size of the device. Required for a blank disk; for an image or snapshot source, zero means "the source's own size" and any larger value grows the filesystem on first boot.

      • DISK_TYPE_LOCAL_NVMEDISK_TYPE_NETWORK_SSDDISK_TYPE_NETWORK_SSD_HIGH_IOPS
      • read_onlybool

        Attach read-only. Several instances may share one read-only volume, which is how a common asset bundle is mounted into many game servers at once.

      • bootbool

        Marks the disk the workload boots from. Exactly one disk may set this.

      • delete_on_instance_deletebool

        Delete the underlying storage when the instance is deleted. Always true in effect for LOCAL_NVME.

      • direct_iobool

        Use direct IO (O_DIRECT), bypassing the host page cache. Lowers memory pressure on the node and makes latency more predictable, at the cost of losing host-side caching.

    • Show child attributes
      • interface_idstringRequired

        Stable identifier within the instance, e.g. "eth0".

      • networkstring

        Private network to attach to, as a resource name. Empty means the project's default network in this location.

      • private_ipv4string

        Requested private IPv4 address. Empty allocates one from the subnet.

      • PUBLIC_ADDRESS_MODE_NONEPUBLIC_ADDRESS_MODE_SHARED_IPV4PUBLIC_ADDRESS_MODE_DEDICATED_IPV4PUBLIC_ADDRESS_MODE_IPV6
      • NETWORK_TIER_STANDARDNETWORK_TIER_PREMIUM
      • mac_addressstring

        The interface's MAC address. Empty generates one. Pinning it matters for game licences tied to a MAC.

      • multi_queuebool

        Enable multi-queue virtio-net with one queue pair per vCPU. Raises packet throughput for servers handling many concurrent clients.

      • tagsrepeated string

        Network tags, which firewall rules on this interface's network target.

        Per interface rather than per instance because a rule belongs to one network, and an instance with an interface on each of two networks is answerable to two sets of rules. Lowercase letters, digits and hyphens, up to 63 characters each.

      • deny_inboundbool

        Refuse every inbound connection on this interface, whatever the network's firewall rules say. Replies to connections the workload opened still arrive.

        For an interface that exists so a workload can reach a network rather than be reached on it — a sandbox connected to one of your networks, for example.

      • no_default_routebool

        Send no internet traffic and no DNS through this interface: only the network's own range is reached through it. Without this, a workload with two interfaces could send its internet traffic out of either.

    • placementPlacementSpec
      Show child attributes
      • zonesrepeated string

        Zones the instance may land in, as location ids ("eu-west-2a"). Empty means any zone in the region. More than one entry is a preference list in priority order, not a hard set.

      • required_node_selectorsrepeated NodeSelectorRequirement

        Hard node requirements. A node must satisfy every entry.

      • preferred_node_selectorsrepeated NodeSelectorRequirement

        Soft node preferences. Nodes satisfying more of these score higher, but none of them can make placement fail.

      • placement_groupstring

        Group this workload belongs to, scoped to the project. Workloads sharing a group are spread out or packed together according to policy.

      • PLACEMENT_POLICY_PACKPLACEMENT_POLICY_SPREADPLACEMENT_POLICY_STRICT_SPREAD_NODEPLACEMENT_POLICY_STRICT_SPREAD_ZONE
      • capacity_classstring

        Class of capacity to draw from. Leave empty to let Plany choose, which is right for almost every workload.

      • disallow_preemptiblebool

        Refuse to place onto pre-emptible (spot) capacity. Spot is materially cheaper and fine for a dev server, but wrong for a ranked match in progress.

      • nodestring

        Pin to one node by resource name. Bypasses scoring entirely; intended for debugging and for rescheduling a VM back onto the node holding its local disk.

    • schedulingSchedulingSpec
      Show child attributes
      • ON_HOST_MAINTENANCE_MIGRATEON_HOST_MAINTENANCE_TERMINATE
      • RESTART_POLICY_NEVERRESTART_POLICY_ALWAYSRESTART_POLICY_ON_FAILURE
      • preemptiblebool

        Run as spot: on spare capacity, at the spot rate, reclaimable with two minutes' notice when an on-demand workload needs the room.

      • preemption_noticeDuration

        Warning given before a spot reclaim, readable at /metadata/spot/instance-action on the metadata service. The notice is always two minutes; leave this unset.

      • max_run_durationDuration

        Stop the instance automatically once it has run this long. Zero means no limit. This is the guard rail that stops a forgotten dev server draining a hobby account's credit overnight.

      • termination_grace_periodDuration

        Time between the shutdown signal and a forced stop, so a game server can save its world. Zero uses the default of thirty seconds.

      • preemptible_fallbackbool

        With preemptible: place as an ordinary on-demand workload when no spare capacity fits, rather than waiting for some. The allocation says which happened, and it is what the instance is billed at.

  • machine_typestring

    The machine type every member runs at, as GameServer.machine_type. Empty takes the smallest type that meets the game's minimum.

    Updatable, and a change reaches a member the next time it starts; it is not a rollout, because a size is not what a match is played on.

  • Run members on spot capacity, as GameServer.spot. Pro plan only.

    A fleet is where spot is most useful — a minigame server reclaimed between rounds costs nobody anything — and it composes with scaling in one way worth knowing: a reclaimed member counts as not running, so a group that needs it creates or starts another. With on_demand_fallback that one is on demand when spot has nothing free, which is what keeps a fleet at size while the region is busy.

    Show child attributes
    • enabledbool

      Run on spot capacity.

    • on_demand_fallbackbool

      Start on demand, at the on-demand rate, when no spot capacity is free.

      Without it a start with no spot capacity waits for some and fails after a minute, which is right for a server that is only worth running cheaply and wrong for one players are waiting on. A server that fell back stays on demand until it next stops; SpotStatus.running_on_spot says which it is.

    • notice_signalstring

      A signal to send the game's process when a notice arrives, e.g. SIGUSR1.

      Empty sends nothing, and that is the default for a reason: the default action of most signals is to terminate, so a signal a game does not handle would stop it two minutes early. Name one only when the game handles it. SIGTERM and SIGKILL are refused — the stop that follows the notice sends the game's own stop signal already.

  • ephemeralbool

    Whether members keep their data.

    Almost always true for the workload a group is for: a match has nothing worth carrying into the next one, and a member that hibernated would write its whole RAM to object storage on the way out of a world nobody will read.

    It also changes what scaling in means. An ephemeral member is deleted when it is drained; a durable one is stopped, keeps its disks, and is started again when the group grows.

  • exposureExposure

    Whether players can reach members directly.

    PROJECT_INTERNAL is the right default for a scaled fleet and the reason the field exists: members behind a matchmaker or a lobby are dialled from inside the project, and giving each one a public listener would be an entry point nobody intended and a proxy charge per member. The choice is the customer's, because a fleet of servers players do pick from a list is just as real a shape.

    EXPOSURE_PUBLICEXPOSURE_PROJECT_INTERNAL
  • warmup_durationDuration

    How long a warm-up server runs before it is captured as the schematic.

    The one number that decides how fast this group scales. A member started from a schematic skips the download, the install and the world generation — seconds instead of minutes — and what makes the schematic worth having is that the capture happened after all of that finished.

    So this is "how long does your game take to be ready to play", and getting it wrong is visible in one direction only: too long wastes a few minutes once, and too short captures a server mid-install, which every member then starts from.

    Zero skips the warm-up entirely and members boot cold. That is the right choice for a game that starts in seconds anyway, and the only choice for one whose first run must not be cloned.

  • schematicstring

    The schematic members are started from.

    Set by the group when its warm-up capture lands, or supplied at creation to reuse one that already exists — which is the faster path and the one a customer takes for their second group of the same game.

    Empty means members boot cold, which is correct rather than broken: a group whose capture failed still scales, just slowly, and stopping it from scaling would turn a performance problem into an outage.

  • stateGameServerGroup.StateOutput only
    STATE_WARMING_UPSTATE_ACTIVESTATE_PAUSEDSTATE_FAILEDSTATE_DELETING
  • state_messagestringOutput only

    Why the group is in this state, in a sentence — including, when it is ACTIVE and holding steady, why it is not scaling. A customer asking "why do I have three servers" should be able to read the answer.

  • errorStatusOutput only
  • current_sizeint32Output only

    Members that exist right now, in any state.

  • desired_sizeint32Output only

    Members the last pass decided there should be.

    Differs from current_size while a member is booting or draining, which is most of the time a group is doing anything.

  • labelsmap<string, string>
  • create_timeTimestampOutput only
  • update_timeTimestampOutput only
  • last_scale_out_timeTimestampOutput only

    When the group last grew. What the scale-out cooldown is measured from.

  • vpcstringImmutable

    The private network every member is on, and the warm-up server before them. Empty is the project's default network in the group's region.

    On the group rather than on each member because a member is the group's to create: two members on different networks would be one fleet that cannot reach itself. Requires vpc.vpcs.use on the network. Immutable, for the reason GameServer.vpc is.

  • network_tagsrepeated string

    Network tags on every member's interface, and the warm-up's, which firewall rules on the group's network can target. Lowercase letters, digits and hyphens.

  • etagstringOutput only
  • managed_bystringOutput only

    The product that created and owns this group, if it was not you.

    See GameServer.managed_by: the same meaning, and the same refusal of your own update or delete. Its members carry it too.

  • pending_buildstringOutput only

    A build the group is baking and will roll onto when the capture lands.

    Empty when the group is on the build it was asked for.

  • How members are replaced when build changes.

    Show child attributes
    • STRATEGY_ROLLING_UPDATESTRATEGY_RECREATE
    • max_surgeint32

      Members above the desired size a rolling update may create, as a count or as a percentage of the desired size. The larger of the two when both are set; 25% when neither is.

    • max_surge_percentint32
    • max_unavailableint32

      Members below the desired size a rolling update may leave the group at, as a count or a percentage. 25% when neither is set.

    • max_unavailable_percentint32
  • sleep_after_idleDuration

    Put members to sleep after this long with nobody on them. See GameServer.sleep_after_idle, which every member is created with.

    A sleeping member still counts toward the group's size and, if the game said it is READY, toward its buffer: it can be allocated or connected to, and either wakes it. That is the point of keeping it rather than removing it. Refused on an ephemeral group, whose members cannot hibernate.

  • member_labelsmap<string, string>

    Labels every member carries, and what an allocation selects on.

    Not labels, which describe the group itself. Changing these reaches members created afterwards; existing members keep what they were created with, as a pod keeps its labels when a template changes.

  • outdated_sizeint32Output only

    Members running a build other than build, while a rollout replaces them.

  • ready_sizeint32Output only

    Members whose game has said READY, awake or asleep.

  • allocated_sizeint32Output only

    Members whose game is ALLOCATED or RESERVED.

  • sleeping_sizeint32Output only

    Members asleep.

  • pending_gamestringOutput only

    A game the group is baking and will roll onto with pending_build.

    Only a managed group moves its game: an Agones template change alters the runtime (the command, the environment, the ports) as well as the image, and a runtime lives on a game. A customer's group keeps its game for life.

GameServerSchematic

GameServerSchematic is a game server captured as a fast-start template.

A server is started, left to install its build and generate its world, and its disk is captured — so every server started from it skips the download, the install and the world generation. For a modded server that is the difference between minutes and tens of seconds.

A schematic is stored, so it is billed. It is charged per GiB-hour from the moment the capture completes until you delete it, whether or not anything starts from it.

  • namestringIdentifier
  • display_namestring
  • gamestringOutput only

    The game this was captured from, so a schematic can be offered for the game it actually fits. Starting a Minecraft server from a captured Garry's Mod disk is not a thing anybody means to do.

  • buildstringOutput only

    The build that was installed when the capture was taken.

    A schematic pins what it contains: the disk holds one build's files, and a game whose build has since moved on cannot be started from this.

  • source_game_serverstringOutput only

    The server it was captured from. Retained after that server is deleted, which is the ordinary case — provenance rather than a reference.

  • STATE_PENDINGSTATE_READYSTATE_FAILEDSTATE_DELETING
  • errorStatusOutput only
  • size_bytesint64Output only

    Size of the captured disk. What storage is billed on.

  • labelsmap<string, string>
  • create_timeTimestampOutput only
  • ready_timeTimestampOutput only

    When the capture completed and storage began accruing.

  • etagstringOutput only

ListGameServerGroupsResponse

  • game_server_groupsrepeated GameServerGroup
    Show child attributes
    • gamestringRequired

      The game every member runs.

    • policyScalingPolicyRequired
      Show child attributes
      • max_sizeint32Required
      • min_sizeint32

        Members never to go below, and never to go above.

        A minimum of zero is legitimate and is what a group for an off-peak game wants: no players, no servers, no bill. The first player then pays a boot, which is what the schematic is for.

      • target_player_percentdouble

        Hold members at this fraction of their player capacity. 1..100.

        The headline signal for a minigame: "keep servers 70% full" is the sentence a customer says. Needs the game to declare how many players a server holds; without that this term sits out rather than guessing.

      • min_free_player_slotsint32

        Keep at least this many player slots free across the whole group, so a party arriving together finds room without waiting for a boot.

        Additive to the percentage rather than an alternative — they answer different questions, and a group that sets both gets whichever needs more.

      • scale_on_waiting_connectionsbool

        Add members when connections are open against servers nobody is playing on.

        The only leading signal available: every other term here reacts to load that has already landed, and this one is somebody who could not get in. It needs no capacity and no sample, so it works for a game the platform knows nothing about.

      • target_cpu_percentdouble

        Hold the group's mean CPU at this percentage of each member's allocation. 1..100.

      • scale_out_cooldownDuration

        How long after growing before the group may grow again.

        A member takes tens of seconds to accept its first player, and every pass inside that window sees the same load on the same members. Without this a group creates one member per pass until the first finishes booting.

      • scale_in_patienceDuration

        How long a member must have been empty before it may be removed.

        Longer than the cooldown by default and by intent. Scaling in on a momentary zero is the failure that matters here: presence is derived from the game's own log lines, which can be late or missed, so a server between two rounds reads as empty for a few seconds. Growing late is a queue; shrinking early is a disconnection, and only the first is fixed by waiting.

      • max_scale_out_batchint32

        Most members to add or remove in one pass.

      • max_scale_in_batchint32
      • drain_timeoutDuration

        How long a drained member is given to empty before it is removed anyway.

        A drain is not a disconnection: the member stops being sent new players and keeps the ones it has. Somebody who never leaves would otherwise hold a member forever, so there is a deadline — long enough that a match finishes inside it.

      • buffer_sizeint32

        Keep this many members READY and unallocated, on top of those allocated.

        Agones' FleetAutoscaler buffer, and the shape a lobby needs: "always two servers accepting players, however many are mid-match". Reads the SDK state the game reports, so it needs a game that calls Ready() and Allocate() — for one that does not, every member is unallocated and the term asks only for the buffer itself.

        A sleeping READY member counts: it can be allocated. That is what makes a buffer cheap while nobody plays.

        Combined with the other terms by maximum, like all of them, and bounded by min_size and max_size.

      • buffer_percentdouble

        The buffer as a percentage of the group's size. 1..100. The larger of this and buffer_size when both are set.

    • namestringIdentifier

      projects/{p}/locations/{l}/gameServerGroups/{g}.

    • display_namestring
    • buildstring

      The build every member runs.

      Pinned like a game server's, and for a stronger reason: members are created and destroyed continuously, so a group that resolved the game's current build per member would put two versions of a customer's game in one fleet, with players matched across them by accident.

      Updatable, and changing it is a rollout, never a mixture by accident. The group goes on creating members on the old build while a warm-up bakes the new one (pending_build), switches when the capture lands, and then replaces outdated members within rollout — never one the game has marked ALLOCATED, which is somebody's match and finishes on the build it started on.

    • settingsmap<string, string>

      Settings handed to every member, exactly as GameServer.settings.

    • resourcesResourceRequirementsOutput only

      What each member gets. Uniform across the fleet by construction.

      Output only: resolved from machine_type and the game's disk, exactly as GameServer.resources is.

      Show child attributes
    • machine_typestring

      The machine type every member runs at, as GameServer.machine_type. Empty takes the smallest type that meets the game's minimum.

      Updatable, and a change reaches a member the next time it starts; it is not a rollout, because a size is not what a match is played on.

    • Run members on spot capacity, as GameServer.spot. Pro plan only.

      A fleet is where spot is most useful — a minigame server reclaimed between rounds costs nobody anything — and it composes with scaling in one way worth knowing: a reclaimed member counts as not running, so a group that needs it creates or starts another. With on_demand_fallback that one is on demand when spot has nothing free, which is what keeps a fleet at size while the region is busy.

      Show child attributes
      • enabledbool

        Run on spot capacity.

      • on_demand_fallbackbool

        Start on demand, at the on-demand rate, when no spot capacity is free.

        Without it a start with no spot capacity waits for some and fails after a minute, which is right for a server that is only worth running cheaply and wrong for one players are waiting on. A server that fell back stays on demand until it next stops; SpotStatus.running_on_spot says which it is.

      • notice_signalstring

        A signal to send the game's process when a notice arrives, e.g. SIGUSR1.

        Empty sends nothing, and that is the default for a reason: the default action of most signals is to terminate, so a signal a game does not handle would stop it two minutes early. Name one only when the game handles it. SIGTERM and SIGKILL are refused — the stop that follows the notice sends the game's own stop signal already.

    • ephemeralbool

      Whether members keep their data.

      Almost always true for the workload a group is for: a match has nothing worth carrying into the next one, and a member that hibernated would write its whole RAM to object storage on the way out of a world nobody will read.

      It also changes what scaling in means. An ephemeral member is deleted when it is drained; a durable one is stopped, keeps its disks, and is started again when the group grows.

    • exposureExposure

      Whether players can reach members directly.

      PROJECT_INTERNAL is the right default for a scaled fleet and the reason the field exists: members behind a matchmaker or a lobby are dialled from inside the project, and giving each one a public listener would be an entry point nobody intended and a proxy charge per member. The choice is the customer's, because a fleet of servers players do pick from a list is just as real a shape.

      EXPOSURE_PUBLICEXPOSURE_PROJECT_INTERNAL
    • warmup_durationDuration

      How long a warm-up server runs before it is captured as the schematic.

      The one number that decides how fast this group scales. A member started from a schematic skips the download, the install and the world generation — seconds instead of minutes — and what makes the schematic worth having is that the capture happened after all of that finished.

      So this is "how long does your game take to be ready to play", and getting it wrong is visible in one direction only: too long wastes a few minutes once, and too short captures a server mid-install, which every member then starts from.

      Zero skips the warm-up entirely and members boot cold. That is the right choice for a game that starts in seconds anyway, and the only choice for one whose first run must not be cloned.

    • schematicstring

      The schematic members are started from.

      Set by the group when its warm-up capture lands, or supplied at creation to reuse one that already exists — which is the faster path and the one a customer takes for their second group of the same game.

      Empty means members boot cold, which is correct rather than broken: a group whose capture failed still scales, just slowly, and stopping it from scaling would turn a performance problem into an outage.

    • stateGameServerGroup.StateOutput only
      STATE_WARMING_UPSTATE_ACTIVESTATE_PAUSEDSTATE_FAILEDSTATE_DELETING
    • state_messagestringOutput only

      Why the group is in this state, in a sentence — including, when it is ACTIVE and holding steady, why it is not scaling. A customer asking "why do I have three servers" should be able to read the answer.

    • errorStatusOutput only
    • current_sizeint32Output only

      Members that exist right now, in any state.

    • desired_sizeint32Output only

      Members the last pass decided there should be.

      Differs from current_size while a member is booting or draining, which is most of the time a group is doing anything.

    • labelsmap<string, string>
    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • last_scale_out_timeTimestampOutput only

      When the group last grew. What the scale-out cooldown is measured from.

    • vpcstringImmutable

      The private network every member is on, and the warm-up server before them. Empty is the project's default network in the group's region.

      On the group rather than on each member because a member is the group's to create: two members on different networks would be one fleet that cannot reach itself. Requires vpc.vpcs.use on the network. Immutable, for the reason GameServer.vpc is.

    • network_tagsrepeated string

      Network tags on every member's interface, and the warm-up's, which firewall rules on the group's network can target. Lowercase letters, digits and hyphens.

    • etagstringOutput only
    • managed_bystringOutput only

      The product that created and owns this group, if it was not you.

      See GameServer.managed_by: the same meaning, and the same refusal of your own update or delete. Its members carry it too.

    • pending_buildstringOutput only

      A build the group is baking and will roll onto when the capture lands.

      Empty when the group is on the build it was asked for.

    • How members are replaced when build changes.

      Show child attributes
      • STRATEGY_ROLLING_UPDATESTRATEGY_RECREATE
      • max_surgeint32

        Members above the desired size a rolling update may create, as a count or as a percentage of the desired size. The larger of the two when both are set; 25% when neither is.

      • max_surge_percentint32
      • max_unavailableint32

        Members below the desired size a rolling update may leave the group at, as a count or a percentage. 25% when neither is set.

      • max_unavailable_percentint32
    • sleep_after_idleDuration

      Put members to sleep after this long with nobody on them. See GameServer.sleep_after_idle, which every member is created with.

      A sleeping member still counts toward the group's size and, if the game said it is READY, toward its buffer: it can be allocated or connected to, and either wakes it. That is the point of keeping it rather than removing it. Refused on an ephemeral group, whose members cannot hibernate.

    • member_labelsmap<string, string>

      Labels every member carries, and what an allocation selects on.

      Not labels, which describe the group itself. Changing these reaches members created afterwards; existing members keep what they were created with, as a pod keeps its labels when a template changes.

    • outdated_sizeint32Output only

      Members running a build other than build, while a rollout replaces them.

    • ready_sizeint32Output only

      Members whose game has said READY, awake or asleep.

    • allocated_sizeint32Output only

      Members whose game is ALLOCATED or RESERVED.

    • sleeping_sizeint32Output only

      Members asleep.

    • pending_gamestringOutput only

      A game the group is baking and will roll onto with pending_build.

      Only a managed group moves its game: an Agones template change alters the runtime (the command, the environment, the ports) as well as the image, and a runtime lives on a game. A customer's group keeps its game for life.

  • next_page_tokenstring

ListGameServerSchematicsResponse

  • Show child attributes
    • namestringIdentifier
    • display_namestring
    • gamestringOutput only

      The game this was captured from, so a schematic can be offered for the game it actually fits. Starting a Minecraft server from a captured Garry's Mod disk is not a thing anybody means to do.

    • buildstringOutput only

      The build that was installed when the capture was taken.

      A schematic pins what it contains: the disk holds one build's files, and a game whose build has since moved on cannot be started from this.

    • source_game_serverstringOutput only

      The server it was captured from. Retained after that server is deleted, which is the ordinary case — provenance rather than a reference.

    • STATE_PENDINGSTATE_READYSTATE_FAILEDSTATE_DELETING
    • errorStatusOutput only
    • size_bytesint64Output only

      Size of the captured disk. What storage is billed on.

    • labelsmap<string, string>
    • create_timeTimestampOutput only
    • ready_timeTimestampOutput only

      When the capture completed and storage began accruing.

    • etagstringOutput only
  • next_page_tokenstring

ListGameServersResponse

  • Show child attributes
    • gamestringRequired

      The game to run. Must be launchable — a branch node has no build.

    • namestringIdentifier

      projects/{project}/locations/{location}/gameServers/{game_server}.

      Project- and region-scoped, like every resource that consumes capacity: it runs somewhere specific, and it is billed to the project that owns it.

    • display_namestring
    • buildstringOutput only

      Resolved at create time and never re-resolved.

      A game's build moves on; a running server's must not. Pinning it here means an update to "Minecraft Forge 1.20.4" cannot silently change what a customer's server is running under their players' feet.

    • settingsmap<string, string>

      Overrides for the game's declared settings, by key.

    • resourcesResourceRequirementsOutput only

      What the server runs with: the machine type's vCPUs and memory, and the game's declared disk.

      Output only. A size is chosen by naming a machine_type; this field used to take any vCPU count and any amount of memory, and a create or update that sets it is refused with a pointer to machine_type. See MachineType for why sizes are named now.

      Show child attributes
    • machine_typestring

      The size to run at, by machine type id — standard-4, highmem-2.

      Empty takes the smallest type that meets the game's own declared minimum, and a type below that minimum is refused, because a server too small for its game boots, installs, and is killed for memory at the first player. ListMachineTypes is the catalogue. Changing it takes effect on the next start.

    • Run on spare capacity at a discount, and accept being reclaimed with two minutes' notice. Pro plan only. See SpotConfig.

      Changing it takes effect on the next start.

      Show child attributes
      • enabledbool

        Run on spot capacity.

      • on_demand_fallbackbool

        Start on demand, at the on-demand rate, when no spot capacity is free.

        Without it a start with no spot capacity waits for some and fails after a minute, which is right for a server that is only worth running cheaply and wrong for one players are waiting on. A server that fell back stays on demand until it next stops; SpotStatus.running_on_spot says which it is.

      • notice_signalstring

        A signal to send the game's process when a notice arrives, e.g. SIGUSR1.

        Empty sends nothing, and that is the default for a reason: the default action of most signals is to terminate, so a signal a game does not handle would stop it two minutes early. Name one only when the game handles it. SIGTERM and SIGKILL are refused — the stop that follows the notice sends the game's own stop signal already.

    • spot_statusSpotStatusOutput only

      What spot is doing for this server right now.

      Show child attributes
      • running_on_spotboolOutput only

        Whether the current run is on spot capacity. False for a server that fell back to on demand, and for one that is not running.

      • termination_timeTimestampOutput only

        When the current run will be stopped, once a notice has been given.

      • last_reclaim_timeTimestampOutput only

        When this server was last reclaimed.

      • preserving_diskboolOutput only

        Whether the disk of a reclaimed server is still being captured. A start is refused as retryable until it finishes, because starting before it would boot a server without its world.

      • noticeDurationOutput only

        How long the notice was, for a console that wants to draw a countdown.

    • stateGameServer.StateOutput only
      STATE_PROVISIONINGSTATE_STARTINGSTATE_RUNNINGSTATE_STOPPEDSTATE_STOPPINGSTATE_FAILEDSTATE_DELETING
    • state_messagestringOutput only
    • errorStatusOutput only
    • endpointsrepeated EndpointOutput only

      How to reach it. Empty until the server is running and has an address.

      A port may appear twice: once as Plany's proxy and once as the server's own address, distinguished by proxied. Give players the proxied one: it is reachable while the server is stopped, and connecting to it starts the server.

      Proxied entries come first, so endpoints[0] is the address to hand out.

      Show child attributes
      • namestring

        Matches the game's plany.game.v1.PortMapping name, e.g. "game".

      • hoststring
      • portint32
      • protocolstring

        "tcp" or "udp".

      • addressstring

        Ready-to-paste form, e.g. "play.example.com:25565". Populated because every console and support conversation ends up building this string anyway, and building it in one place avoids three subtly different ones.

      • proxiedbool

        Whether this address is Plany's proxy rather than the server itself.

        A proxied address is reachable while the server is stopped or asleep, and connecting to it starts the server — so it is the one to give to players. A player's first connection after a sleep waits a few seconds while the server comes back.

    • instancestringOutput only

      An identifier Plany support may ask for when investigating a server. Output only; nothing in the API acts on it.

    • labelsmap<string, string>
    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • last_active_timeTimestampOutput only

      When it last had a player. Drives idle shutdown, and is the field activity billing will read.

    • service_accountstring

      The identity this server acts as.

      Leave it empty and Playpute creates one per server, allowed to touch this server and nothing else — the right default, since a server runs your players' mods.

      Set it to a service account you own and the server acts as that instead. That is for a fleet: grant one service account a role elsewhere, attach it to twenty servers, and those twenty can use it while the rest of the account cannot.

      Attaching one requires iam.serviceAccounts.actAs on that service account, not merely permission to create a server — otherwise anybody who could create a server could act as anybody.

    • ssh_public_keysrepeated stringInput only

      SSH keys allowed to log in to this server, for debugging.

      They take effect only on a server booted from an image that includes an SSH server, and are read when the server boots, so a key added later needs a restart. Input only: the keys are not returned when the server is read.

    • imagestringInput only

      The image to boot, by id. Empty uses Plany's current default, which is what almost every server should do.

      An id from Plany's own published images; a server cannot boot an image of your own.

    • ephemeralbool

      Keep nothing. The world and the disks go when the server does.

      The right shape for a match rather than a world: a minigame round has nothing worth carrying into the next one, and an ephemeral server saves the storage and the time of keeping it.

      An ephemeral server never sleeps, because there is nothing to wake into, so sleep_after_idle is refused on one.

      Immutable after creation: the guarantee is about data that was never kept, so it cannot be turned off afterwards.

    • exposureExposure

      Whether players outside the project can reach this server.

      Immutable after creation: it decides whether a listener and a public address exist at all, and flipping it on a running server would change the address players were given.

      EXPOSURE_PUBLICEXPOSURE_PROJECT_INTERNAL
    • schematicstring

      The schematic this server's disk was copied from, if any.

      What makes a scaled fleet viable: the build is already unpacked, the install script has already run and the world already exists, so a member reaches RUNNING in seconds where a cold boot is minutes.

      A copy, not an attachment. The schematic is read once into a fresh disk and never referenced again, which is why deleting one does not disturb a server started from it — and why two members from one schematic diverge immediately rather than sharing anything.

    • groupstringOutput only

      The group that created and owns this server, if any.

      Output-only and not settable: a server does not join a group, a group creates it. The distinction matters because the group's loop deletes what it owns, and a server that could name a group it was not created by would be a way to have somebody else'"'"'s fleet delete your server.

      A member deleted by hand comes back. Its size is the group'"'"'s to decide, so removing one is a decision the next pass overrules.

    • drainingboolOutput only

      Whether this server is draining: serving the players it has and being sent no new ones, on its way out.

      Its own field rather than a state, because a draining server is still RUNNING in every way that matters — it holds players, it bills, it serves. Folding it into state would make every consumer that switches on state handle a case that behaves identically to RUNNING, and the one that forgot would stop showing a server people are on.

    • Secrets this server can read: database passwords, API keys, RCON passwords, a licence key a game wants in a file.

      Each attachment names a secret in the same project and region and says how the server sees it. The value is never stored on the server's configuration — the server fetches it when it starts, as its own identity — so nothing you can read back from the server reveals it.

      Changing this takes effect on the next start. A running server keeps what it read when it started.

      Show child attributes
      • secretstringRequired

        projects/{project}/locations/{location}/secrets/{secret}, optionally with /versions/{version}.

        Unqualified is the ordinary case and resolves to the latest enabled version, so a rotation reaches this server on its next start with nothing to edit. Pin a version when a server must not follow a rotation — which is rare, and worth being deliberate about, because the pin outlives the memory of why it was made.

      • environment_variablestringRequired

        The environment variable the server sees the secret as, e.g. RCON_PASSWORD.

        Required, and must be a valid variable name — upper case letters, digits and underscores, not starting with a digit. It is not derived from the secret's id, because stripe-live-key is not a variable name.

        The value has to be valid UTF-8 to be used this way. A secret holding binary data is refused when the server starts; use file_path for one.

      • file_pathstring

        Also write the value to a file at this path, relative to the build root.

        For the things that will not go in an environment variable: a service account JSON, a TLS key, a licence file a game reads by path. Optional, and when it is set the environment variable is still exported, because a value that is available two ways is easier to use than one with a rule about when it is which.

        Written 0600 and owned by the game user, and deliberately not preserved across restarts the way a plany.game.v1.ConfigFile can be: this is the platform's copy of a value the platform holds, so the file is rewritten every launch and a rotation cannot leave a stale one behind.

    • sdkSdkStatusOutput only

      What the game has told the platform about itself through the Agones SDK.

      Every game server runs the SDK server, whether or not it came from an Agones manifest, so a customer's own game can call Ready() and Allocate() the way an Agones game does. A game that never calls it has an empty sdk, and nothing reads one: allocation, the buffer term and idle sleep all treat an unset state as "not using the SDK" rather than as not ready.

      Separate from state for the reason activity is. state is what the machine is doing and the platform decides it; this is what the game says it is doing, and a RUNNING server is READY, ALLOCATED or neither.

      Show child attributes
      • stateSdkStatus.StateOutput only
        STATE_READYSTATE_ALLOCATEDSTATE_RESERVEDSTATE_SHUTDOWNSTATE_UNHEALTHY
      • labelsmap<string, string>Output only

        Labels and annotations the game and its allocations wrote.

        SetLabel("mode", "ranked") is stored as agones.dev/sdk-mode, which is Agones' own prefix and what a selector written for Agones asks for. An allocation's metadata is stored as given. Kept apart from GameServer.labels, which the customer or the manifest owns: a game writing its own labels must not be able to rewrite the ones its fleet selects on.

      • annotationsmap<string, string>Output only
      • reserved_untilTimestampOutput only

        When a RESERVED server returns to READY.

      • allocate_timeTimestampOutput only

        When it was last allocated.

      • health_timeTimestampOutput only

        When the game last sent Health().

      • versionint64Output only

        Increases on every change. Reported to the game as the Agones resource_version.

      • update_timeTimestampOutput only
    • sleep_after_idleDuration

      Put the server to sleep after this long with nobody on it.

      Sleep is hibernation: the server's memory is captured, its host released, and the next player's connection — or an allocation — restores it in seconds with everything it held in memory. Compute is not charged while it sleeps.

      The counterpart of idle_shutdown_minutes, and different in the one way that matters: that stops a server a customer forgot about, and this is the platform doing what "pay when played" means for a server somebody wants kept ready. A server the game has marked ALLOCATED or RESERVED never sleeps, because it is somebody's match.

      Idle is measured from the connection proxy's view of the server — no connections and no players — and a server whose presence could not be read is not idle. Refused on an ephemeral server, which cannot hibernate. Zero keeps it awake.

    • managed_bystringOutput only

      The product that created and owns this server, if it was not you.

      autopilot.agones.plany.cloud for a server Agones Autopilot created from a manifest. Change such a server by changing the manifest: Playpute's own update and delete refuse it.

    • install_complete_timeTimestampOutput only

      When the server finished installing its build — for a container build, the image pulled and unpacked; for any other, the build downloaded and its install script run.

    • vpcstringImmutable

      The private network this server is on. Empty is the project's default network in the server's region.

      Decided by the server, never by its game: a game is a catalogue entry shared by every project that runs it, and a network written there would be one project's network named in everybody's servers. Requires vpc.vpcs.use on the network, which must be in the server's own project and region.

      Immutable. A server that changed network would change address under the players connected to it, and the connection proxy in front of it is the proxy for that network — players reach a server through the proxy on the network it is on, so each network a project uses has a proxy of its own.

    • network_tagsrepeated string

      Network tags on this server's interface, which firewall rules on its network can target. Lowercase letters, digits and hyphens.

    • etagstringOutput only
  • next_page_tokenstring

ListMachineTypesResponse

  • Every type, smallest first. The catalogue is short, so it is not paged.

    Show child attributes
    • namestringIdentifier

      projects/{project}/locations/{location}/machineTypes/{machine_type}.

      The last segment — standard-4 — is what a GameServer names in machine_type. Scoped under a project and a region only so that reading it is authorized like everything else a customer reads here; the catalogue itself does not vary by project.

    • display_namestringOutput only

      Human-readable, e.g. "Standard, 4 vCPU".

    • familystringOutput only

      The family: standard (2 GiB per vCPU) or highmem (4 GiB per vCPU).

    • vcpusint32Output only
    • memory_bytesint64Output only
    • spotSpotAvailabilityOutput only

      Spot capacity for this type in this region, right now and recently.

      Show child attributes
      • available_nowbool

        Whether a spot server of this type could be placed right now.

        A reading, not a promise: spare capacity is whatever on-demand servers are not using, and the next on-demand create may take it.

      • availability_7ddouble

        The fraction of the last seven days in which a spot server of this type could have been placed, 0 to 1.

      • reclaims_per_day_7ddouble

        How often a running spot server of this type was reclaimed over the last seven days, as reclaims per server-day. 0.1 means one reclaim every ten days of running, on average.

      • sample_timeTimestamp

        When the record was last sampled. Unset when this region has never recorded anything for the type — which is not the same as zero availability, and a console must not draw it as such.

ListProxyRoutesResponse

  • Show child attributes
    • namestringIdentifier

      projects/{p}/locations/{l}/gameServers/{s}/proxyRoutes/{port_name}.

      The last segment is the game's own port name — "game", "query" — rather than a generated id, so a route is addressable from the thing that produced it and a re-allocation cannot leave two routes for one port.

    • game_serverstringOutput only
    • gamestringOutput only

      The game being served.

    • port_namestringOutput only

      The game's plany.game.v1.PortMapping name this route fronts, e.g. "game".

    • listen_hoststringOutput only

      Where the proxy listens, and what players are told to connect to.

    • listen_portint32Output only
    • protocolstringOutput only

      "tcp" or "udp". A game declaring both gets two routes: they are two listeners on two sockets, and a UDP session has no relationship to a TCP connection on the same number.

    • target_portint32Output only

      The port the game listens on inside the server. Not the port the proxy listens on: a shared address cannot give every server 25565, so the two differ and the proxy translates.

    • billableboolOutput only

      Whether this route is charged for.

      False for a game Plany publishes, true for a customer's own. Waking a Minecraft server costs Plany the same either way; the difference is what the platform is selling. A pre-configured game is the product, and its proxy is part of the price of the server. A customer's own game is a platform capability being used to host something Plany did not build, and charging for it is what stops the listener pool being free infrastructure for arbitrary traffic.

    • proxystringOutput only

      The connection proxy this route is a listener on.

      Every route on one network shares one, and it is what listen_port is unique within — which is why two projects, or two networks of one project, can both use 25565.

    • create_timeTimestampOutput only
  • next_page_tokenstring

MachineType

MachineType is a named size a game server runs at.

Sizes are named so that spot capacity has a history you can read: QuerySpotHistory can tell you that standard-4 was available 99% of last week and was reclaimed twice. The catalogue is the same in every project and region; this resource is that list with a region's spot record beside each entry.

A game's own resources are a minimum

A game still declares the resources it needs, and that is the floor a type must meet. A server that names no type gets the smallest one that meets it — so you never have to know what a game needs to create one.

  • namestringIdentifier

    projects/{project}/locations/{location}/machineTypes/{machine_type}.

    The last segment — standard-4 — is what a GameServer names in machine_type. Scoped under a project and a region only so that reading it is authorized like everything else a customer reads here; the catalogue itself does not vary by project.

  • display_namestringOutput only

    Human-readable, e.g. "Standard, 4 vCPU".

  • familystringOutput only

    The family: standard (2 GiB per vCPU) or highmem (4 GiB per vCPU).

  • vcpusint32Output only
  • memory_bytesint64Output only
  • spotSpotAvailabilityOutput only

    Spot capacity for this type in this region, right now and recently.

    Show child attributes
    • available_nowbool

      Whether a spot server of this type could be placed right now.

      A reading, not a promise: spare capacity is whatever on-demand servers are not using, and the next on-demand create may take it.

    • availability_7ddouble

      The fraction of the last seven days in which a spot server of this type could have been placed, 0 to 1.

    • reclaims_per_day_7ddouble

      How often a running spot server of this type was reclaimed over the last seven days, as reclaims per server-day. 0.1 means one reclaim every ten days of running, on average.

    • sample_timeTimestamp

      When the record was last sampled. Unset when this region has never recorded anything for the type — which is not the same as zero availability, and a console must not draw it as such.

QuerySpotHistoryResponse

  • One point per hour, oldest first.

    Show child attributes
    • intervalInterval
    • availabilitydouble

      The fraction of this bucket in which a spot server of the type could have been placed. Unset (with measured false) for a bucket the platform took no samples in.

    • reclaimsint64

      Spot servers of this type reclaimed during the bucket.

    • running_hoursdouble

      Server-hours of spot running of this type during the bucket. What makes reclaims a rate rather than a count: two reclaims among two servers and two among two hundred are different records.

    • measuredbool

      Whether any sample landed in this bucket. A gap is "not measured", never "unavailable".

SdkStatus

SdkStatus is a game server's Agones SDK state.

  • stateSdkStatus.StateOutput only
    STATE_READYSTATE_ALLOCATEDSTATE_RESERVEDSTATE_SHUTDOWNSTATE_UNHEALTHY
  • labelsmap<string, string>Output only

    Labels and annotations the game and its allocations wrote.

    SetLabel("mode", "ranked") is stored as agones.dev/sdk-mode, which is Agones' own prefix and what a selector written for Agones asks for. An allocation's metadata is stored as given. Kept apart from GameServer.labels, which the customer or the manifest owns: a game writing its own labels must not be able to rewrite the ones its fleet selects on.

  • annotationsmap<string, string>Output only
  • reserved_untilTimestampOutput only

    When a RESERVED server returns to READY.

  • allocate_timeTimestampOutput only

    When it was last allocated.

  • health_timeTimestampOutput only

    When the game last sent Health().

  • versionint64Output only

    Increases on every change. Reported to the game as the Agones resource_version.

  • update_timeTimestampOutput only

WakeGameServerResponse

  • The server's state after this call. STARTING means a start was issued or was already under way.

    STATE_PROVISIONINGSTATE_STARTINGSTATE_RUNNINGSTATE_STOPPEDSTATE_STOPPINGSTATE_FAILEDSTATE_DELETING
  • readybool

    Whether upstream can be connected to now.

    Distinct from state == RUNNING: a server is RUNNING before the game inside it is listening. A hint that saves a connection attempt rather than a promise.

  • upstreamEndpoint

    Where to forward, once ready: the server's own address, not the proxy's.

    Show child attributes
    • namestring

      Matches the game's plany.game.v1.PortMapping name, e.g. "game".

    • hoststring
    • portint32
    • protocolstring

      "tcp" or "udp".

    • addressstring

      Ready-to-paste form, e.g. "play.example.com:25565". Populated because every console and support conversation ends up building this string anyway, and building it in one place avoids three subtly different ones.

    • proxiedbool

      Whether this address is Plany's proxy rather than the server itself.

      A proxied address is reachable while the server is stopped or asleep, and connecting to it starts the server — so it is the one to give to players. A player's first connection after a sleep waits a few seconds while the server comes back.

  • retry_afterDuration

    How long to wait before asking again. Zero means the caller may retry immediately.

Enums

AllocateGameServerRequest.Scheduling

Which of several matching servers to choose.

ValueDescription
SCHEDULING_UNSPECIFIEDPACKED.
SCHEDULING_PACKEDThe oldest matching server, so a fleet empties from its newest members and scale-in has something to remove. Agones' default.
SCHEDULING_DISTRIBUTEDAny matching server, spread across the fleet.

Exposure

Exposure says who can reach a game server.

The distinction exists for fleets that are fronted by something else — a lobby, a matchmaker, a game's own directory service. Those want servers players never dial directly, and giving each one a listener anyway would be a public entry point nobody intended and a charge for a route nobody uses.

ValueDescription
EXPOSURE_UNSPECIFIEDPublic, which is what an ordinary game server is.
EXPOSURE_PUBLICReachable by players. A listener is held open on the project's connection proxy for every public port the game declares, and that address is what the server advertises and what players are given.
EXPOSURE_PROJECT_INTERNALReachable only from inside the project's own network. No public address: the server is reached at its private address by something already on that network — another game server, or a matchmaker of your own. **A server nothing outside can reach cannot be woken by a player connecting**, so an internal server is started by whatever directs traffic to it.

GameServer.State

ValueDescription
STATE_UNSPECIFIED
STATE_PROVISIONINGAccepted, and the server is being placed and started.
STATE_STARTINGBooted; the game's install and launch are running.
STATE_RUNNINGAccepting players.
STATE_STOPPEDDeliberately stopped. The world is retained and nothing is billed for compute; storage still is.
STATE_STOPPINGStopping.
STATE_FAILEDSomething failed. `error` says what.
STATE_DELETINGBeing torn down.

GameServerGroup.State

ValueDescription
STATE_UNSPECIFIED
STATE_WARMING_UPAccepted, and the warm-up server is being created and captured. Members are not created yet — the whole point of the schematic is that the first member starts from it.
STATE_ACTIVEScaling. The ordinary state, whatever the current size is, including zero: a group holding no members because nobody is playing is working, not idle.
STATE_PAUSEDScaling suspended by the customer. Members keep running and keep serving players; nothing is created and nothing is removed. Deliberately not "stopped": a paused group that tore its members down would be a way to disconnect everybody by asking to stop *changing* things.
STATE_FAILEDSomething failed that scaling cannot fix. `error` says what.
STATE_DELETINGBeing torn down, members first.

GameServerSchematic.State

ValueDescription
STATE_UNSPECIFIED
STATE_PENDINGThe host is capturing the disk. Minutes, for a server with a world.
STATE_READYCaptured and startable.
STATE_FAILEDThe capture failed. `error` says why.
STATE_DELETINGBeing removed.

LabelRequirement.Operator

ValueDescription
OPERATOR_UNSPECIFIED
OPERATOR_IN
OPERATOR_NOT_IN
OPERATOR_EXISTS
OPERATOR_DOES_NOT_EXIST

RolloutPolicy.Strategy

ValueDescription
STRATEGY_UNSPECIFIEDROLLING_UPDATE.
STRATEGY_ROLLING_UPDATEReplace outdated members a few at a time, creating before removing.
STRATEGY_RECREATERemove every outdated member that is not allocated at once, then create. Faster, and a group with no spare capacity for a while.

SdkStatus.State

The states a game moves itself through, named as Agones names them.

Only the ones a game causes. Agones' Creating, Starting and Scheduled are the machine's business and are GameServer.state here; Error is GameServer.error.

ValueDescription
STATE_UNSPECIFIEDThe game has not called the SDK. Not "not ready": a game that does not use the SDK is left entirely alone by everything that reads this.
STATE_READY`Ready()`: may be handed to a match.
STATE_ALLOCATEDHanded to a match, by an allocation or by the game's own `Allocate()`. Never scaled in, never put to sleep, never re-allocated unless a selector asks for allocated servers.
STATE_RESERVED`Reserve(d)`: held back from allocation and from scale-in until `reserved_until`, then READY again.
STATE_SHUTDOWN`Shutdown()`: finished. A group member is deleted and replaced; a server on its own is deleted.
STATE_UNHEALTHYStopped sending `Health()`. A group member is deleted and replaced.