Skip to main content
The Server Browser API provides endpoints for discovering, filtering, and managing game servers. This API powers the server browser in the Kyber Launcher and handles server registration, updates, and player join validation.

Overview

Server hosts register their game servers with the API, and players use the server browser to discover and join available servers. The API handles server validation, mod compatibility checking, and real-time server status updates.
Most endpoints require authentication. Server registration and updates require the server to be owned by the authenticated user.

Core Methods

GetServers

Retrieve a list of all public servers. Endpoint: ServerBrowserServer.GetServers Request:
request
ServerListRequest
Empty request object
Response:
servers
Server[]
required
Array of public server objects with current status, player counts, maps, and mods
Implementation:
source/API/internal/rpc/server_browser.go:282-303
func (s *ServerBrowserServer) GetServers(ctx context.Context, _ *pbapi.ServerListRequest) (*pbapi.ServerList, error) {
	servers, err := s.store.Servers.GetPublic(ctx)
	if err != nil {
		logger.L().Error("Failed to get public servers", zap.Error(err))
		return nil, status.Error(codes.Internal, "Failed to get servers")
	}

	if servers == nil {
		return &pbapi.ServerList{
			Servers: []*pbapi.Server{},
		}, nil
	}

	cs := make([]*pbapi.Server, 0)
	for _, server := range servers {
		cs = append(cs, server.Proto())
	}

	return &pbapi.ServerList{
		Servers: cs,
	}, nil
}

GetServer

Retrieve detailed information about a specific server by ID. Endpoint: ServerBrowserServer.GetServer Request:
id
string
required
Server ID to retrieve
Response:
server
Server
required
Detailed server information including configuration, current map, players, and mods
Error Codes:
  • NOT_FOUND - Server with the specified ID does not exist
  • INTERNAL - Failed to retrieve server from database
Implementation:
source/API/internal/rpc/server_browser.go:305-317
func (s *ServerBrowserServer) GetServer(ctx context.Context, req *pbapi.ServerRequest) (*pbapi.Server, error) {
	server, err := s.store.Servers.GetByID(ctx, req.GetId())
	if err != nil {
		logger.L().Error("Failed to get server", zap.Error(err))
		return nil, status.Error(codes.Internal, "Failed to get server")
	}

	if server == nil {
		return nil, status.Error(codes.NotFound, "Server not found")
	}

	return server.Proto(), nil
}

RegisterServer

Register a new game server with the server browser. Endpoint: ServerBrowserServer.RegisterServer Request:
name
string
required
Server name (max 32 characters, profanity filtered)
description
string
Server description (max 128 characters, profanity filtered)
max_players
int32
required
Maximum number of players (1-64)
password
string
Optional server password for private servers
region
Region
required
Server region (NA_WEST, NA_EAST, EU_WEST, EU_CENTRAL, ASIA, OCEANIA)
mods
ModInfo[]
List of required mods with name and hash
tags
string[]
Server tags for filtering
Response:
id
string
required
Unique server ID
token
string
required
JWT token for server updates and authentication
Validation:
  • Server name and description are checked for profanity
  • Name must be 1-32 characters
  • Description must not exceed 128 characters
  • Max players must be between 1 and 64
  • User cannot have more than 10 active servers

UpdateServer

Update an existing server’s status, players, and current map. Endpoint: ServerBrowserServer.UpdateServer Request:
id
string
required
Server ID to update
current_players
int32
Current number of players
players
Player[]
List of connected players with names and IDs
current_map
LevelSetup
Current map and game mode information
next_map
LevelSetup
Next map in rotation
Authorization: User must be the owner of the server or have appropriate permissions. Implementation: Servers are automatically marked as stale and removed if they don’t send updates within 40 seconds. A background cleanup process runs every 10 seconds.

CanJoinServer

Validate whether a player can join a server based on mod compatibility and server status. Endpoint: ServerBrowserServer.CanJoinServer Request:
server_id
string
required
Server ID to validate
mods
ModInfo[]
Player’s installed mods
Response:
can_join
bool
required
Whether the player can join the server
reason
string
Reason for denial if can_join is false
missing_mods
ModInfo[]
Mods required by the server that the player doesn’t have
Validation Logic:
  • Checks if server exists and is not full
  • Validates mod compatibility (all required mods must be installed)
  • Returns list of missing mods for download

Mod Management

CheckModImages

Check which mod images need to be uploaded for proper server display. Endpoint: ServerBrowserServer.CheckModImages Request:
mods
ModImageMod[]
required
List of mods with names and hashes to check
Response:
missing
string[]
required
Array of mod hashes that don’t have images uploaded

UploadModImages

Upload preview images for mods to display in the server browser. Endpoint: ServerBrowserServer.UploadModImages Request:
images
ModImage[]
required
Array of mod images with hash and base64-encoded image data
Validation:
  • Images must be valid base64-encoded data
  • Supports jpg, jpeg, png, webp formats
  • Images are stored in S3/R2 for serving

Real-Time Updates

Server status updates are published to WebSocket clients for real-time server browser updates. Updates include:
  • Player count changes
  • Map rotations
  • Server online/offline status
  • New servers registered

Background Tasks

Stale Server Cleanup

A background process runs every 10 seconds to remove stale servers:
  • Servers that haven’t sent an update in 40 seconds are marked as stale
  • Stale servers are automatically removed from the browser
  • This ensures the browser only shows active servers
source/API/internal/rpc/server_browser.go:39-80
func (s *ServerBrowserServer) cleanupStaleServers() {
	for {
		ticker := time.NewTicker(10 * time.Second)
		defer ticker.Stop()

		for range ticker.C {
			cutoff := time.Now().Add(-40 * time.Second)
			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
			servers, err := s.store.Servers.GetWithCutoff(ctx, cutoff)
			// ... cleanup logic
		}
	}
}

Error Codes

  • INTERNAL - Database or internal server error
  • NOT_FOUND - Server ID not found
  • PERMISSION_DENIED - User doesn’t own the server
  • INVALID_ARGUMENT - Validation failed (profanity, invalid values)

Integration

Server Host Flow

  1. Register Server: Call RegisterServer() with server details
  2. Store Token: Save the returned JWT token for updates
  3. Send Updates: Call UpdateServer() every 30 seconds with current status
  4. Handle Shutdown: Server is automatically removed after 40 seconds without updates

Player Join Flow

  1. List Servers: Call GetServers() to get all available servers
  2. Filter/Search: Apply client-side filtering based on region, game mode, etc.
  3. Validate Join: Call CanJoinServer() to check mod compatibility
  4. Download Mods: If missing mods, prompt user to download
  5. Join Server: Connect to server using returned connection details

Server Management

Player management and moderation

VoIP

Voice chat integration for servers

Implementation Notes

  • Server IDs are UUID v4 strings
  • Servers are stored in MongoDB with real-time indexing
  • WebSocket connections receive real-time updates via RabbitMQ
  • Map images are fetched from S3/R2 CDN based on mod hashes
  • Profanity filtering uses the go-away library

Build docs developers (and LLMs) love