Skip to main content

Game currency

Game currency uses a purchase flow with a separate calculation step. An authenticated player selects an owned game account and pays from cabinet balance. Without signing in, only offers delivered as an item to a character are available, and the buyer selects a payment method.

The purchase calculation fixes the offer, quantity, adjustments, total, recipient, and expiration. It is not a separate payment. Submit a valid calculation identifier to confirm the purchase.

After sign-in, operations use the selected game server and the current player's game accounts. For guest purchases, supply the server, character name and payer email. The purchase calculation returns the price and discount.

The server performs catalog lookup, price calculation, order creation, debit, and delivery as one coordinated flow. The client displays returned values and does not recalculate money through floating-point numbers.

Offer list​

QuerydocumentId: gameCurrencyOffersauth: Bearer session

gameCurrencyOffers​

Description​

Returns enabled game-currency offers for the current project and server context. The result uses cursor pagination; the operation does not accept gameServerId from the client.

Input​

FieldTypeRequiredDescription
firstIntnoPage size from 1 to 100. The schema default is 50; pass it explicitly in the persisted operation
afterIDnoCursor from pageInfo.endCursor of the previous page

Result​

GameCurrencyOfferConnection contains items and pageInfo. Each offer contains:

FieldTypeDescription
idID!Opaque offer identifier
skuString!Unique offer code
nameString!Localized name
descriptionString!Localized description
shortNameString!Short game-currency name
iconReferenceString!Offer artwork reference
messageString!Delivery message
deliveryTypeGameCurrencyDeliveryType!CHARACTER_ITEM or ACCOUNT_POINTS
unitsPerPurchaseInt!Game units in one package
unitPriceGameCurrencyMoney!Exact price of one package

When pageInfo.hasNextPage is true, pass endCursor unchanged as after.

Exchange example​

Request
documentId: gameCurrencyOffers
{
"documentId": "gameCurrencyOffers",
"variables": {
"first": 50,
"after": null
}
}
Response
200 OK
{
"data": {
"gameCurrencyOffers": {
"items": [
{
"id": "01910000-0000-7000-8000-000000000101",
"sku": "adena-pack",
"name": "Adena package",
"description": "Currency for the game account.",
"shortName": "ADENA",
"iconReference": "/assets/images/currency/adena.webp",
"message": "Currency is delivered after payment.",
"deliveryType": "ACCOUNT_POINTS",
"unitsPerPurchase": 100,
"unitPrice": {
"units": "250",
"code": "USD",
"scale": 2,
"decimal": "2.50"
}
},
{
"id": "01910000-0000-7000-8000-000000000201",
"sku": "soulshot-pack",
"name": "Soulshot package",
"description": "An item delivered to the selected character.",
"shortName": "SOULSHOT",
"iconReference": "/assets/images/currency/soulshot.webp",
"message": "Choose a character for delivery.",
"deliveryType": "CHARACTER_ITEM",
"unitsPerPurchase": 1000,
"unitPrice": {
"units": "500",
"code": "USD",
"scale": 2,
"decimal": "5.00"
}
}
],
"pageInfo": {
"endCursor": null,
"hasNextPage": false
}
}
}
}

Errors​

  • GAME_CURRENCY_SCOPE_UNAVAILABLE - the player's server context is unavailable.
  • GAME_CURRENCY_UNAVAILABLE - the catalog is temporarily unavailable.

Prepare a purchase​

MutationdocumentId: prepareGameCurrencyPurchaseauth: Bearer session

prepareGameCurrencyPurchase​

Description​

Creates a calculation for the selected offer and recipient with the price, discounts, quantity and expiry. This operation neither charges nor reserves funds.

Input​

FieldTypeRequiredDescription
input.requestIdID!yesNew UUIDv7 for the preparation attempt; identical data is idempotent
input.offerIdID!yesOffer identifier from gameCurrencyOffers
input.quantityInt!yesPackage count from 1 to 1,000,000
input.accountNameString!yesLogin of an account owned by the player
input.characterNameStringnoRequired for CHARACTER_ITEM; omitted for ACCOUNT_POINTS

characterName is required for character delivery and must be absent for account delivery.

Result​

GameCurrencyQuote contains the calculation until its expiration:

FieldTypeDescription
idID!Calculation identifier
offerGameCurrencyOffer!Offer snapshot
quantityInt!Package count
deliveredUnitsInt!Total delivered units
unitAmountGameCurrencyMoney!Price of one package
subtotalGameCurrencyMoney!Amount before adjustments
adjustments[GameCurrencyPriceAdjustment!]!Separate discounts and surcharges
totalGameCurrencyMoney!Amount to pay
hasSavingsBoolean!Whether the calculation contains a discount
deliveryGameCurrencyDeliveryTarget!Verified recipient
expiresAtDateTime!Calculation expiration

Money contains atomic units, currency code, scale, and a ready-to-display decimal value. adjustments.source distinguishes catalog, referral, VIP, and campaign rules.

Exchange example​

Request
documentId: prepareGameCurrencyPurchase
{
"documentId": "prepareGameCurrencyPurchase",
"variables": {
"input": {
"requestId": "01910000-0000-7000-8000-000000000105",
"offerId": "01910000-0000-7000-8000-000000000101",
"quantity": 2,
"accountName": "account-one"
}
}
}
Response
200 OK
{
"data": {
"prepareGameCurrencyPurchase": {
"id": "01910000-0000-7000-8000-000000000102",
"offer": {
"id": "01910000-0000-7000-8000-000000000101",
"sku": "adena-pack",
"name": "Adena package",
"description": "Currency for the game account.",
"shortName": "ADENA",
"iconReference": "/assets/images/currency/adena.webp",
"message": "Currency is delivered after payment.",
"deliveryType": "ACCOUNT_POINTS",
"unitsPerPurchase": 100,
"unitPrice": {
"units": "250",
"code": "USD",
"scale": 2,
"decimal": "2.50"
}
},
"quantity": 2,
"deliveredUnits": 200,
"unitAmount": {
"units": "250",
"code": "USD",
"scale": 2,
"decimal": "2.50"
},
"subtotal": {
"units": "500",
"code": "USD",
"scale": 2,
"decimal": "5.00"
},
"adjustments": [
{
"code": "vip-20",
"kind": "DISCOUNT",
"source": "VIP",
"amount": {
"units": "100",
"code": "USD",
"scale": 2,
"decimal": "1.00"
}
}
],
"total": {
"units": "400",
"code": "USD",
"scale": 2,
"decimal": "4.00"
},
"hasSavings": true,
"delivery": {
"type": "GAME_ACCOUNT",
"accountName": "account-one",
"characterName": null
},
"expiresAt": "2026-08-31T10:10:00.000000Z"
}
}
}

Errors​

  • GAME_CURRENCY_INVALID_REQUEST - request, quantity, or recipient rules are invalid.
  • GAME_CURRENCY_ACCOUNT_UNAVAILABLE - the account or character is not available to the player.
  • GAME_CURRENCY_OFFER_UNAVAILABLE - the offer is disabled, removed, or outside the current context.
  • GAME_CURRENCY_SCOPE_UNAVAILABLE - the permitted project, server, or wallet cannot be resolved.
  • GAME_CURRENCY_CONFLICT - a UUIDv7 was reused with different data.
  • GAME_CURRENCY_UNAVAILABLE - the calculation is temporarily unavailable.

Purchase from the calculation​

MutationdocumentId: purchaseGameCurrencyauth: Bearer session

purchaseGameCurrency​

Description​

Creates and pays an order from a valid calculation. The amount, discount and recipient come from that calculation. To change the purchase, obtain a new calculation first.

Input​

FieldTypeRequiredDescription
input.orderRequestIdID!yesNew UUIDv7 for order creation
input.paymentRequestIdID!yesNew UUIDv7 for wallet debit
input.quoteIdID!yesCalculation identifier returned by preparation

orderRequestId and paymentRequestId are separate idempotency keys. Repeating either step is safe; using different data produces a conflict instead of a second debit or delivery.

Result​

FieldTypeDescription
orderIdID!Order identifier
quoteIdID!Used calculation
orderStatusGameCurrencyOrderStatus!Order state
paymentIdIDWallet payment
paymentStatusGameCurrencyPaymentStatus!Debit or compensation state
totalGameCurrencyMoney!Recorded order total
createdAtDateTime!Creation time

A successful delivery normally ends with FULFILLED and PAID. Intermediate states describe processing; the client must not send another payment or create a manual delivery.

Exchange example​

Request
documentId: purchaseGameCurrency
{
"documentId": "purchaseGameCurrency",
"variables": {
"input": {
"orderRequestId": "01910000-0000-7000-8000-000000000108",
"paymentRequestId": "01910000-0000-7000-8000-000000000109",
"quoteId": "01910000-0000-7000-8000-000000000102"
}
}
}
Response
200 OK
{
"data": {
"purchaseGameCurrency": {
"orderId": "01910000-0000-7000-8000-000000000103",
"quoteId": "01910000-0000-7000-8000-000000000102",
"orderStatus": "FULFILLED",
"paymentId": "01910000-0000-7000-8000-000000000104",
"paymentStatus": "PAID",
"total": {
"units": "400",
"code": "USD",
"scale": 2,
"decimal": "4.00"
},
"createdAt": "2026-08-31T10:01:00.000000Z"
}
}
}

A zero-total purchase is confirmed without payment: paymentId is null and paymentStatus is NOT_REQUIRED. The order progresses through CONFIRMED, FULFILLING and FULFILLED; confirmation does not yet mean delivery is complete.

States​

GameCurrencyOrderStatus: CONFIRMED, PENDING_PAYMENT, PAID, FULFILLING, FULFILLED, CANCELLED.

GameCurrencyPaymentStatus: NOT_REQUIRED, DEBIT_PENDING, PAID, REVERSAL_PENDING, REVERSED, REQUIRES_REVIEW.

When the calculation expires, prepare a new one and display its result. If delivery fails, the server starts the defined compensation flow; the client does not perform a manual refund.

Errors​

  • GAME_CURRENCY_REFRESH_REQUIRED - the calculation or order expired or is no longer payable; prepare again.
  • GAME_CURRENCY_INSUFFICIENT_BALANCE - the permitted player wallet has insufficient funds.
  • GAME_CURRENCY_PAYMENT_DEBT - repay the selected balance's debt, then start a new purchase.
  • GAME_CURRENCY_CONFLICT - an idempotency key was reused with different data.
  • GAME_CURRENCY_SCOPE_UNAVAILABLE - the project and server wallet scope is unavailable.
  • GAME_CURRENCY_UNAVAILABLE - the operation is temporarily unavailable.

Guest purchase​

The guest flow consists of the catalog, purchase calculation, payment-method preparation, and execution of the selected method. Every operation is public but rate-limited. Unknown and unavailable characters return the same GAME_CURRENCY_RECIPIENT_UNAVAILABLE code.

Guest catalog​

QuerydocumentId: guestGameCurrencyOffersauth: public

guestGameCurrencyOffers​

Returns only active CHARACTER_ITEM offers for the selected game server. ACCOUNT_POINTS offers require authentication and are excluded.

FieldTypeRequiredDescription
gameServerIdInt!yesSelected project game server
firstIntnoPage size from 1 to 100
afterIDnoCursor for the next page
Request
documentId: guestGameCurrencyOffers
{
"documentId": "guestGameCurrencyOffers",
"variables": {
"gameServerId": 1,
"first": 50,
"after": null
}
}
Response
200 OK
{
"data": {
"guestGameCurrencyOffers": {
"items": [
{
"id": "019c8a00-0000-7000-8000-000000000001",
"sku": "ADENA_250000",
"name": "Adena",
"description": "250,000 Adena for the selected character.",
"shortName": "Adena",
"iconReference": "/assets/images/currency/adena.webp",
"message": "Currency is delivered after payment.",
"deliveryType": "CHARACTER_ITEM",
"unitsPerPurchase": 250000,
"unitPrice": {
"units": "199",
"code": "USD",
"scale": 2,
"decimal": "1.99"
}
}
],
"pageInfo": {
"endCursor": null,
"hasNextPage": false
}
}
}
}

Character calculation​

MutationdocumentId: prepareGuestGameCurrencyPurchaseauth: public

prepareGuestGameCurrencyPurchase​

Verifies the character and creates a short-lived calculation. The email belongs to the payer and is not used as the game-currency recipient.

FieldTypeRequiredDescription
input.gameServerIdInt!yesGame server from the guest catalog
input.requestIdID!yesCalculation UUIDv7
input.offerIdID!yesOffer from the guest catalog
input.quantityInt!yesPackage count from 1 to 1,000,000
input.characterNameString!yesCharacter on the selected server
input.payerEmailString!yesPayer email
Request
documentId: prepareGuestGameCurrencyPurchase
{
"documentId": "prepareGuestGameCurrencyPurchase",
"variables": {
"input": {
"gameServerId": 1,
"requestId": "019c8a10-0000-7000-8000-000000000001",
"offerId": "019c8a00-0000-7000-8000-000000000001",
"quantity": 10,
"characterName": "Asterion",
"payerEmail": "[email protected]"
}
}
}
Response
200 OK
{
"data": {
"prepareGuestGameCurrencyPurchase": {
"id": "019c8a10-0000-7000-8000-000000000002",
"offer": {
"id": "019c8a00-0000-7000-8000-000000000001",
"sku": "ADENA_250000",
"name": "Adena",
"description": "250,000 Adena for the selected character.",
"shortName": "Adena",
"iconReference": "/assets/images/currency/adena.webp",
"message": "Currency is delivered after payment.",
"deliveryType": "CHARACTER_ITEM",
"unitsPerPurchase": 250000,
"unitPrice": {
"units": "199",
"code": "USD",
"scale": 2,
"decimal": "1.99"
}
},
"quantity": 10,
"deliveredUnits": 2500000,
"unitAmount": {
"units": "199",
"code": "USD",
"scale": 2,
"decimal": "1.99"
},
"subtotal": {
"units": "1990",
"code": "USD",
"scale": 2,
"decimal": "19.90"
},
"adjustments": [],
"total": {
"units": "1990",
"code": "USD",
"scale": 2,
"decimal": "19.90"
},
"hasSavings": false,
"delivery": {
"type": "CHARACTER",
"accountName": null,
"characterName": "Asterion"
},
"expiresAt": "2026-09-01T10:15:00.000000Z"
}
}
}

Errors​

  • GAME_CURRENCY_RECIPIENT_UNAVAILABLE - the recipient is unknown or unavailable.
  • GAME_CURRENCY_OFFER_UNAVAILABLE - the offer is disabled or does not support guest checkout.
  • GAME_CURRENCY_RATE_LIMITED - the rate limit was exceeded; retry after the returned delay.
  • GAME_CURRENCY_CONFLICT - a UUIDv7 was reused with different data.

Payment methods​

MutationdocumentId: prepareGuestGameCurrencyCheckoutauth: public

prepareGuestGameCurrencyCheckout​

Creates an order awaiting payment from an active calculation and returns eligible methods with a separate payment calculation for each method.

FieldTypeRequiredDescription
input.gameServerIdInt!yesThe same game server
input.orderRequestIdID!yesOrder-creation UUIDv7
input.paymentRequestIdID!yesPayment-preparation UUIDv7
input.quoteIdID!yesActive purchase calculation
input.characterNameString!yesThe same character
input.payerEmailString!yesThe same payer email
input.payerCountryStringnoTwo-letter country code when available
Request
documentId: prepareGuestGameCurrencyCheckout
{
"documentId": "prepareGuestGameCurrencyCheckout",
"variables": {
"input": {
"gameServerId": 1,
"orderRequestId": "019c8a10-0000-7000-8000-000000000003",
"paymentRequestId": "019c8a10-0000-7000-8000-000000000004",
"quoteId": "019c8a10-0000-7000-8000-000000000002",
"characterName": "Asterion",
"payerEmail": "[email protected]",
"payerCountry": "DE"
}
}
}
Response
200 OK
{
"data": {
"prepareGuestGameCurrencyCheckout": {
"orderId": "019c8a10-0000-7000-8000-000000000005",
"quoteId": "019c8a10-0000-7000-8000-000000000002",
"orderStatus": "PENDING_PAYMENT",
"intent": {
"id": "019c8a10-0000-7000-8000-000000000006",
"status": "OPEN",
"expiresAt": "2026-09-01T10:20:00.000000Z"
},
"methods": [
{
"id": "019c8a10-0000-7000-8000-000000000007",
"code": "paygol",
"name": "PayGol",
"iconAssetId": "payment-method-paygol",
"paymentQuote": {
"id": "019c8a10-0000-7000-8000-000000000008",
"paymentAmount": {
"units": "1990",
"code": "EUR",
"scale": 2,
"decimal": "19.90"
},
"destinationAmount": {
"units": "1990",
"code": "USD",
"scale": 2,
"decimal": "19.90"
},
"payerFee": {
"units": "0",
"code": "EUR",
"scale": 2,
"decimal": "0.00"
},
"expiresAt": "2026-09-01T10:15:00.000000Z"
}
}
]
}
}
}

When no method is eligible, the operation returns GAME_CURRENCY_METHODS_UNAVAILABLE and does not create a payment attempt.

Start payment​

MutationdocumentId: startGuestGameCurrencyCheckoutauth: public

startGuestGameCurrencyCheckout​

Starts the selected method using its active calculation. Every recipient field must match the prepared order.

FieldTypeRequiredDescription
input.gameServerIdInt!yesOrder game server
input.requestIdID!yesStart UUIDv7
input.orderIdID!yesPrepared order
input.quoteIdID!yesOrder purchase calculation
input.characterNameString!yesVerified character
input.payerEmailString!yesPayer email
input.methodProfileIdID!yesmethods[].id
input.paymentQuoteIdID!yesmethods[].paymentQuote.id
Request
documentId: startGuestGameCurrencyCheckout
{
"documentId": "startGuestGameCurrencyCheckout",
"variables": {
"input": {
"gameServerId": 1,
"requestId": "019c8a10-0000-7000-8000-000000000009",
"orderId": "019c8a10-0000-7000-8000-000000000005",
"quoteId": "019c8a10-0000-7000-8000-000000000002",
"characterName": "Asterion",
"payerEmail": "[email protected]",
"methodProfileId": "019c8a10-0000-7000-8000-000000000007",
"paymentQuoteId": "019c8a10-0000-7000-8000-000000000008"
}
}
}
Response
200 OK
{
"data": {
"startGuestGameCurrencyCheckout": {
"orderId": "019c8a10-0000-7000-8000-000000000005",
"quoteId": "019c8a10-0000-7000-8000-000000000002",
"orderStatus": "PENDING_PAYMENT",
"intent": {
"id": "019c8a10-0000-7000-8000-000000000006",
"status": "PROCESSING",
"expiresAt": "2026-09-01T10:20:00.000000Z"
},
"attempt": {
"id": "019c8a10-0000-7000-8000-000000000010",
"status": "REQUIRES_CUSTOMER_ACTION",
"expiresAt": "2026-09-01T10:15:00.000000Z"
},
"action": {
"kind": "REDIRECT",
"expiresAt": "2026-09-01T10:15:00.000000Z",
"redirect": {
"url": "https://payments.example/checkout/019c8a10"
},
"formPost": null,
"qrCode": null,
"deepLink": null,
"wait": null
}
}
}
}

action.kind selects one client action: REDIRECT, FORM_POST, QR_CODE, DEEP_LINK, or WAIT. Use its URL and fields unchanged until action.expiresAt.

Retry a payment action​

MutationdocumentId: retryGuestGameCurrencyCheckoutauth: public

retryGuestGameCurrencyCheckout​

Continues the same order after an interrupted redirect or temporary failure. Input fields match startGuestGameCurrencyCheckout; use a new requestId while preserving the order, calculation, recipient, and method.

Request
documentId: retryGuestGameCurrencyCheckout
{
"documentId": "retryGuestGameCurrencyCheckout",
"variables": {
"input": {
"gameServerId": 1,
"requestId": "019c8a10-0000-7000-8000-000000000011",
"orderId": "019c8a10-0000-7000-8000-000000000005",
"quoteId": "019c8a10-0000-7000-8000-000000000002",
"characterName": "Asterion",
"payerEmail": "[email protected]",
"methodProfileId": "019c8a10-0000-7000-8000-000000000007",
"paymentQuoteId": "019c8a10-0000-7000-8000-000000000008"
}
}
}
Response
200 OK
{
"data": {
"retryGuestGameCurrencyCheckout": {
"orderId": "019c8a10-0000-7000-8000-000000000005",
"quoteId": "019c8a10-0000-7000-8000-000000000002",
"orderStatus": "PENDING_PAYMENT",
"intent": {
"id": "019c8a10-0000-7000-8000-000000000006",
"status": "PROCESSING",
"expiresAt": "2026-09-01T10:20:00.000000Z"
},
"attempt": {
"id": "019c8a10-0000-7000-8000-000000000012",
"status": "PENDING_PROVIDER",
"expiresAt": "2026-09-01T10:15:00.000000Z"
},
"action": {
"kind": "WAIT",
"expiresAt": "2026-09-01T10:15:00.000000Z",
"redirect": null,
"formPost": null,
"qrCode": null,
"deepLink": null,
"wait": {
"recommendedPollAfterSeconds": 3
}
}
}
}
}

Repeating the same UUIDv7 with identical data is idempotent. Reusing it with different data returns GAME_CURRENCY_CONFLICT. An expired calculation or method returns GAME_CURRENCY_REFRESH_REQUIRED.

Delivery rules​

  • ACCOUNT_POINTS delivers currency to the verified game account; characterName is not used.
  • CHARACTER_ITEM delivers an item to the selected character. After sign-in, choose a character from the game account; for a guest purchase, enter the character's name on the selected server.
  • Offers and recipients are limited to the project and server resolved from the session.
  • Repeating a request with the same UUIDv7 does not create another order, debit, or delivery.

The complete GameCurrency* structures are in the API schema reference. Player balance top-up is described in Player balance top-up.

Free guest purchase​

MutationdocumentId: confirmFreeGuestGameCurrencyPurchaseauth: public

confirmFreeGuestGameCurrencyPurchase​

Confirms a purchase whose calculated total is zero. Call after the guest explicitly presses Buy, using the active guest purchase calculation. Do not request payment methods or start payment for this purchase.

input fieldTypeMeaning
gameServerIdInt!Selected game server.
orderRequestIdID!UUIDv7 for order creation.
confirmationRequestIdID!A different UUIDv7 for confirmation.
quoteIdID!Active zero-total calculation ID.
characterNameString!Calculation recipient, up to 64 characters.
payerEmailString!Calculation email, up to 254 characters.
Request
documentId: confirmFreeGuestGameCurrencyPurchase
{
"documentId": "confirmFreeGuestGameCurrencyPurchase",
"variables": {
"input": {
"gameServerId": 1,
"orderRequestId": "019bf3dd-b08b-7000-8000-000000000310",
"confirmationRequestId": "019bf3dd-b08b-7000-8000-000000000311",
"quoteId": "019bf3dd-b08b-7000-8000-000000000312",
"characterName": "Asterion",
"payerEmail": "[email protected]"
}
}
}
Response
200 OK
{
"data": {
"confirmFreeGuestGameCurrencyPurchase": {
"orderId": "019bf3dd-b08b-7000-8000-000000000313",
"quoteId": "019bf3dd-b08b-7000-8000-000000000312",
"orderStatus": "CONFIRMED",
"paymentId": null,
"paymentStatus": "NOT_REQUIRED",
"total": {
"units": "0",
"code": "ELX",
"scale": 3,
"decimal": "0.000"
},
"createdAt": "2026-09-13T10:00:00Z"
}
}
}

For a retry, keep both request identifiers and all other fields unchanged. Prepare a new calculation if it expires. The result is GameCurrencyPurchase, with paymentId: null and paymentStatus: NOT_REQUIRED. CONFIRMED means the confirmation was accepted, not that delivery has completed.