Skip to main content

Player Wallet Top-Up

See Player Balance Top-Up for the related user flow.

The top-up flow consists of read-only method discovery followed by two execution steps:

  1. playerWalletTopUpMethods performs a read-only lookup of methods matching the amount.
  2. preparePlayerWalletTopUp or prepareGuestPlayerWalletTopUp creates an intent and an immutable calculation for the selected method.
  3. startPlayerWalletTopUp or startGuestPlayerWalletTopUp starts the selected calculation and returns the action the client must perform.

To retrieve payment methods, submit the amount and, when available, the payer country. This request does not require a session. Authenticated mutations top up the current player's balance; guest mutations require the recipient email. Project settings determine whether the balance is project-wide or per-server. All mutations use UUIDv7 request identifiers. The Origin header must match an origin registered for the project.

Top-ups remain available while a payment debt is outstanding. Main-balance credits repay the debt first; any remainder becomes available for purchases. Bonus credits do not repay debt. Read the current state from me.paymentDebt, me.purchasesRestricted, or the refreshBalance query. Once the debt is fully repaid, purchasesRestricted becomes false; submit a previously rejected purchase again with a new requestId.

Discover payment methods​

QuerydocumentId: playerWalletTopUpMethodsauth: optional

playerWalletTopUpMethods​

Input​

FieldTypeRequiredDescription
amountString!yesA positive decimal amount without exponent notation or group separators
payerCountryStringnoA two-letter country code such as US

Result​

PlayerWalletTopUpMethodDiscovery contains method cards:

FieldTypeDescription
methodProfileIdID!Method-profile identifier in the current project
methodCodeString!Uppercase method code such as BANK_CARD or PAYGOL; use displayName for the visible label
displayNameString!Localized method name
iconAssetIdIDIcon identifier when configured

The query creates no intent, calculation, or payment attempt and reserves no funds. Repeat it after the amount, country, or balance context changes. Pass the selected methodProfileId to the protected prepare mutation.

Exchange example​

Request
documentId: playerWalletTopUpMethods
{
"documentId": "playerWalletTopUpMethods",
"variables": {
"input": {
"amount": "10.00",
"payerCountry": "US"
}
}
}
Response
200 OK
{
"data": {
"playerWalletTopUpMethods": {
"methods": [
{
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"methodCode": "BANK_CARD",
"displayName": "Bank card",
"iconAssetId": "payment-method-card"
},
{
"methodProfileId": "01910000-0000-7000-8000-000000000006",
"methodCode": "SBP",
"displayName": "Fast Payments System",
"iconAssetId": null
}
]
}
}
}

When no configured profile matches, the operation returns TOP_UP_METHODS_UNAVAILABLE.

Prepare a top-up​

MutationdocumentId: preparePlayerWalletTopUpauth: Bearer session

preparePlayerWalletTopUp​

Input​

FieldTypeRequiredDescription
requestIdID!yesA new UUIDv7. Repeating the same request with the same payload returns the original result
amountString!yesA positive decimal amount without exponent notation or group separators
methodProfileIdID!yesMethod profile selected from playerWalletTopUpMethods
payerCountryStringnoA two-letter country code such as US

Result​

PlayerWalletTopUpPreparation contains:

FieldTypeDescription
checkoutIdID!User-flow identifier passed to the start operation
intentPlayerWalletTopUpIntent!Created intent and destination amount
methods[PlayerWalletTopUpMethod!]!The selected method and its calculation; a successful preparation contains one item

Every PlayerWalletTopUpMoney contains atomic units, asset code, scale, and a ready-to-display decimal value. Render money from decimal; do not convert it through float.

Exchange example​

Request
documentId: preparePlayerWalletTopUp
{
"documentId": "preparePlayerWalletTopUp",
"variables": {
"input": {
"requestId": "01910000-0000-7000-8000-000000000001",
"amount": "10.00",
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"payerCountry": "US"
}
}
}
Response
200 OK
{
"data": {
"preparePlayerWalletTopUp": {
"checkoutId": "01910000-0000-7000-8000-000000000001",
"intent": {
"id": "01910000-0000-7000-8000-000000000002",
"status": "OPEN",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"createdAt": "2026-08-29T10:00:00.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"completedAt": null
},
"methods": [
{
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"methodCode": "BANK_CARD",
"displayName": "Bank card",
"iconAssetId": "payment-method-card",
"quote": {
"id": "01910000-0000-7000-8000-000000000004",
"sequence": 1,
"expiresAt": "2026-08-29T10:10:00.000000Z",
"paymentAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"payerFee": {
"units": "30",
"code": "USD",
"scale": 2,
"decimal": "0.30"
},
"conversion": {
"numerator": "1",
"denominator": "1",
"roundingMode": "HALF_UP"
},
"fees": [
{
"kind": "FIXED",
"amount": {
"units": "30",
"code": "USD",
"scale": 2,
"decimal": "0.30"
}
}
],
"funding": {
"baseAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"bonusAmount": {
"units": "300",
"code": "ELX",
"scale": 2,
"decimal": "3.00"
},
"totalAmount": {
"units": "1300",
"code": "ELX",
"scale": 2,
"decimal": "13.00"
},
"components": [
{
"source": "PAYMENT_PROMOTION",
"amount": {
"units": "100",
"code": "ELX",
"scale": 2,
"decimal": "1.00"
},
"percentage": 10,
"decidedAt": "2026-08-29T10:00:00.000000Z",
"validUntil": "2026-08-29T10:10:00.000000Z",
"grantLifetimeSeconds": null
},
{
"source": "LOYALTY",
"amount": {
"units": "200",
"code": "ELX",
"scale": 2,
"decimal": "2.00"
},
"percentage": 20,
"decidedAt": "2026-08-29T10:00:00.000000Z",
"validUntil": null,
"grantLifetimeSeconds": 86400
}
]
}
}
}
]
}
}
}

PAYMENT_PROMOTION and LOYALTY are displayed as separate rows. The funding calculation is frozen in the quote field: the client does not add percentages or replace totalAmount with a locally calculated value.

Start payment​

MutationdocumentId: startPlayerWalletTopUpauth: Bearer session

startPlayerWalletTopUp​

Input​

FieldTypeDescription
requestIdID!A new start UUIDv7 used for idempotent replay
checkoutIdID!Value returned by preparation
methodProfileIdID!Selected method from methods
quoteIdID!Calculation identifier for the selected method

Repeating the operation with the same four values is safe. Reusing requestId with different values returns a conflict.

Exchange example​

Request
documentId: startPlayerWalletTopUp
{
"documentId": "startPlayerWalletTopUp",
"variables": {
"input": {
"requestId": "01910000-0000-7000-8000-000000000010",
"checkoutId": "01910000-0000-7000-8000-000000000001",
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"quoteId": "01910000-0000-7000-8000-000000000004"
}
}
}
Response
200 OK
{
"data": {
"startPlayerWalletTopUp": {
"checkoutId": "01910000-0000-7000-8000-000000000001",
"intent": {
"id": "01910000-0000-7000-8000-000000000002",
"status": "PROCESSING",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"createdAt": "2026-08-29T10:00:00.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"completedAt": null
},
"attempt": {
"id": "01910000-0000-7000-8000-000000000005",
"status": "REQUIRES_CUSTOMER_ACTION",
"createdAt": "2026-08-29T10:00:01.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z"
},
"action": {
"kind": "REDIRECT",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"redirect": {
"url": "https://checkout.example.test/pay/123"
},
"formPost": null,
"qrCode": null,
"deepLink": null,
"wait": null
}
}
}
}

Client actions​

kindPopulated fieldAction
REDIRECTredirect.urlNavigate to the HTTPS checkout page
FORM_POSTformPost.url, formPost.fieldsBuild and immediately submit a POST form
QR_CODEqrCode.payload, optional imageUrlRender the QR code; payload remains authoritative
DEEP_LINKdeepLink.urlRender a QR code and an open-app button
WAITwait.recommendedPollAfterSecondsRepeat the same start operation after the specified delay

Only the object matching kind is populated. action: null means that no external action remains; use intent.status for the outcome.

Prepare a guest top-up​

MutationdocumentId: prepareGuestPlayerWalletTopUpauth: public

prepareGuestPlayerWalletTopUp​

Guest preparation is available without signing in. Submit the recipient email, amount, and selected payment method.

Input​

FieldTypeRequiredDescription
requestIdID!yesA new preparation UUIDv7; repeating the same payload returns the original result
recipientEmailString!yesRecipient account email
amountString!yesA positive decimal amount without exponent notation or group separators
methodProfileIdID!yesMethod profile returned by playerWalletTopUpMethods
payerCountryStringnoA two-letter country code such as US

Result​

The operation returns the same PlayerWalletTopUpPreparation as authenticated preparation: checkoutId, intent, and one method with its quote field.

Exchange example​

Request
documentId: prepareGuestPlayerWalletTopUp
{
"documentId": "prepareGuestPlayerWalletTopUp",
"variables": {
"input": {
"requestId": "01910000-0000-7000-8000-000000000011",
"recipientEmail": "[email protected]",
"amount": "10.00",
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"payerCountry": "US"
}
}
}
Response
200 OK
{
"data": {
"prepareGuestPlayerWalletTopUp": {
"checkoutId": "01910000-0000-7000-8000-000000000011",
"intent": {
"id": "01910000-0000-7000-8000-000000000012",
"status": "OPEN",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"expiresAt": "2026-08-29T10:15:00.000000Z"
},
"methods": [
{
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"methodCode": "BANK_CARD",
"displayName": "Bank card",
"iconAssetId": "payment-method-card",
"quote": {
"id": "01910000-0000-7000-8000-000000000013",
"sequence": 1,
"expiresAt": "2026-08-29T10:10:00.000000Z",
"paymentAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"payerFee": {
"units": "30",
"code": "USD",
"scale": 2,
"decimal": "0.30"
},
"funding": null
}
}
]
}
}
}

An unavailable recipient returns TOP_UP_RECIPIENT_UNAVAILABLE. If no payment method matches the amount or context, the operation returns TOP_UP_METHODS_UNAVAILABLE.

Start a guest payment​

MutationdocumentId: startGuestPlayerWalletTopUpauth: public

startGuestPlayerWalletTopUp​

Starts guest payment with the recipient, method and valid calculation returned by preparation. Pass them unchanged.

Input​

FieldTypeRequiredDescription
requestIdID!yesA new start UUIDv7
checkoutIdID!yesValue returned by guest preparation
recipientEmailString!yesThe same recipient email used for preparation
methodProfileIdID!yesSelected method from preparation
quoteIdID!yesCalculation identifier for the selected method

Result and client actions​

The operation returns the same PlayerWalletTopUpCheckout as authenticated start: intent status, attempt, and one of REDIRECT, FORM_POST, QR_CODE, DEEP_LINK, or WAIT. See Client actions for the action fields.

Exchange example​

Request
documentId: startGuestPlayerWalletTopUp
{
"documentId": "startGuestPlayerWalletTopUp",
"variables": {
"input": {
"requestId": "01910000-0000-7000-8000-000000000014",
"checkoutId": "01910000-0000-7000-8000-000000000011",
"recipientEmail": "[email protected]",
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"quoteId": "01910000-0000-7000-8000-000000000013"
}
}
}
Response
200 OK
{
"data": {
"startGuestPlayerWalletTopUp": {
"checkoutId": "01910000-0000-7000-8000-000000000011",
"intent": {
"id": "01910000-0000-7000-8000-000000000012",
"status": "PROCESSING",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"expiresAt": "2026-08-29T10:15:00.000000Z"
},
"attempt": {
"id": "01910000-0000-7000-8000-000000000015",
"status": "REQUIRES_CUSTOMER_ACTION",
"createdAt": "2026-08-29T10:00:01.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z"
},
"action": {
"kind": "REDIRECT",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"redirect": {
"url": "https://checkout.example.test/pay/123"
},
"formPost": null,
"qrCode": null,
"deepLink": null,
"wait": null
}
}
}
}

Use the start result for guest payment; there is no separate guest-history operation.

Payment history​

QuerydocumentId: playerPaymentHistoryauth: Bearer session

playerPaymentHistory​

Returns payments owned by the current player with cursor pagination. The statuses filter is optional; an empty list means every status.

FieldTypeRequiredDescription
firstInt!yesPage size from 1 to 100
afterIDnoendCursor from the previous page
statuses[PlayerPaymentStatus!]noStatuses to include
Request
documentId: playerPaymentHistory
{
"documentId": "playerPaymentHistory",
"variables": {
"first": 20,
"after": null,
"statuses": [
"PROCESSING",
"SETTLED"
]
}
}
Response
200 OK
{
"data": {
"playerPaymentHistory": {
"items": [
{
"id": "01910000-0000-7000-8000-000000000002",
"purpose": "PLAYER_WALLET_CREDIT",
"status": "SETTLED",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"quotedAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"settledAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"method": {
"code": "card",
"displayName": "Bank card",
"iconAssetId": "payment-method-card"
},
"description": "Balance top-up",
"createdAt": "2026-08-29T10:00:00.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"completedAt": "2026-08-29T10:02:10.000000Z"
}
],
"pageInfo": {
"endCursor": "01910000-0000-7000-8000-000000000002",
"hasNextPage": false
}
}
}
}

One payment​

QuerydocumentId: playerPaymentauth: Bearer session

playerPayment​

Accepts a public paymentId from history and returns the same payment snapshot. If the payment is not found, the result is PLAYER_PAYMENT_NOT_FOUND.

Request
documentId: playerPayment
{
"documentId": "playerPayment",
"variables": {
"paymentId": "01910000-0000-7000-8000-000000000002"
}
}
Response
200 OK
{
"data": {
"playerPayment": {
"id": "01910000-0000-7000-8000-000000000002",
"purpose": "PLAYER_WALLET_CREDIT",
"status": "SETTLED",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"quotedAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"settledAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"method": {
"code": "card",
"displayName": "Bank card",
"iconAssetId": "payment-method-card"
},
"description": "Balance top-up",
"createdAt": "2026-08-29T10:00:00.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"completedAt": "2026-08-29T10:02:10.000000Z"
}
}
}

States​

PlayerWalletTopUpIntentStatus: OPEN, PROCESSING, SETTLED, CANCELLED, EXPIRED.

PlayerWalletTopUpAttemptStatus: CREATED, REQUIRES_CUSTOMER_ACTION, PENDING_PROVIDER, AUTHORIZED, CAPTURED, DECLINED, CANCELLED, EXPIRED, REVIEW_REQUIRED.

An expired calculation cannot be started. Prepare again and display the new result. A successful callback credits the wallet once; repeating the callback cannot create another credit.

Errors​

CodeClient meaning
TOP_UP_INVALID_REQUESTInvalid input format
TOP_UP_INVALID_AMOUNTAmount is outside the allowed range
TOP_UP_ORIGIN_NOT_ALLOWEDCurrent Origin is not registered for the project
TOP_UP_RECIPIENT_UNAVAILABLERecipient is unknown, blocked, or cannot receive a top-up
TOP_UP_MERCHANT_UNAVAILABLEProject top-up is disabled or not configured
TOP_UP_METHODS_UNAVAILABLENo payment method matches the amount and context
TOP_UP_REFRESH_REQUIREDIntent, method, or calculation is stale; prepare again
TOP_UP_SCOPE_UNAVAILABLEThe wallet destination cannot be resolved
TOP_UP_CONFLICTAn idempotency identifier was reused with different data
TOP_UP_RATE_LIMITEDThe limit was exceeded; extensions.retryAfterSeconds specifies the wait
TOP_UP_UNAVAILABLEThe operation is temporarily unavailable

If the calculation expires, prepare it again. For a temporary error, retain the original request parameters for retry.