Skip to main content
🎉 GP CONF 2026: WEB Games Market Conference 👾 September 23 | Details

Player

Player operations run in the browser. Send Content-Type and X-Game-Platform-ID, use the platform's configured domain so the browser Origin matches it, and set credentials: 'include' on every request.

Do not send the platform API key from the browser. After login, the API sets an HttpOnly session cookie; browser JavaScript must neither read nor create it.

Load the authentication configuration

The response exposes only the public provider identifiers required to start login. Provider secrets are not returned in the browser context.

fragment PlatformAuthConfig on AuthConfig {
id
name
description
xsollaConfig {
loginProjectId
}
googleConfig {
clientID
}
yandexConfig {
clientID
}
vkIdConfig {
clientID
}
configs {
web {
implementation
activeService
}
}
}

query PlayerAuthConfiguration {
result: PlatformFetchGamePlatform {
__typename
... on Problem {
message
}
... on GamePlatform {
isMultipleAuthConfigUsed
authConfig {
...PlatformAuthConfig
}
allAuthConfigs {
...PlatformAuthConfig
}
}
}
}

Successful response shape:

{
"data": {
"result": {
"__typename": "GamePlatform",
"isMultipleAuthConfigUsed": false,
"authConfig": {
"id": "configured-auth-id",
"name": "Google login",
"description": "Sign in with Google",
"googleConfig": {
"clientID": "public-oauth-client-id"
},
"configs": {
"web": {
"implementation": "EXTERNAL",
"activeService": "GOOGLE"
}
}
},
"allAuthConfigs": []
}
}
}

When isMultipleAuthConfigUsed is true, let the player choose one of allAuthConfigs and pass its id as authConfigId during login. Otherwise use authConfig.

Log in

Complete the OAuth flow for one of the authentication providers configured on the platform, then exchange the resulting short-lived provider token with GamePush.

Provider setup and callback requirements are described in Third-Party Authentication. Return here for the platform-specific token exchange and session cookie flow.

mutation LoginPlayer($input: LoginPlayerOnGamePlatformInput!) {
result: LoginPlayerOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on LoginPlayerOnGamePlatformResult {
isNewUser
}
}
}

Variables:

{
"input": {
"gamePlatformID": 42,
"token": "SHORT_LIVED_PROVIDER_TOKEN",
"tokenType": "AccessToken",
"redirectUri": "https://games.example.com/auth/callback",
"authConfigId": "configured-auth-id"
}
}

Use a real, short-lived provider token at runtime; do not log or commit it. tokenType accepts AccessToken or ExchangeToken as required by the selected provider.

Successful response:

{
"data": {
"result": {
"__typename": "LoginPlayerOnGamePlatformResult",
"isNewUser": false
}
}
}

To end the session, keep the same browser headers and cookie settings:

mutation LogoutPlayer {
result: LogoutPlayerOnGamePlatform {
__typename
... on Problem {
message
}
... on Success {
success
}
}
}
{
"data": {
"result": {
"__typename": "Success",
"success": true
}
}
}

Read and update the profile

query CurrentPlatformPlayer($input: GetGamePlatformPlayerInput!) {
result: GetGamePlatformPlayer(input: $input) {
__typename
... on Problem {
message
}
... on GamePlatformPlayer {
id
gamePlatformID
name
avatar
balance
autoSkipAds
credentials {
login
type
}
vip {
productTag
enabled
disableGameAds
disablePlatformAds
currencyAccrual
bonusCurrency
endTime
}
playedGames
}
}
}

Variables:

{
"input": {}
}

Successful response shape:

{
"data": {
"result": {
"__typename": "GamePlatformPlayer",
"id": 9001,
"gamePlatformID": 42,
"name": "Player",
"avatar": "https://cdn.example.com/avatar.webp",
"balance": "1200",
"autoSkipAds": false,
"credentials": {
"login": "player@example.com",
"type": "EMAIL"
},
"vip": {
"productTag": "vip-month",
"enabled": true,
"disableGameAds": true,
"disablePlatformAds": true,
"currencyAccrual": 100,
"bonusCurrency": 50,
"endTime": "2026-09-01T00:00:00Z"
},
"playedGames": [101, 102]
}
}
}

Pass projectId in the input only when the profile must be prepared for a particular game.

mutation UpdatePlatformPlayer($input: UpdatePlayerProfileOnGamePlatformInput!) {
result: UpdatePlayerProfileOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on GamePlatformPlayer {
id
name
avatar
autoSkipAds
}
}
}

Variables and successful response:

{
"input": {
"name": "New name",
"avatarURL": "https://cdn.example.com/new-avatar.webp",
"autoSkipAds": false
}
}
{
"data": {
"result": {
"__typename": "GamePlatformPlayer",
"id": 9001,
"name": "New name",
"avatar": "https://cdn.example.com/new-avatar.webp",
"autoSkipAds": false
}
}
}

Build “My games”

Read playedGames from the profile, then resolve those IDs to cards. An empty ID list produces an empty list.

query MyGames($input: FetchGamesOnGamePlatformByIdsInput!, $lang: Lang) {
result: FetchGamesOnGamePlatformByIds(input: $input) {
__typename
... on Problem {
message
}
... on GameViewsList {
count
items {
id
name(lang: $lang)
icon(lang: $lang)
cover(lang: $lang)
platformUrl(lang: $lang)
rating
}
}
}
}
{
"lang": "EN",
"input": {
"gamePlatformId": 42,
"gameIds": [101, 102],
"targetOS": "Desktop"
}
}
{
"data": {
"result": {
"__typename": "GameViewsList",
"count": 2,
"items": [
{
"id": 101,
"name": "Example Game",
"platformUrl": "https://games.example.com/game/example-game",
"rating": 8.4
}
]
}
}
}

Record a game after it starts:

mutation AddPlayedGame($input: AddGameToPlayedOnGamePlatformInput!) {
result: AddGameToPlayedOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on Success {
success
}
}
}
{
"input": {
"gameViewId": 101
}
}
{
"data": {
"result": {
"__typename": "Success",
"success": true
}
}
}

Remove one game or import a local list into an empty player profile with these operations:

mutation RemovePlayedGame(
$input: RemoveGameFromPlayedOnGamePlatformInput!
) {
result: RemoveGameFromPlayedOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on Success {
success
}
}
}

mutation SyncPlayedGames($input: SyncPlayedGamesOnGamePlatformInput!) {
result: SyncPlayedGamesOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on Success {
success
}
}
}

Variables for RemovePlayedGame:

{
"input": {
"gameViewId": 101
}
}

Variables for SyncPlayedGames:

{
"input": {
"gameViewIds": [101, 102]
}
}

Both successful mutations return {"__typename":"Success","success":true}. SyncPlayedGamesOnGamePlatform is intended for importing a guest's locally saved games after the player first signs up. It saves at most the first 25 published games only when the server-side playedGames list is empty. If that list already contains games, the mutation returns success without changing it. It does not replace an existing list; use the add and remove mutations for later changes.

Purchase platform currency or benefits

Render available bundles from productsList in the Platform query. Start a purchase only after the player has signed in.

The shared product and purchase concepts are described in Purchases. The operations below cover the platform-specific bundle purchase, provider payload, and status check.

mutation PurchasePlatformBundle($input: PurchaseGamePlatformCurrencyBundleInput!) {
result: PurchaseGamePlatformCurrencyBundle(input: $input) {
__typename
... on Problem {
message
}
... on PlayerPurchaseOutput {
product {
id
tag
type
price(platform: PARTNER)
currency
}
purchase {
_id
orderStatus
payload
}
}
}
}
{
"input": {
"productId": 15,
"lang": "EN"
}
}
{
"data": {
"result": {
"__typename": "PlayerPurchaseOutput",
"product": {
"id": 15,
"tag": "coins-1000",
"type": "CURRENCY_BUNDLE",
"price": 4.99,
"currency": "USD"
},
"purchase": {
"_id": "purchase-id",
"orderStatus": "NEW",
"payload": {
"token": "SHORT_LIVED_PAYMENT_TOKEN"
}
}
}
}
}

Read paymentsConfig.configs.web.activeService from the Platform query and handle payload according to that service:

activeServiceReturned payloadSite action
XSOLLA{ "token": "..." }Open Xsolla Pay Station at https://secure.xsolla.com/paystation4/?token=<token>.
ROBOKASSA{ "url": "https://..." }Open the returned checkout URL in the payment interface or redirect the player to it.
STRIPE{ "url": "https://..." }Open the returned Stripe Checkout URL in the payment interface or redirect the player to it.

Provider-side setup is described in Xsolla, Robokassa, and Stripe. Use activeService to select the integration instead of inferring it from arbitrary payload fields. Treat payment tokens and URLs as short-lived data: do not log or persist them.

The browser must not mark a purchase as paid. After the provider flow completes, poll the purchase by ID and use orderStatus as the source of truth:

query PlatformPurchase($input: GetGamePlatformPurchaseInput!) {
result: GetGamePlatformPurchase(input: $input) {
__typename
... on Problem {
message
}
... on PlayerPurchase {
_id
orderStatus
payload
product {
id
type
price(platform: PARTNER)
}
}
}
}
{
"input": {
"purchaseId": "purchase-id"
}
}
{
"data": {
"result": {
"__typename": "PlayerPurchase",
"_id": "purchase-id",
"orderStatus": "PAID",
"payload": {
"token": "SHORT_LIVED_PAYMENT_TOKEN"
},
"product": {
"id": 15,
"type": "CURRENCY_BUNDLE",
"price": 4.99
}
}
}
}

For an in-game product paid from the platform balance, use the product, project, and provider returned by the game API:

mutation PurchaseGameProduct($input: PurchaseProductOnGamePlatformInput!) {
result: PurchaseProductOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on PlayerPurchase {
_id
projectId
productId
orderStatus
product {
id
name(lang: EN)
price(platform: PARTNER)
}
}
}
}
{
"input": {
"productId": 301,
"projectId": 501,
"provider": "GAMEPUSH"
}
}
{
"data": {
"result": {
"__typename": "PlayerPurchase",
"_id": "game-purchase-id",
"projectId": 501,
"productId": 301,
"orderStatus": "PAID",
"product": {
"id": 301,
"name": "Starter pack",
"price": 500
}
}
}
}

Always treat orderStatus from the API as the source of truth; never mark a purchase as paid only because the browser returned from a payment page.