How to automate catalog updates

You can automate the creation and updating of the catalog with In-Game Store API calls. With automation, you can keep your catalog up to date without spending a lot of time on it. Catalog automate allows you to create and update items and promotions and import data from external systems.

This reduces the time it takes to maintain and update:

  • catalogs that contain a lot of items
  • promotions of any type
  • country-based prices

Notice

To maintain user engagement, it’s important to keep the item catalog up to date on the Xsolla side after its creation. We recommend updating the catalog on the Xsolla side when updates occur on your side, such as when adding products or changing prices.

You can:

Basic authorization is used for API calls to create and update items and promotions. Pass the Authorization:Basic <your_authorization_basic_key>, where <your_authorization_basic_key> is the merchant ID:API key pair encoded according to the Base64 standard. Go to Publisher Account to find these parameters:

  • Merchant ID is shown:
    • In the Company settings > Company section.
    • In the URL in the browser address bar on any Publisher Account page. The URL has the following format: https:​//publisher.xsolla.com/<merchant ID>/<Publisher Account section>.

  • API key is shown in Publisher Account only once when it is created and must be stored on your side. You can create a new key in the following section:
    • Company settings > API keys
    • Project settings > API keys

Create and update items

If you need to create numerous items, you can create a script that calls the API method of the required item type the necessary number of times.

Notice

The list of parameters returned in response to items request differs from the list of parameters you need to pass when updating the catalog. In addition to the required and updated parameters, pass parameters in the items update method that are returned in response to the items request.

Example:

In the Get virtual items method, a limits object with user limit data is returned. If you want to update only the price or name of the item, pass the current data of the limits object in the Update virtual item method. If you do not pass the limits object, the limit data will be deleted when the item is updated by the Update virtual item method.

Virtual items

To update the catalog:

  1. Get data from the catalog with the Get virtual item or Get all virtual items list API methods.
  2. Pass new parameter values with the Update virtual item API method.

To create virtual items, use the Create virtual item API method.

Virtual currency

To update the catalog:

  1. Get data from the catalog with the Get virtual currency list API method.
  2. Pass new parameter values with the Update virtual currency API method.

To create virtual currency, use the Create virtual currency API method.

Virtual currency packages

To update the catalog:

  1. Get data from the catalog with the Get virtual currency package list API method.
  2. Pass new parameter values with the Update virtual currency package API method.

To create a virtual currency pack, use the Create virtual currency package API method.

Bundles

To update the catalog:

  1. Get data from the catalog with the Get list of bundles API method.
  2. Pass new parameter values with the Update bundle API method.

To create a bundle, use the Create bundle API method.
If you want to add game keys, country restrictions or prices to bundles, use the instructions.

Create and update promotions

Notice
The list of parameters that is returned from the get API methods is different from the parameters that you pass in the promotions update methods. In addition to the required and updated parameters, pass parameters from the update method that are returned in the response to the request to the method you use to get the list of promotions.

Coupons

Note
To ensure Coupon promotions work correctly, you first need to create a promotion, and then generate codes for this promotion.

To update the promotion:

  1. Get data from the catalog with Get coupon promotion or Get list of coupon promotions API methods.
  2. Pass new parameter values with the Update coupon promotion API method.
  3. Activate the promotion with the Activate coupon promotion API method.

To create a promotion, use the Create coupon promotion API methods, and then Create coupon code to create custom coupons codes or Generate coupon codes to generate random coupon codes.
To deactivate a promotion, use the Deactivate coupon promotion API method.

Promo codes

Note
For Promo code promotions to work correctly, you first need to create a promotion, and then generate codes for this promotion.

To update the promotion:

  1. Get data from the catalog with Get promo codes promotion or Get list of promo codes promotions API methods.
  2. Pass new parameter values with the Update promo codes promotion API method.
  3. Activate the promotion with the Activate promo code promotion API method.

To create a promotion, use the Create promo code promotion API methods, and then Create code for promo code promotion to create custom promo codes or Generate codes for promo code promotion to generate random promo codes.
To deactivate a promotion, use the Deactivate promo code promotion API method.

Discounts

To update the promotion:

  1. Get data from the catalog with Get item promotion or Get list of item promotions API methods.
  2. Pass new parameter values with the Update item promotion API method.
  3. Activate the promotion with the Activate promotion API method.

To create a promotion, use the Create discount promotion for item API method.
To deactivate a promotion, use the Deactivate promotion API method.

Bonuses

To update the promotion:

  1. Get data from the catalog with Get bonus promotion or Get list of bonus promotions API methods.
  2. Pass new parameter values with the Update bonus promotion API method.
  3. Activate the promotion with the Activate promotion API method.

To create a promotion, use the Create bonus promotion API method.
To deactivate a promotion, use the Deactivate promotion API method.

Automatic creation of items via API

If you need to create numerous items based on data from your system, you can automate this process using the API.

You need to:

If you want to use item groups, create them in advance via the Publisher Account interface.

If you want to use multiple types of items, they should be created in the following order:

  1. Item groups in the Publisher Account.
  2. Virtual currencies.
  3. Virtual items.
  4. Virtual currency packages.
  5. Bundles.

Next is an example of a script that repeatedly calls the Create virtual item method to create virtual items.

The script is developed using JavaScript and the JavaScript runtime — Node.js.

  1. Import the fetch function of the “node-fetch” module to send HTTP requests to the Xsolla server.
Copy
Full screen
Small screen
import fetch from "node-fetch";
  1. Set the constants needed for request authorization. Instead of <your project_id from PA> and <your api key from PA>, insert your values for the project ID and API key, which will be encoded using Base64 for subsequent use in API requests.
Copy
Full screen
Small screen
const projectId = <your project_id from PA>;

const apiKey = <your api key from PA>;

const buff = new Buffer(`${projectId}:${apiKey}`);

const basicAuth = buff.toString('base64')
  1. Implement the helper function sleep, which is used to create a delay when sending requests. This is necessary in order not to exceed API request rate limits.
Copy
Full screen
Small screen
function sleep(ms) {

   return new Promise(resolve => setTimeout(resolve, ms));

}
  1. Implement the getItems function, which is specific to your system, to retrieve item data from your system.
Copy
Full screen
Small screen
async function getItems() {

   // receive items from the original system or read from a pre-prepared file

   return items;

}
  1. Implement the prepareData function, which is specific to your system, to format item data in accordance with the data format in the Create virtual item API call.
Copy
Full screen
Small screen
function prepareData(items) {

   // format items in accordance with API requirements

   return formattedItems;

}
  1. Add the createItem function, which sends a POST request to the Xsolla API to create a virtual item.
Copy
Full screen
Small screen
async function createItem(item) {

   const url = `https://store.xsolla.com/api/v2/project/${projectId}/admin/items/virtual_items`;



   return await fetch(url, {

       method: "POST",

       headers: {

           Authorization: "Basic " + basicAuth,

           "Content-Type": "application/json"

       },

       body: JSON.stringify(item),

   });

}
  1. Add the checkItemExist function, which checks whether a virtual item with a specified SKU exists. The function sends a GET request to the Xsolla API:
    • If a response with a 404 HTTP code is received, the item with the specified SKU is not found, and it needs to be created.
    • If a response with a 200 HTTP code is received, the item with the specified SKU is found and does not need to be created.
Copy
Full screen
Small screen
async function checkItemExist(sku) {

   const url = `https://store.xsolla.com/api/v2/project/${projectId}/admin/items/virtual_items/sku/${sku}`;

   const response = await fetch(url, {

       method: "GET",

       headers: {

           Authorization: "Basic " + basicAuth

       }

   });

   return response.status !== 404;

}
  1. Add the createItems function, which goes through the list of items and checks whether there is an item with a SKU from your system on the Xsolla side. If there is no item with such a SKU, the function creates it. The progress information is displayed in the console.
Copy
Full screen
Small screen
async function createItems(items) {

   let success = 0;

   let alreadyCreated = 0;

   for (let i = 0; i < items.length; i++) {

       const item = items[i];

       if (item['sku'] === undefined) {

           console.log(`${i} Field "sku" not specified`);

           continue;

       }

       const sku = item['sku'];

       if (await checkItemExist(sku)) {

           console.log(`${i} Item with sku "${sku}" already created`);

           alreadyCreated++;

           continue;

       }

       const response = await createItem(item);

       if (response.status === 201) {

           console.log(`${i} Item with sku "${sku}" successfully created`)

           success++;

       } else {

           const jsonData = await response.json();

           console.log(`${i} An error occurred while creating the items with sku "${sku}"`);

           console.log(jsonData);

       }

       // add a delay so as not to run into rate limits

       await sleep(500);

   }

   console.log(`${success} items out of ${items.length} created. ${alreadyCreated} items already existed`);

}
  1. Add the run function that calls all the above functions in the correct order.
Copy
Full screen
Small screen
async function run() {

 const items = await getItems();

 const formattedItems = prepareData(items);

 await createItems(formattedItems);

}

The full code:

Copy
Full screen
Small screen
import fetch from "node-fetch";

const projectId = <your project_id from PA>;
const apiKey = <your api key from PA>;
const buff = new Buffer(`${projectId}:${apiKey}`);
const basicAuth = buff.toString('base64')

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function getItems() {
    // receive items from the original system or read from a pre-prepared file
    return items;
}

function prepareData(items) {
    // format items in accordance with API requirements
    return formatedItems;
}

async function createItem(item) {
    const url = `https://store.xsolla.com/api/v2/project/${projectId}/admin/items/virtual_items`;

    return await fetch(url, {
        method: "POST",
        headers: {
            Authorization: "Basic " + basicAuth,
            "Content-Type": "application/json"
        },
        body: JSON.stringify(item),
    });
}

async function isItemExisted(sku) {
    const url = `https://store.xsolla.com/api/v2/project/${projectId}/admin/items/virtual_items/sku/${sku}`;
    const response = await fetch(url, {
        method: "GET",
        headers: {
            Authorization: "Basic " + basicAuth
        }
    });
    return response.status !== 404;
}

async function createItems(items) {
    let success = 0;
    let alreadyCreated = 0;
    for (let i = 0; i < items.length; i++) {
        const item = items[i];
        if (item['sku'] === undefined) {
            console.log(`${i} Field "sku" not specified`);
            continue;
        }
        const sku = item['sku'];
        if (await isItemExisted(sku)) {
            console.log(`${i} Item with sku "${sku}" already created`);
            alreadyCreated++;
            continue;
        }
        const response = await createItem(item);
        if (response.status === 201) {
            console.log(`${i} Item with sku "${sku}" successfully created`)
            success++;
        } else {
            const jsonData = await response.json();
            console.log(`${i} An error occurred while creating the items with sku "${sku}"`);
            console.log(jsonData);
        }
        // add a delay so as not to run into rate limits
        await sleep(500);
    }
    console.log(`${success} items out of ${items.length} created. ${alreadyCreated} items already existed`);
}

async function run() {
  const items = await getItems();
  const formattedItems = prepareData(items);
  await createItems(formattedItems);
}

run(); 

Updating by importing from external systems

Follow the instructions to import data from external systems like PlayFab or Google Play.

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: October 3, 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!