Set up selling game keys

You can sell game keys via a direct link, store UI, or widget.

ItemSelling method
One copy of a game (game key).Direct link, widget, or store interface. When selling through the store interface, use the quick purchase method without creating a cart.
Several copies of the game (game keys) or several games in a cart.Store interface. Use the Site Builder or integrate the In-Game Store API.

You can sell game keys to authorized and unauthorized users.

Authorization allows you to:

You can authorize users using the Login product or your own authorization system. Detailed setup information is provided in these instructions.

Note
Users can refund the keys. After successful refund, you will get the list of the affected keys in Xsolla email. We recommend you block the access to these keys on any third-party platforms.

The following link opens the payment UI:

Copy
Full screen
Small screen
https://purchase.xsolla.com/pages/buy?type={YOUR-ITEM-TYPE}&project_id={YOUR_PROJECT_ID}&sku={YOUR-ITEM-SKU}
Note

Buying game keys via a direct link for real currency is possible only after signing a license agreement with Xsolla. To do this, in Publisher Account, go to the Agreements & Taxes > Agreements section, complete the agreement form, and wait for the confirmation. It may take up to 3 business days to review the agreement.

To test payments, you can use the test environment by adding the mode=sandbox parameter to the link.

Add the following data to this link:

  • YOUR-ITEM-TYPE — item type:
    • game — game; game_key — game on a specific platform.
    • bundle — bundle.
  • YOUR-PROJECT-ID — ID of your project from the Project settings > General settings > Project ID section in Publisher Account.
  • YOUR-ITEM-SKU — game key package SKU. To sell a game on a specific platform, use the Get games list (usually this SKU looks like unit_name_drm_sku) to get the SKU.

  • Payment UI style: theme (dark or the default light theme), size, and other parameters. Specify the ui_settings parameters in the URL and pass a settings.ui JSON-object with Base64 encoding as the value. Example of the URL with UI settings:
Copy
Full screen
Small screen
https://purchase.xsolla.com/pages/buy?type={YOUR-ITEM-TYPE}&project_id={YOUR_PROJECT_ID}&sku={YOUR-ITEM-SKU}&ui_settings=ewoJCQkic2l6ZSI6ICJzbWFsbCIsCgkJCSJ0aGVtZSI6ICJkYXJrIgoJCX0=
  • Token for passing user data. Used when selling game keys to authenticated users only. This token depends on the authentication method. Example of the URL with a token:
Copy
Full screen
Small screen
https://purchase.xsolla.com/pages/buy?type={YOUR-ITEM-TYPE}&project_id={YOUR_PROJECT_ID}&sku={YOUR_ITEM_SKU}&xsolla_login_token={ACCESS_TOKEN}
  • The mode=sandbox parameter for payment tests. You can use test bank cards to complete payments.
Note
When making a payment, the Xsolla server sends a request to the webhook URL to verify that the user exists in the game. To avoid errors when testing payment, go to Publisher Account > Project settings > Webhooks and set the switch to OFF. If you want to use webhooks, implement successful processing of a User validation webhook.
  1. Example of the URL for testing:
Copy
Full screen
Small screen
https://purchase.xsolla.com/pages/buy?type={YOUR-ITEM-TYPE}&project_id={YOUR_PROJECT_ID}&sku={YOUR-ITEM-SKU}&mode=sandbox

Selling via store UI

You can sell game keys through the store interface. To create a store, you can:

To sell game keys packages using the In-Game Store API:

  1. To display a catalog, use the Get games list method.
  2. Implement the purchase of game keys:

Choose a suitable authentication option for the methods to work correctly.
Note
When selling a game through the In-Game Store API, you should implement a feature that allows players to select a specific platform on the client. To get the SKU, pass the value of the items.unit_items.sku parameter from the request to get the list of games.

Selling via widget

You can add a widget to your page to sell game keys and customize it. To copy the widget code, go to the Widget customization section after creating the keys package in your Publisher Account.

If a game is sold on a single platform, the widget will display the game price specific to that platform.

Example: Buy now for $10.

If a game is sold on multiple platforms, the widget will display the lowest price among the platforms.

Example: Get from $10.

In the order creation window, the user can see prices for all platforms and make a choice.

You can also display the price for a specific platform in the widget by specifying the platform SKU in the drm parameter.

Widget code example:

Copy
Full screen
Small screen
    <div id="xsolla-buy-button-widget"></div>
          <script>
              var options = {
                  project_id: "101010",
                  sku: "my_key",
                  user: {
                      auth: "9qs9VyCIQQXBlzJQcfETIKWZDvhi4Sz1"
                  },
                  drm: "steam",
                  item_type: "unit",
                  api_settings: {
                      sandbox: true,
                  },
                  widget_ui: {
                      target_element: "#xsolla-buy-button-widget",
                      theme: {
                          foreground: "green",
                          background: "light"
                      },
                  },
    
                 payment_widget_ui: {
                      lightbox: {
                          height: '700px',
                          spinner: 'round'
                      }
                }
              };
              var s = document.createElement('script');
              s.type = "text/javascript";
              s.async = true;
              s.src = "https://cdn.xsolla.net/embed/buy-button/3.1.8/widget.min.js";
              s.addEventListener('load', function (e) {
                  var widgetInstance = XBuyButtonWidget.create(options);
              }, false);
              var head = document.getElementsByTagName('head')[0];
              head.appendChild(s);
          </script>
          <style>
              #xsolla-buy-button-widget {
    
              /* place code for button positioning here */
                margin: 10px  
              }
    
              /* Styles the button itself */
              .x-buy-button-widget.x-buy-button-widget__tiny
                .x-buy-button-widget-payment-button {
                background-color: #ff005b;
                color: black;
              }     
          </style>
    
    Note
    Widget parameters

    ParameterTypeDescription
    project_id
    integerID of the project in which game keys or bundles with game keys, in-game items or bundles with items, are uploaded.
    item_type
    stringItem type. Can take values of virtual_good, virtual_currency, game_key, unit. The unit type is used when there are multiple platforms for distributing the game.
    sku
    stringUnique item ID.
    drm
    stringDistribution platform SKU, for example, steam. Allows displaying the price for a specific platform.
    api_settings
    objectEnvironment and host configuration settings:
    • host — host for performing requests. The default value is — store.xsolla.com
    • api_host — host for performing API requests. The default value is — store.xsolla.com/api
    • sandbox — set true value, to test the payment process. sandbox-secure.xsolla.com will be used instead secure.xsolla.com to process payments (see Testing the payment process)
    user
    objectAn object with user data.
    user.auth
    stringUser authorization token: JSON Web Token or Pay Station access token.
    user.locale
    stringUser locale. Determines the language of the button text and payment interface. It is used a two-letter language code based on ISO_639-1.
    widget_ui.theme
    objectThe color theme of the widget, determining its appearance. It can take values {foreground:[‘blue’,‘red’,‘green’,‘gold’], background:[’light’,‘dark’]}
    widget_ui.template
    stringTemplate. Possible values:
    • standard (default) - includes game image, title, and stylized button
    • simple — only displays the button without any styles applied
    widget_ui.target_element
    stringElement of the page, where the widget should be rendered (jQuery selector should be used, for example #widget-example). Required

    Parameters that determine the appearance of the payment interface

    ParameterTypeDescription
    payment_ui
    objectPayment interface appearance parameters.
    payment_widget_ui
    objectAn object with parameters that determine the appearance of the payment interface.
    payment_widget_ui.lightbox
    objectAn object with options for the modal window in which the payment interface is opened.
    payment_widget_ui.lightbox.width
    stringLightbox frame width. If null, depends on Pay Station width. Default is null.
    payment_widget_ui.lightbox.height
    stringLightbox frame height. If null, depends on Pay Station height. Default is 100%.
    payment_widget_ui.lightbox.zIndex
    integerDefines arrangement order. Default is 1000.
    payment_widget_ui.lightbox.overlayOpacity
    integerOpacity of the widget’s background (0 — completely ​​transparent, 1 — completely opaque). The default value is 60% (.6).
    payment_widget_ui.lightbox.overlayBackground
    stringOverlay background color. Default is #000000.
    payment_widget_ui.lightbox.contentBackground
    stringFrame background color. Default is #ffffff. Note that these color changes do not affect the Pay Station iframe itself, only the settings of the lightbox that hold it.
    payment_widget_ui.lightbox.spinner
    stringType of animated loading indicator. Can be xsolla or round. Default is xsolla.
    payment_widget_ui.lightbox.spinnerColor
    stringSpinner color. No default value.
    payment_widget_ui.childWindow
    objectSettings for the child window in which the payment interface is opened. Works for the mobile version.
    payment_widget_ui.childWindow.target
    stringThe property that determines where the child window should be opened. It can take values of _blank, _self, _parent. The default value is — _blank.

    Widget methods

    • var widgetInstance = XBuyButtonWidget.create(options) — create the widget instance and render it on the page.
    • widgetInstance.on(event, handler) — attaches an event handler function for the event to the widget.
      • event (string) — event type.
      • handler (function) — a function to execute when the event is triggered.
    • widgetInstance.off(event, handler) — removes an event handler.
      • event (string) — event type.
      • handler (function) — a handler function previously attached for the event.

    List of events:

    ParameterDescription
    initWidget initialized.
    openWidget opened.
    loadPayment UI (Pay Station) loaded.
    closePayment UI (Pay Station) closed.
    statusUser is on the status page.
    status-invoiceUser is on the status page; payment in progress.
    status-deliveringEvent when the user was moved on the status page, payment was completed, and we’re sending payment notification.
    status-doneUser is on the status page; payment credited to the user’s account.
    status-troubledEvent when the user was moved on the status page, but the payment failed.

    You can access the list of events using XBuyButtonWidget.eventTypes object.

    Button customization

    1. Open your project in Publisher Account.
    2. In the side menu, click Store.
    3. In the Game Keys pane, click Configure.
    4. Select a game key and go to the Widget customization tab.
    Note
    If there are no game keys, create a new one.
    1. In the Customize block, select the background color.
    Note
    You can also modify the theme object in code so that the parameter background has an empty string as a value.
    1. When you add the widget code to your page, it includes inherited styles. Add the styles below to override these styles.
    Notice
    Added these in a style tag below the script tag that you got from the Widget customization tab for CSS inheritance/priority reasons.
    Copy
    Full screen
    Small screen
    /* This should be used for button positioning but note this technically repositions the entire widget */
    #xsolla-buy-button-widget {
      /* place code for button positioning here */
    }
    
    /* Styles the button itself */
    .x-buy-button-widget.x-buy-button-widget__tiny
      .x-buy-button-widget-payment-button {
      background-color: #ff005b;
      color: black;
    }
    
    /* Button on hover */
    .x-buy-button-widget.x-buy-button-widget__tiny
      .x-buy-button-widget-payment-button:hover {
      background-color: #ff005b;
    }
    
    /* The following are style overrides to leave you with just the button */
    
    /* space immediately surrounding button */
    .x-buy-button-widget-button-block.x-buy-button-widget-button-block__light {
      background-color: white;
    }
    
    /* space above button (including game title area) */
    .x-buy-button-widget.x-buy-button-widget__tiny
      .x-buy-button-widget-game-logo {
      height: 200px;
      background-image: none !important;
      background-color: white;
    }
    
     /* Game title (located right above button) */
    .x-buy-button-widget-game-name.x-buy-button-widget-game-name__light {
      display: none !important;
    }
    
    Notice
    • The id/class names above and the code snippet are used in conjunction with the copied widget code (the image at step 5). For this reason, it is important that you implement the copied widget code.
    • You can use the code above as is or modify the code based on your scenario. The code comments (lines 1, 3, 5, 11, 16, 18, 22, 29) are there to help determine what each CSS rule targets and assist in future styling. For example, if you want just the button (and not the entire widget), you’ll need to substitute the background color of your page in the places below where the color is white — lines 20 and 27.

    How to create multiple buttons or SKUs

    You can refer to Xsolla Pay2Play Widget Simple Integration 4 buttons for a code example on how this is accomplished using the Pay2Play widget.

    The structure is similar to the Buy Button widget code. An example of a migration:

    Copy
    Full screen
    Small screen
    <div id="xsolla-buy-button-widget"></div>
    <div id="xsolla-buy-button-widget-2"></div>
        <script>
          var options = {
            project_id: "191204",
            sku: "789",
            item_type: "unit",
            api_settings: {
              sandbox: false,
            },
            widget_ui: {
              target_element: "#xsolla-buy-button-widget",
              theme: {
                foreground: "gold",
                background: "",
              },
            },
            payment_widget_ui: {
              lightbox: {
                height: "700px",
                spinner: "round",
              },
            },
          };
          // options for second buy button - note the different SKU and target_element
          var options2 = {
            project_id: "191204",
            sku: "123",
            item_type: "unit",
            api_settings: {
              sandbox: false,
            },
            widget_ui: {
              target_element: "#xsolla-buy-button-widget-2",
              theme: {
                foreground: "gold",
                background: "",
              },
            },
            payment_widget_ui: {
              lightbox: {
                height: "700px",
                spinner: "round",
              },
            },
          };
          var s = document.createElement("script");
          s.type = "text/javascript";
          s.async = true;
          s.src = "https://cdn.xsolla.net/embed/buy-button/3.1.4/widget.min.js";
    
    // one event listener per widget instance. repeat for more buttons, passing in different SKUs
          s.addEventListener(
            "load",
            function (e) {
              var widgetInstance = XBuyButtonWidget.create(options);
            },
            false
          );
          s.addEventListener(
            "load",
            function (e) {
              var widgetInstance2 = XBuyButtonWidget.create(options2);
            },
            false
          );
          var head = document.getElementsByTagName("head")[0];
          head.appendChild(s);
        </script>
    
    Notice
    • Lines 1 and 2 — one div per button, each with a unique ID.
    • Starting on line 26 are the options for the second button (laid out in the options2 object). You will need a set of options like the ones above for each Buy button. Note the different sku (line28) and target_element (line 34, targeting the div on line 2).
    Was this article helpful?
    Thank you!
    Is there anything we can improve? Message
    We’re sorry to hear that
    Please explain why this article wasn’t helpful to you. Message
    Thank you for your feedback!
    We’ll review your message and use it to help us improve your experience.
    Last updated: November 8, 2024

    Found a typo or other text error? Select the text and press Ctrl+Enter.

    Report a problem
    We always review our content. Your feedback helps us improve it.
    Provide an email so we can follow up
    Thank you for your feedback!