GOTURGAMESGet the launcher
Introducing the GoturGames launcher · One account, your games, automatic updates, and friends. Get the free desktop app ↗

GOTURGAMES / DEVELOPERS

Your game.
Connected.

Ship your game with one manifest. Give players a shared library, automatic updates, friends and private multiplayer lobbies.

Node.js / Unity C# / HTTP · Desktop launcher 1.7+ · Networking optional

Give a desktop game automatic launcher installation, updates, friends and private lobbies. SDK 1.1.0 requires GoturGames launcher 1.7 or later. Networking is optional: single-player games need only their launch configuration.

Quick start

  1. Create a draft game in Studio, or have the studio create it for you. Its URL slug is your permanent game identifier.
  2. Download the SDK. Copy goturgames.mjs for Node.js 18+, or GoturGames.cs into a Unity project using .NET Standard 2.1. Other engines can use the HTTP contract below.
  3. Connect on game startup. Use the supplied host/join details with your game’s transport, and report readiness after the listener is accepting connections.
  4. Put goturgames.json at the ZIP root. Set your game slug, upload platform, exact executable path, CPU architectures and minimum OS. Enable networking only after the game includes its integration code.
  5. Upload through Studio or your game’s scoped publishing token. Review the detected settings, then publish. Matching platform manifests automatically configure the catalog and lobby directory. No launcher source edit or game-name registration is needed.
  6. Install with launcher 1.7+, add a second test account as a friend, then choose Friends & lobbies → Host & launch. Invite the friend after the game reports ready. Both players need a license and the same game version.

Package manifest

The example manifest declares a Windows build. Each platform ZIP has its own root file with the same networking settings. Executable paths are relative to the ZIP root, case-sensitive, and must name an actual regular file. Commands, shell scripts, arbitrary launcher arguments and external download URLs are not accepted as executable configuration.

{
  "schema": 1,
  "slug": "your-game",
  "platform": "Windows",
  "launch": {
    "executable": "YourGame/YourGame.exe",
    "architectures": ["x64"],
    "minOS": "10.0"
  },
  "networking": {
    "enabled": true,
    "sdk": 1,
    "protocol": "your-game-v1",
    "transport": "tcp",
    "port": 7777,
    "maxPlayers": 8
  }
}

For macOS use a path such as YourGame.app/Contents/MacOS/YourGame, architectures arm64 and/or x64, and a minimum OS such as 13.0. For Linux use a compiled executable ending in .x86_64, its supported architecture, and a numeric minimum kernel version, for example 0 to impose no kernel floor. Windows executables end in .exe. Preserve executable permission bits for macOS and Linux. Every executable is installed, verified and launched from its package directory; do not rely on the website working directory.

Set networking to {"enabled":false} for single-player games. Enabled networking needs SDK 1, a protocol ID of 1–64 letters/numbers/dots/underscores/hyphens, transport tcp or udp, a port from 1024–65535, and 2–64 players. Change your protocol ID when network messages become incompatible. Release all supported platforms together when changing networking settings. The upload parser accepts one root manifest of at most 32 KiB and rejects wrong game/platform IDs, missing executables, unsafe paths and conflicting settings.

Node.js integration

import {GoturGames} from './goturgames.mjs';
const gotur = await GoturGames.connect();
if (gotur?.session.id) {
  const {hosting, connection} = gotur.session;
  // connection: {address, port, transport, code}
  if (hosting) {
    await myNetwork.host(connection.port, connection.code);
    await gotur.setReady(true);
  } else {
    await myNetwork.join(connection.address, connection.port, connection.code);
  }
}

myNetwork represents your game’s own networking API; replace those calls with your engine’s host and join methods. The SDK does not create your gameplay server. The bundle includes examples/tcp-game.mjs, a runnable TCP handshake and ping/pong transport example. It demonstrates passing the access code without claiming to be a production gameplay protocol.

A normal Play launch of an integrated game also gets a bridge. It has no lobby initially. An in-game Host button can call await gotur.createLobby(reachableIPv4); then start your listener and report ready. Friends can be invited from the launcher. await gotur.leaveLobby() ends that lobby. GoturGames.connect() returns null outside the launcher, so your game can keep its normal standalone flow.

Unity and C# integration

using GoturGamesSDK;
GoturGames gotur;

async void Start() {
    try {
        gotur = await GoturGames.ConnectAsync();
        if (gotur == null || !gotur.Session.HasLobby) return;
        var session = gotur.Session;
        var c = session.connection;
        if (session.hosting) {
            // Replace with your transport's Host(c.port, c.code).
            // Await successful startup before reporting ready.
            await gotur.SetReadyAsync(true);
        } else {
            // Replace with your transport's Join(c.address, c.port, c.code).
        }
    } catch (System.Exception error) {
        UnityEngine.Debug.LogWarning(error.Message);
        // Show a retry/return-to-menu option in the game.
    }
}
void OnDestroy() { gotur?.Dispose(); }

Use CreateLobbyAsync(reachableIPv4) for an in-game Host button, LeaveLobbyAsync() when leaving, and RefreshAsync() to re-read the local session. The Unity library uses HttpClient with proxying disabled for its loopback connection; no project-wide insecure HTTP setting is needed. Do not dispose the library until its outstanding calls finish.

Readiness and session lifecycle

Hosts report setReady(true) / SetReadyAsync(true) after their listener is ready, then report false when a match stops accepting joins. Repeat the current readiness every five seconds to restore it after a brief server failure. The launcher sends directory heartbeats every 20 seconds; lobbies and presence expire within 65 seconds if it stops. Closing the game removes directory membership. Leaving as the host closes the lobby for everyone. Host migration is not provided.

The launcher reserves directory slots for accepted invitations, enforces player limits, and checks game licenses, friendship and exact release versions. Your game must also enforce its actual connection limit, access-code handshake, message validation and authoritative gameplay rules. A directory slot is a coordination reservation, not proof that a network connection succeeded. A player ID supplied by the local SDK is profile context, not a signed identity proof for a remote game server.

HTTP contract for other engines

The launcher sets GOTURGAMES_SESSION_URL to a loopback origin like http://127.0.0.1:49152 and GOTURGAMES_SESSION_KEY to a per-game, per-process capability. Never log or store the key. Requests use Authorization: Bearer <capability>, no browser Origin header, and JSON bodies. Reject any non-loopback bridge URL in your client. Requests time out after six seconds in the supplied libraries.

  • GET /session returns bridgeSchema:1, slug, version, player:{id} and networking. When assigned a lobby it also includes id, protocol, hosting, capacity, members and connection:{address,port,transport,code}.
  • POST /lobby with {"action":"create"} creates a lobby for this game and installed version only, returning the session object. Leave an existing lobby before creating another.
  • POST /status with {"ready":true} or {"ready":false} updates the owned lobby. At most one status update per second is accepted.
  • POST /lobby with {"action":"leave"} leaves or closes the assigned lobby. Then re-read /session.

Responses use 200 for success, 400 for invalid/failed bridge actions, 403 for an invalid capability or browser origin, 404 for unknown routes and 429 for readiness updates faster than once per second. Retry temporary failures with backoff; never mark a closed transport ready. The bridge cannot access another game, send friend requests, or expose the launcher’s account token.

Upload and publish

Studio → your saved game → Developer publishing access issues a game-scoped token. Only an authorized studio administrator can create games and issue/revoke tokens. This first version is controlled developer onboarding rather than open registration. Keep the publishing token outside your repository, packages and client code.

Use HTTPS and Authorization: Bearer ggp_... for these endpoints:

  • GET /api/releases/<slug>/info reads the current catalog revision and uploaded builds, including validated integration metadata.
  • POST /api/releases/<slug>/builds?version=1.0.0&platform=Windows&filename=YourGame.zip uploads the ZIP body with Content-Type: application/zip and its Content-Length. X-File-SHA256 optionally binds the upload checksum. The server forces the authenticated game slug.
  • POST /api/releases/<slug>/publish with {"version":"1.0.0","expectedRevision":3,"builds":[{"id":"<uploaded-build-id>"}]} publishes the selected builds and their integration settings together. Include all platforms whose networking settings change.

Upload responses include the immutable build ID, checksum and parsed integration. Uploading alone does not change the live release. Publishing checks the revision and all build ownership/version IDs before updating links and settings. A conflict returns 409; re-read the revision and review changes. Bad integration metadata returns 400; bad/missing tokens return 401, another game’s token returns 403, oversized uploads return 413, a busy upload returns 409, and insufficient storage returns 507. Publishing credentials can be revoked from Studio. Existing games without an embedded manifest keep their current delivery behavior.

Networking boundaries

The directory maps private lobbies to a game, protocol, release and members. The launcher relays TCP streams or UDP datagrams through outbound WSS connections to GoturGames on port 443. Players never enter an IP address or forward a router port. The host game listens on its declared port; guests receive a launcher-owned loopback address and dynamically assigned port. Always use the session connection address and port rather than hard-coding them. Keep the launcher open. The relay is bounded and intended for small co-op lobbies; dedicated servers, browser/WebRTC support and paid checkout are separate work. Host disconnects end the lobby; host migration is not provided.

Test before publishing

Test two real players on different accounts, then on different computers. Verify a full lobby, a declined invite, a missing license, an older game version, a host that closes mid-join, and a match that reports not ready. Test from different networks through the relay. A VPN is not required. Verify standalone startup without environment variables. Keep the integration disabled until these checks pass, and never include publisher or account credentials in a release.

Developer panel and installation checks

Open the developer panel, sign in with your shared GoturGames account, and create a studio profile. Register a private game, upload a ZIP containing goturgames.json, then choose Validate installation. The system extracts every file with the same limits as launcher installs, rejects unsafe paths and special files, hashes the contents, and verifies the executable or DLC content root. It does not execute uploaded code or prove the game runs on a particular device. Test on supported devices before submitting selected builds for Studio review. New games and updates become public only after Studio approval. Existing game owners can be assigned to their developer account by GoturGames Studio.

DLC content packages

Register a DLC entry under a base game owned by your studio. Package a data-only ZIP using the DLC manifest example and put the assets below the declared contentRoot. Do not include a launch executable or enable networking for a DLC package. Each platform gets its own verified package and system requirements. Players must own and install the base game before installing its DLC. Launching the base game supplies installed, licensed, verified addons through session.addons in SDK 1.1 and through GOTURGAMES_DLC (a JSON array) for other engines. Each entry contains slug, version, and contentPath. Load your expansion's data from this path; DLC assets are kept in separate immutable installations. Engines must implement the content loading themselves. DLC is not automatically injected into an unmodified game. A revoked base license or DLC license removes the corresponding entitlement on the next launch.

Prices, licenses and draft subscription tiers

Free games grant an account license when claimed. Outright licenses use the existing purchase/studio entitlement model; paid checkout is disabled. The developer panel saves a future USD license price independently from the current free catalog price. Saving a draft price does not charge players or convert their existing licenses.

Create multiple draft monthly tiers, each with a price, a monthly game selection allowance, and named packages of eligible games or DLC owned by your studio. These are configuration drafts only: there is no payment, active subscription, renewal or subscription license grant until billing is implemented. The intended policy is access during an active subscription, with selection allowances resetting each billing month rather than accumulating. Outright licenses remain independent. Cancellation, refunds and payment webhooks still need Stripe integration.

Statistics and privacy

The launcher records store views (once per account/game/day), verified completed downloads and downloaded bytes, game starts and server-timed session heartbeats. Personal play seconds and launch counts are available to that player. Local download history includes queued, active, completed, cancelled, interrupted and failed jobs, times and reused bytes. Files are not counted as fresh network downloads when reused during an update.

The developer panel returns lifetime aggregate counts only. Names, email addresses, player IDs, IP addresses, timestamps for individual players and individual sessions are excluded. Reports remain hidden until at least five accounts have contributed. Download and play metrics additionally require five distinct contributors to those metrics. Studio has aggregate first-party totals for operations. Client activity is useful product telemetry, not fraud-proof billing evidence. Browser-game sessions cannot be measured by the desktop process monitor; a browser integration is separate work.