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.
{- "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
- "expires_at": "2026-01-02T15:04:05Z",
- "external_id": "anon_9f86d081884c7d659a2feaa0c55ad015",
- "player_id": 42,
- "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}| token required | string non-empty |
{- "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHRlcm5hbF9pZCI6InN0ZWFtOjc2NTYxMTk4MDAwMDAwMDAifQ.k7HfXWY0mYbXvJqPz3sB4c9Q2rN8dEwTuVxYzA1bC2d"
}{- "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
- "expires_at": "2026-01-02T15:04:05Z",
- "player_id": 42,
- "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}string | |
| password | string |
{- "email": "player@example.com",
- "password": "correct-horse-battery-staple"
}{- "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
- "expires_at": "2026-01-02T15:04:05Z",
- "player_id": 42,
- "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}| refresh_token required | string non-empty |
{- "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}{- "detail": "Property foo is required but is missing.",
- "errors": [
- {
- "location": "string",
- "message": "string",
- "value": null
}
], - "status": 400,
- "title": "Bad Request",
}| refresh_token required | string non-empty |
{- "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}{- "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
- "expires_at": "2026-01-02T15:04:05Z",
- "player_id": 42,
- "refresh_token": "3f2c8a1d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}string | |
| password | string |
{- "email": "player@example.com",
- "password": "correct-horse-battery-staple"
}{- "detail": "Property foo is required but is missing.",
- "errors": [
- {
- "location": "string",
- "message": "string",
- "value": null
}
], - "status": 400,
- "title": "Bad Request",
}| code required | string non-empty |
| email required | string non-empty |
{- "code": "482913",
- "email": "player@example.com"
}{- "player_id": 42,
- "verified": true
}{- "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"
}string | |
| xuid | string |
{- "email": "player@example.com",
- "xuid": "2533274790395904"
}{- "detail": "Property foo is required but is missing.",
- "errors": [
- {
- "location": "string",
- "message": "string",
- "value": null
}
], - "status": 400,
- "title": "Bad Request",
}| key_prefix | string Examples: key_prefix=save- |
| limit | string Examples: limit=50 |
| cursor | string Examples: cursor=104 |
{- "items": [
- {
- "key": "save-slot-1",
- "size_bytes": 512,
- "updated_at": "2026-01-02T15:04:05Z",
- "version": 7
}
], - "next_cursor": "104"
}| key required | string Examples: save-slot-1 |
{- "detail": "Property foo is required but is missing.",
- "errors": [
- {
- "location": "string",
- "message": "string",
- "value": null
}
], - "status": 400,
- "title": "Bad Request",
}| key required | string Examples: save-slot-1 |
| If-Match | string Examples: 7 |
Any JSON value to store: object, array, string, number, boolean, or null.
{- "hp": 100,
- "level": 3
}{- "key": "save-slot-1",
- "updated_at": "2026-01-02T15:04:05Z",
- "value": {
- "hp": 100,
- "level": 3
}, - "version": 7
}| id required | integer <int64> >= 1 Examples: 1 |
| radius | string Examples: radius=5 |
{- "entries": [
- {
- "player_id": 42,
- "rank": 3,
- "score": 1500
}
], - "self_rank": 12
}| id required | integer <int64> >= 1 Examples: 1 |
| score | integer <int64> |
{- "score": 1500
}{- "detail": "Property foo is required but is missing.",
- "errors": [
- {
- "location": "string",
- "message": "string",
- "value": null
}
], - "status": 400,
- "title": "Bad Request",
}| status | string Examples: status=accepted |
| limit | string Examples: limit=50 |
| cursor | string Examples: cursor=104 |
{- "items": [
- {
- "account_id": "6f9619ff-8b86-4d01-b42d-00cf4fc964ff",
- "created_at": "2026-01-02T15:04:05Z",
- "display_name": "PlayerTwo",
- "email": "friend@example.com",
- "id": 12,
- "player_id": 87,
- "presence": {
- "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
- "status": "online"
}, - "status": "accepted",
- "updated_at": "2026-01-02T15:04:05Z"
}
], - "next_cursor": "104"
}| player_id required | integer <int64> >= 1 Examples: 87 |
{- "detail": "Property foo is required but is missing.",
- "errors": [
- {
- "location": "string",
- "message": "string",
- "value": null
}
], - "status": 400,
- "title": "Bad Request",
}| session_id | string |
| status required | string [ 1 .. 32 ] characters |
{- "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
- "status": "online"
}{- "ok": true
}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.
| max_players | integer <int64> |
| private | boolean |
| props | any |
object (GameSessionAddr) | |
| title_id | string |
{- "max_players": 8,
- "private": false,
- "props": {
- "map": "arena-2"
}, - "public_addr": {
- "ip": "203.0.113.10",
- "port": 7777
}, - "title_id": "my-game"
}{- "expires_at": "2026-01-02T15:04:05Z",
- "join_code": "XKCD42",
- "peers": [
- {
- "addr": {
- "ip": "203.0.113.10",
- "port": 7777
}, - "player_id": 87,
- "xuid": "2533274790395904"
}
], - "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
- "state": "open"
}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.
| id required | string Examples: gs_9f86d081884c7d659a2feaa0c55ad015 |
{- "detail": "Property foo is required but is missing.",
- "errors": [
- {
- "location": "string",
- "message": "string",
- "value": null
}
], - "status": 400,
- "title": "Bad Request",
}| id required | string Examples: gs_9f86d081884c7d659a2feaa0c55ad015 |
{- "expires_at": "2026-01-02T15:04:05Z",
- "join_code": "XKCD42",
- "peers": [
- {
- "addr": {
- "ip": "203.0.113.10",
- "port": 7777
}, - "player_id": 87,
- "xuid": "2533274790395904"
}
], - "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
- "state": "open"
}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.
| id required | string Examples: gs_9f86d081884c7d659a2feaa0c55ad015 |
| qos | any |
{- "qos": {
- "rtt_ms": 48
}
}{- "ok": true,
- "peers": [
- {
- "addr": {
- "ip": "203.0.113.10",
- "port": 7777
}, - "player_id": 87,
- "xuid": "2533274790395904"
}
]
}| id required | string Examples: gs_9f86d081884c7d659a2feaa0c55ad015 |
object (GameSessionAddr) |
{- "public_addr": {
- "ip": "203.0.113.10",
- "port": 7777
}
}{- "expires_at": "2026-01-02T15:04:05Z",
- "join_code": "XKCD42",
- "peers": [
- {
- "addr": {
- "ip": "203.0.113.10",
- "port": 7777
}, - "player_id": 87,
- "xuid": "2533274790395904"
}
], - "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
- "state": "open"
}| id required | string Examples: gs_9f86d081884c7d659a2feaa0c55ad015 |
| after_id | integer <int64> >= 0 Examples: after_id=512 |
{- "signals": [
- {
- "created_at": "2026-01-02T15:04:05Z",
- "from_player_id": 42,
- "id": 513,
- "kind": "answer",
- "negotiation_id": "neg-42-87-1",
- "payload": "eyJ0eXBlIjoiYW5zd2VyIiwic2RwIjoidj0wLi4uIn0=",
- "to_player_id": 87
}
]
}| id required | string Examples: gs_9f86d081884c7d659a2feaa0c55ad015 |
| 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 |
{- "kind": "offer",
- "negotiation_id": "neg-42-87-1",
- "payload": "eyJ0eXBlIjoib2ZmZXIiLCJzZHAiOiJ2PTAuLi4ifQ==",
- "to_player_id": 87
}{- "id": 512
}{- "invites": [
- {
- "expires_at": "2026-01-02T15:04:05Z",
- "from_email": "player@example.com",
- "from_xuid": "2533274790395904",
- "invite_id": 314,
- "join_code": "XKCD42",
- "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015"
}
]
}| session_id required | string non-empty |
| to_email required | string non-empty |
{- "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
- "to_email": "friend@example.com"
}{- "invite_id": 314
}| id required | integer <int64> Examples: 314 |
{- "detail": "Property foo is required but is missing.",
- "errors": [
- {
- "location": "string",
- "message": "string",
- "value": null
}
], - "status": 400,
- "title": "Bad Request",
}| 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 |
{- "allow_cross_region": true,
- "attributes": {
- "lobby_code": "XKCD42"
}, - "count_multiple": 2,
- "fleet": "default",
- "game_mode": "ctf",
- "max_count": 4,
- "min_count": 2,
- "mode": "game_session",
- "numeric_properties": {
- "skill": 1420.5
}, - "query": "string",
- "region": "us-east-1",
- "string_properties": {
- "map": "arena-2"
}
}{- "allow_cross_region": true,
- "attributes": {
- "lobby_code": "XKCD42"
}, - "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": {
- "skill": 1420.5
}, - "protocol_hint": "udp",
- "query": "string",
- "region": "us-east-1",
- "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
- "status": "matched",
- "string_properties": {
- "map": "arena-2"
}, - "users": [
- {
- "attributes": {
- "lobby_code": "XKCD42"
}, - "numeric_properties": {
- "skill": 1420.5
}, - "player_id": 42,
- "region": "us-east-1",
- "string_properties": {
- "map": "arena-2"
}
}
]
}| id required | integer <int64> Examples: 9001 |
{- "detail": "Property foo is required but is missing.",
- "errors": [
- {
- "location": "string",
- "message": "string",
- "value": null
}
], - "status": 400,
- "title": "Bad Request",
}| id required | integer <int64> Examples: 9001 |
{- "allow_cross_region": true,
- "attributes": {
- "lobby_code": "XKCD42"
}, - "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": {
- "skill": 1420.5
}, - "protocol_hint": "udp",
- "query": "string",
- "region": "us-east-1",
- "session_id": "gs_9f86d081884c7d659a2feaa0c55ad015",
- "status": "matched",
- "string_properties": {
- "map": "arena-2"
}, - "users": [
- {
- "attributes": {
- "lobby_code": "XKCD42"
}, - "numeric_properties": {
- "skill": 1420.5
}, - "player_id": 42,
- "region": "us-east-1",
- "string_properties": {
- "map": "arena-2"
}
}
]
}| match_id | string Examples: match_id=mm_5f3a9c1d2e4b6a70 |
{- "password": "dGVzdC1obWFjLXNhbXBsZS12YWx1ZQ==",
- "realm": "ggscale",
- "stun_urls": [
- "stun:stun.example.com:3478"
], - "ttl": 600,
- "urls": [
- "turn:relay.example.com:3478?transport=udp"
], - "username": "1767225600:3:42:k1"
}required | Array of objects or null (RemoteAddrEntry) |
{- "addresses": [
- {
- "address": "203.0.113.10:7777",
- "scope": "public",
- "type": "ip"
}
]
}{- "addresses": [
- {
- "address": "203.0.113.10:7777",
- "scope": "public",
- "type": "ip"
}
]
}| 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 |
{- "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"
}{- "detail": "Property foo is required but is missing.",
- "errors": [
- {
- "location": "string",
- "message": "string",
- "value": null
}
], - "status": 400,
- "title": "Bad Request",
}| fleet required | string Examples: default |
{- "servers": [
- {
- "address": "203.0.113.10:7777",
- "current_players": 12,
- "game_mode": "ctf",
- "level": "arena-2",
- "max_players": 16,
- "name": "us-east-1-a1",
- "region": "us-east-1",
- "version": "1.4.2"
}
]
}| session_token required | string |
{- "session_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}{- "email": "player@example.com",
- "external_id": "anon_9f86d081884c7d659a2feaa0c55ad015",
- "player_id": 42
}