How to automate catalog updates

You can automate the creation and updating of the catalog with Shop Builder 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 items 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>/.

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 required when using the API calls for updating promotions doesn’t match the list of parameters returned by the API calls for retrieving promotions. When calling the API methods for updating promotions, you must pass:
  • the required parameters
  • the parameters you want to change
  • all other parameters returned by the promotion retrieval method

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 code 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
1import 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
1const projectId = <your project_id from PA>;
2
3const apiKey = <your api key from PA>;
4
5const buff = new Buffer(`${projectId}:${apiKey}`);
6
7const basicAuth = buff.toString('base64')
  1. Implement a delay mechanism when sending requests to avoid exceeding the API rate limits. You can:
    • Use the sleep helper function to set a fixed delay between requests.
    • Use the delay helper function to implement exponential backoff. In this case, the waiting time between repeated requests increases after each 429 Too Many Requests error, with an additional random value (jitter) added to distribute the load.
Fixed delay option:
Copy
Full screen
Small screen
1function sleep(ms) {
2
3   return new Promise(resolve => setTimeout(resolve, ms));
4
5}

Exponential backoff option:

Copy
Full screen
Small screen
 1/** Pause for the specified number of milliseconds */
 2function delay(ms) {
 3  return new Promise((resolve) => setTimeout(resolve, ms));
 4}
 5
 6/**
 7 * A fetch wrapper that handles HTTP 429 responses:
 8 * - pure exponential backoff with jitter (ignores Retry-After);
 9 * - limited number of retry attempts.
10 */
11async function fetchWithRateLimit(
12  url,
13  options = {},
14  {
15    maxAttempts = 4,     // 1 initial attempt + 3 retries (balanced approach)
16    baseDelayMs = 1000,  // 1 second base delay (15x the 67ms interval for 15 RPS)
17    factor = 1.5,        // gentler backoff multiplier (1s → 1.5s → 2.25s → 3.4s)
18    maxDelayMs = 4000,   // 4 seconds max delay (prevents excessive waiting)
19    jitterMs = 300       // 300ms random jitter (spreads retries without long delays)
20  } = {}
21) {
22  let attempt = 0;
23
24  while (true) {
25    attempt += 1;
26    const res = await fetch(url, options);
27
28    if (res.status !== 429) return res;
29
30    // 429: calculate pause (exponential backoff + jitter)
31    const backoff = Math.min(
32      Math.floor(baseDelayMs * Math.pow(factor, attempt - 1)),
33      maxDelayMs
34    );
35    const jitter = Math.floor(Math.random() * (jitterMs + 1)); // 0..jitterMs
36    const waitMs = backoff + jitter;
37
38    if (attempt >= maxAttempts) {
39      // retry limit reached — return the last response
40      return res;
41    }
42
43    await delay(waitMs);
44  }
45}
  1. Implement the getItems function, which is specific to your system, to retrieve item data from your system.
Copy
Full screen
Small screen
1async function getItems() {
2
3   // receive items from the original system or read from a pre-prepared file
4
5   return items;
6
7}
  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
1function prepareData(items) {
2
3   // format items in accordance with API requirements
4
5   return formattedItems;
6
7}
  1. Add the createItem function, which sends a POST request to the Xsolla API to create a virtual item.
Copy
Full screen
Small screen
 1async function createItem(item) {
 2
 3   const url = `https://store.xsolla.com/api/v2/project/${projectId}/admin/items/virtual_items`;
 4
 5
 6
 7   return await fetch(url, {
 8
 9       method: "POST",
10
11       headers: {
12
13           Authorization: `Basic ${basicAuth}`,
14
15           "Content-Type": "application/json"
16
17       },
18
19       body: JSON.stringify(item),
20
21   });
22
23}
  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
 1async function checkItemExist(sku) {
 2
 3   const url = `https://store.xsolla.com/api/v2/project/${projectId}/admin/items/virtual_items/sku/${sku}`;
 4
 5   const response = await fetch(url, {
 6
 7       method: "GET",
 8
 9       headers: {
10
11           Authorization: `Basic ${basicAuth}`
12
13       }
14
15   });
16
17   return response.status !== 404;
18
19}
  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
 1async function createItems(items) {
 2
 3   let success = 0;
 4
 5   let alreadyCreated = 0;
 6
 7   for (let i = 0; i < items.length; i++) {
 8
 9       const item = items[i];
10
11       if (item['sku'] === undefined) {
12
13           console.log(`${i} Field "sku" not specified`);
14
15           continue;
16
17       }
18
19       const sku = item['sku'];
20
21       if (await checkItemExist(sku)) {
22
23           console.log(`${i} Item with sku "${sku}" already created`);
24
25           alreadyCreated++;
26
27           continue;
28
29       }
30
31       const response = await createItem(item);
32
33       if (response.status === 201) {
34
35           console.log(`${i} Item with sku "${sku}" successfully created`)
36
37           success++;
38
39       } else {
40
41           const jsonData = await response.json();
42
43           console.log(`${i} An error occurred while creating the items with sku "${sku}"`);
44
45           console.log(jsonData);
46
47       }
48
49       // add a delay so as not to run into rate limits
50
51       await sleep(500);
52
53   }
54
55   console.log(`${success} items out of ${items.length} created. ${alreadyCreated} items already existed`);
56
57}
  1. Add the run function that calls all the above functions in the correct order.
Copy
Full screen
Small screen
1async function run() {
2
3 const items = await getItems();
4
5 const formattedItems = prepareData(items);
6
7 await createItems(formattedItems);
8
9}

The full code:

Updating by importing from external systems

Follow the instructions to import data from external systems like PlayFab, App Store 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 8, 2025

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!
We couldn't send your feedback
Try again later or contact us at doc_feedback@xsolla.com.