ggscale API (1.0.0)

Download OpenAPI specification:

Player-facing and game-server-facing HTTP API for ggscale. Authenticate with a tenant API key (Authorization: Bearer). Player endpoints additionally require a session token in X-Session-Token.

Authentication

Player sign-in and session tokens: email/password, anonymous, and custom-token.

Create an anonymous player session

Authorizations:
ApiKeyAuth

Responses

Response samples

Content type
application/json
{
  • "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  • "expires_at": "2026-01-02T15:04:05Z",
  • "external_id": "anon_9f86d081884c7d659a2feaa0c55ad015",
  • "player_id": 42,
  • "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}

Exchange a tenant-signed token for a session

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
token
required
string non-empty

Responses

Request samples

Content type
application/json
{
  • "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHRlcm5hbF9pZCI6InN0ZWFtOjc2NTYxMTk4MDAwMDAwMDAifQ.k7HfXWY0mYbXvJqPz3sB4c9Q2rN8dEwTuVxYzA1bC2d"
}

Response samples

Content type
application/json
{
  • "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  • "expires_at": "2026-01-02T15:04:05Z",
  • "player_id": 42,
  • "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}

Log in with email and password

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
email
string
password
string

Responses

Request samples

Content type
application/json
{
  • "email": "player@example.com",
  • "password": "correct-horse-battery-staple"
}

Response samples

Content type
application/json
{
  • "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  • "expires_at": "2026-01-02T15:04:05Z",
  • "player_id": 42,
  • "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}

Revoke a refresh token

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
refresh_token
required
string non-empty

Responses

Request samples

Content type
application/json
{
  • "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}

Response samples

Content type
application/problem+json
{}

Rotate a refresh token

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
refresh_token
required
string non-empty

Responses

Request samples

Content type
application/json
{
  • "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}

Response samples

Content type
application/json
{
  • "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  • "expires_at": "2026-01-02T15:04:05Z",
  • "player_id": 42,
  • "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}

Sign up with email and password

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
email
string
password
string

Responses

Request samples

Content type
application/json
{
  • "email": "player@example.com",
  • "password": "correct-horse-battery-staple"
}

Response samples

Content type
application/problem+json
{}

Verify an email address with a code

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
code
required
string non-empty
email
required
string non-empty

Responses

Request samples

Content type
application/json
{
  • "code": "482913",
  • "email": "player@example.com"
}

Response samples

Content type
application/json
{
  • "player_id": 42,
  • "verified": true
}

Player Profiles

Per-project player identity: email and external console id.

Get the caller's profile

Authorizations:
(ApiKeyAuthPlayerSession)

Responses

Response samples

Content type
application/json
{
  • "created_at": "2026-01-02T15:04:05Z",
  • "email": "player@example.com",
  • "email_verified_at": "2026-01-02T15:04:05Z",
  • "external_id": "user_1b4e28ba2fa14f0e8bf1a09b4d7e5f60",
  • "id": 42,
  • "project_id": 7,
  • "xuid": "2533274790395904"
}

Update the caller's email or xuid

Authorizations:
(ApiKeyAuthPlayerSession)
Request Body schema: application/json
required
email
string
xuid
string

Responses

Request samples

Content type
application/json
{
  • "email": "player@example.com",
  • "xuid": "2533274790395904"
}

Response samples

Content type
application/problem+json
{}

Cloud Saves

Per-player JSON object storage with optimistic concurrency.

List the caller's storage objects

Authorizations:
(ApiKeyAuthPlayerSession)
query Parameters
key_prefix
string
Examples: key_prefix=save-
limit
string
Examples: limit=50
cursor
string
Examples: cursor=104

Responses

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_cursor": "104"
}

Delete a storage object

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
key
required
string
Examples: save-slot-1

Responses

Response samples

Content type
application/problem+json
{}

Get a storage object

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
key
required
string
Examples: save-slot-1

Responses

Response samples

Content type
application/json
{
  • "key": "save-slot-1",
  • "updated_at": "2026-01-02T15:04:05Z",
  • "value": {
    },
  • "version": 7
}

Create or replace a storage object

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
key
required
string
Examples: save-slot-1
header Parameters
If-Match
string
Examples: 7
Request Body schema: application/json
required
any

Any JSON value to store: object, array, string, number, boolean, or null.

Responses

Request samples

Content type
application/json
{
  • "hp": 100,
  • "level": 3
}

Response samples

Content type
application/json
{
  • "key": "save-slot-1",
  • "updated_at": "2026-01-02T15:04:05Z",
  • "value": {
    },
  • "version": 7
}

Leaderboards

Ranked scoreboards with server-authoritative score submission.

Scores around the caller's rank

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
integer <int64> >= 1
Examples: 1
query Parameters
radius
string
Examples: radius=5

Responses

Response samples

Content type
application/json
{
  • "entries": [
    ],
  • "self_rank": 12
}

Submit a score to a leaderboard

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
integer <int64> >= 1
Examples: 1
Request Body schema: application/json
required
score
integer <int64>

Responses

Request samples

Content type
application/json
{
  • "score": 1500
}

Response samples

Content type
application/problem+json
{}

Top scores for a leaderboard

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
integer <int64> >= 1
Examples: 1
query Parameters
limit
string
Examples: limit=10

Responses

Response samples

Content type
application/json
{
  • "entries": [
    ]
}

Friends & Presence

Friend requests, blocks, and online presence.

List the caller's friends by status

Authorizations:
(ApiKeyAuthPlayerSession)
query Parameters
status
string
Examples: status=accepted
limit
string
Examples: limit=50
cursor
string
Examples: cursor=104

Responses

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_cursor": "104"
}

Remove a friend

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
player_id
required
integer <int64> >= 1
Examples: 87

Responses

Response samples

Content type
application/problem+json
{}

Accept a friend request

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
player_id
required
integer <int64> >= 1
Examples: 87

Responses

Response samples

Content type
application/json
{
  • "status": "requested"
}

Block a player

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
player_id
required
integer <int64> >= 1
Examples: 87

Responses

Response samples

Content type
application/json
{
  • "status": "requested"
}

Reject a friend request

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
player_id
required
integer <int64> >= 1
Examples: 87

Responses

Response samples

Content type
application/json
{
  • "status": "requested"
}

Send a friend request

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
player_id
required
integer <int64> >= 1
Examples: 87

Responses

Response samples

Content type
application/json
{
  • "status": "requested"
}

Unblock a player

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
player_id
required
integer <int64> >= 1
Examples: 87

Responses

Response samples

Content type
application/json
{
  • "status": "requested"
}

Update the caller's presence

Authorizations:
(ApiKeyAuthPlayerSession)
Request Body schema: application/json
required
session_id
string
status
required
string [ 1 .. 32 ] characters

Responses

Request samples

Content type
application/json
{
  • "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
  • "status": "online"
}

Response samples

Content type
application/json
{
  • "ok": true
}

Game Sessions & Invites

Pre-game rooms with join codes, plus short-lived invites.

Resolve a game session by join code

Authorizations:
(ApiKeyAuthPlayerSession)
query Parameters
joinCode
string
Examples: joinCode=XKCD42

Responses

Response samples

Content type
application/json
{
  • "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015"
}

Create a game session

Creates a session with a one-hour lifetime window. Member heartbeats slide the window forward, so an active session stays alive for the length of the match while an idle one expires within the hour. When the match ends, the host should DELETE the session — that frees the project's open-session slot immediately instead of waiting for expiry.

Authorizations:
(ApiKeyAuthPlayerSession)
Request Body schema: application/json
required
max_players
integer <int64>
private
boolean
props
any
object (GameSessionAddr)
title_id
string

Responses

Request samples

Content type
application/json
{
  • "max_players": 8,
  • "private": false,
  • "props": {
    },
  • "public_addr": {
    },
  • "title_id": "my-game"
}

Response samples

Content type
application/json
{
  • "expires_at": "2026-01-02T15:04:05Z",
  • "join_code": "XKCD42",
  • "peers": [
    ],
  • "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
  • "state": "open"
}

Leave (or, for the host, end) a game session

A joiner is removed from the roster; the host ends the session for everyone. Call this from the host when the match ends — an ended session stops counting against the project's open-session limit immediately.

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
string
Examples: gs_9f86d081884c7d659a2feaa0c55ad015

Responses

Response samples

Content type
application/problem+json
{}

Get a game session

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
string
Examples: gs_9f86d081884c7d659a2feaa0c55ad015

Responses

Response samples

Content type
application/json
{
  • "expires_at": "2026-01-02T15:04:05Z",
  • "join_code": "XKCD42",
  • "peers": [
    ],
  • "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
  • "state": "open"
}

Heartbeat a game session peer

Marks the caller's peer as alive and returns the current roster. A member heartbeat also extends the session's expiry when under 30 minutes remain, keeping active matches alive past the one-hour default window.

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
string
Examples: gs_9f86d081884c7d659a2feaa0c55ad015
Request Body schema: application/json
required
qos
any

Responses

Request samples

Content type
application/json
{
  • "qos": {
    }
}

Response samples

Content type
application/json
{
  • "ok": true,
  • "peers": [
    ]
}

Join a game session

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
string
Examples: gs_9f86d081884c7d659a2feaa0c55ad015
Request Body schema: application/json
required
object (GameSessionAddr)

Responses

Request samples

Content type
application/json
{
  • "public_addr": {
    }
}

Response samples

Content type
application/json
{
  • "expires_at": "2026-01-02T15:04:05Z",
  • "join_code": "XKCD42",
  • "peers": [
    ],
  • "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
  • "state": "open"
}

Poll game-session negotiation signals

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
string
Examples: gs_9f86d081884c7d659a2feaa0c55ad015
query Parameters
after_id
integer <int64> >= 0
Examples: after_id=512

Responses

Response samples

Content type
application/json
{
  • "signals": [
    ]
}

Send a game-session negotiation signal

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
string
Examples: gs_9f86d081884c7d659a2feaa0c55ad015
Request Body schema: application/json
required
kind
required
string
Enum: "offer" "answer" "restart_offer" "restart_answer"
negotiation_id
required
string [ 1 .. 128 ] characters
payload
required
string non-empty
to_player_id
required
integer <int64> >= 1

Responses

Request samples

Content type
application/json
{
  • "kind": "offer",
  • "negotiation_id": "neg-42-87-1",
  • "payload": "eyJ0eXBlIjoib2ZmZXIiLCJzZHAiOiJ2PTAuLi4ifQ==",
  • "to_player_id": 87
}

Response samples

Content type
application/json
{
  • "id": 512
}

List the caller's pending game invites

Authorizations:
(ApiKeyAuthPlayerSession)

Responses

Response samples

Content type
application/json
{
  • "invites": [
    ]
}

Invite a friend to a game session

Authorizations:
(ApiKeyAuthPlayerSession)
Request Body schema: application/json
required
session_id
required
string non-empty
to_email
required
string non-empty

Responses

Request samples

Content type
application/json
{
  • "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
  • "to_email": "friend@example.com"
}

Response samples

Content type
application/json
{
  • "invite_id": 314
}

Cancel or dismiss a game invite

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
integer <int64>
Examples: 314

Responses

Response samples

Content type
application/problem+json
{}

Matchmaking

Tickets that return a roster, a game session, or a fleet allocation.

Create a matchmaking ticket

Authorizations:
(ApiKeyAuthPlayerSession)
Request Body schema: application/json
required
allow_cross_region
boolean
attributes
any
count_multiple
integer <int64>
fleet
string
game_mode
string
max_count
integer <int64>
min_count
integer <int64>
mode
string
object
query
string
region
string
object

Responses

Request samples

Content type
application/json
{
  • "allow_cross_region": true,
  • "attributes": {
    },
  • "count_multiple": 2,
  • "fleet": "default",
  • "game_mode": "ctf",
  • "max_count": 4,
  • "min_count": 2,
  • "mode": "game_session",
  • "numeric_properties": {
    },
  • "query": "string",
  • "region": "us-east-1",
  • "string_properties": {
    }
}

Response samples

Content type
application/json
{
  • "allow_cross_region": true,
  • "attributes": {
    },
  • "count_multiple": 2,
  • "created_at": "2026-01-02T15:04:05Z",
  • "expires_at": "2026-01-02T15:09:05Z",
  • "failure_reason": "expired",
  • "game_mode": "ctf",
  • "host_player_id": 42,
  • "id": 9001,
  • "join_code": "XKCD42",
  • "match_address": "203.0.113.10:7777",
  • "match_id": "mm_5f3a9c1d2e4b6a70",
  • "matched_at": "2026-01-02T15:04:35Z",
  • "max_count": 4,
  • "min_count": 2,
  • "mode": "game_session",
  • "numeric_properties": {
    },
  • "protocol_hint": "udp",
  • "query": "string",
  • "region": "us-east-1",
  • "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
  • "status": "matched",
  • "string_properties": {
    },
  • "users": [
    ]
}

Cancel a matchmaking ticket

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
integer <int64>
Examples: 9001

Responses

Response samples

Content type
application/problem+json
{}

Get a matchmaking ticket

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
id
required
integer <int64>
Examples: 9001

Responses

Response samples

Content type
application/json
{
  • "allow_cross_region": true,
  • "attributes": {
    },
  • "count_multiple": 2,
  • "created_at": "2026-01-02T15:04:05Z",
  • "expires_at": "2026-01-02T15:09:05Z",
  • "failure_reason": "expired",
  • "game_mode": "ctf",
  • "host_player_id": 42,
  • "id": 9001,
  • "join_code": "XKCD42",
  • "match_address": "203.0.113.10:7777",
  • "match_id": "mm_5f3a9c1d2e4b6a70",
  • "matched_at": "2026-01-02T15:04:35Z",
  • "max_count": 4,
  • "min_count": 2,
  • "mode": "game_session",
  • "numeric_properties": {
    },
  • "protocol_hint": "udp",
  • "query": "string",
  • "region": "us-east-1",
  • "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
  • "status": "matched",
  • "string_properties": {
    },
  • "users": [
    ]
}

Realtime

The WebSocket channel for presence, invites, and match events.

Realtime WebSocket channel

Upgrades to a WebSocket for realtime player events; not a JSON endpoint. Authenticate with the tenant API key and the player session token.

Authorizations:
(ApiKeyAuthPlayerSession)

Responses

P2P & TURN Relay

Short-lived TURN credentials for NAT traversal.

Issue short-lived TURN-REST relay credentials

Authorizations:
(ApiKeyAuthPlayerSession)
query Parameters
match_id
string
Examples: match_id=mm_5f3a9c1d2e4b6a70

Responses

Response samples

Content type
application/json
{
  • "password": "dGVzdC1obWFjLXNhbXBsZS12YWx1ZQ==",
  • "realm": "ggscale",
  • "stun_urls": [
    ],
  • "ttl": 600,
  • "urls": [
    ],
  • "username": "1767225600:3:42:k1"
}

Remote Addresses

A player's opaque connect handles, such as a Steam id.

Get the caller's remote addresses

Authorizations:
(ApiKeyAuthPlayerSession)

Responses

Response samples

Content type
application/json
{
  • "addresses": [
    ]
}

Replace the caller's remote addresses

Authorizations:
(ApiKeyAuthPlayerSession)
Request Body schema: application/json
required
required
Array of objects or null (RemoteAddrEntry)

Responses

Request samples

Content type
application/json
{
  • "addresses": [
    ]
}

Response samples

Content type
application/json
{
  • "addresses": [
    ]
}

Get an accepted friend's remote addresses

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
player_id
required
integer <int64> >= 1

Responses

Response samples

Content type
application/json
{
  • "addresses": [
    ]
}

Server-tier: read a player's remote addresses

Authorizations:
ApiKeyAuth
path Parameters
player_id
required
integer <int64> >= 1

Responses

Response samples

Content type
application/json
{
  • "addresses": [
    ]
}

Game Server Fleet

Dedicated-server heartbeat and fleet listing. Beta.

Game-server liveness heartbeat

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
address
string
agones_name
string
current_players
integer <int64>
fleet
string
game_mode
string
level
string
max_players
integer <int64>
name
string
region
string
version
string

Responses

Request samples

Content type
application/json
{
  • "address": "203.0.113.10:7777",
  • "agones_name": "gameserver-abc12",
  • "current_players": 12,
  • "fleet": "default",
  • "game_mode": "ctf",
  • "level": "arena-2",
  • "max_players": 16,
  • "name": "us-east-1-a1",
  • "region": "us-east-1",
  • "version": "1.4.2"
}

Response samples

Content type
application/problem+json
{}

List live servers in a fleet

Authorizations:
(ApiKeyAuthPlayerSession)
path Parameters
fleet
required
string
Examples: default

Responses

Response samples

Content type
application/json
{
  • "servers": [
    ]
}

Session Verification

Server-tier check of a player session token.

Server-tier: verify a player session token

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
session_token
required
string

Responses

Request samples

Content type
application/json
{
  • "session_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}

Response samples

Content type
application/json
{
  • "email": "player@example.com",
  • "external_id": "anon_9f86d081884c7d659a2feaa0c55ad015",
  • "player_id": 42
}

Health

Liveness probe.

Liveness probe

Responses

Response samples

Content type
application/json
{
  • "commit": "abc1234",
  • "status": "ok",
  • "version": "1.0.0"
}