Import catalog

Create and update item catalog using JSON import

You can create, update, or deactivate items using import from a JSON file.

Note
You can create, update, or deactivate items using API calls or manually in the Publisher Account. However, for each item, you need to perform a separate request or action. With import, you can perform these actions for multiple items simultaneously by specifying them in a single JSON file.

With this tool, you can:

Features:

  • Support for the following types of items:
    • virtual items
    • virtual currency
    • virtual currency packages
    • bundles
  • Data validation. If the file structure or data format does not meet the requirements, you will see a list of errors when importing.

Limitations:

Note
For pre-created items, you can import regional prices from a CSV file.

Import of the item catalog

To import an item catalog from a file:

  1. Open the project in Publisher Account.
  2. In the side menu, click Store and go to the Virtual currency, Virtual items, or Bundles section.
  3. Click Import items.

  1. Choose the action:
    • Add new items — only items with new SKUs will be added.
    • Add new items and update existing ones — items with new SKUs will be added and data of existing items will be updated.
    • Add new, update existing, disable missing items — items with SKUs from the file will be added/updated. If there is an item in the catalog, but there is no such SKU in the file, the status of the item in the Publisher Account will be changed to Partially available — item cannot be purchased separately but is available as part of a bundle or bonus.

  1. Fill in the file for import:
    • Download the file template in the download window and fill it in according to the example below.
    • Export the items and use the exported file as a template.
    • Create your own JSON file and fill it out as per the example below.

An example of a full JSON file:

Copy
Full screen
Small screen

{
    "virtual_currency": [
        {
            "sku": "Gem_test_import",
            "name": {
                "en": "Gem_test_import"
            },
            "type": "virtual_currency",
            "description": {
                "en": "my test imported currency"
            },
            "image_url": "https://cdn3.xsolla.com/img/misc/merchant/default-dc-image.png",
            "description": {
                "en": "my test imported currency",
                "de": "meine importierte Testwährung"
            },
            "attributes": [],
            "is_free": false,
            "order": 1,
            "groups": [],
            "regional_prices": [],
            "prices": [
                {
                    "amount": 2,
                    "currency": "USD",
                    "is_default": true,
                    "is_enabled": true
                }
            ],
            "media_list": [],
            "vc_prices": [],
            "is_enabled": true,
            "is_show_in_store": true,
            "regions": [],
            "limits": {
                "per_user": null,
                "per_item": null,
                "recurrent_schedule": null
            },
            "periods": [],
            "inventory_options": {
                "consumable": true,
                "expiration_period": null
            },
            "is_hard": false
        }
    ],
    "virtual_items": [
        {
            "sku": "event_access_test_import",
            "name": {
                "en": "Special Event Access_test_import"
            },
            "type": "virtual_good",
            "description": {
                "en": "Get special event access as a bonus only on your first purchase. Find the right doggy at the Robo-Dog Exhibition!"
            },
            "image_url": "https://cdn3.xsolla.com/img/misc/images/1e3ef1a96cc9dd8d98bc124d5d6fad79.png",
            "long_description": null,
            "attributes": [],
            "is_free": false,
            "order": 1,
            "groups": [
                "my_test_group"
            ],
            "regional_prices": [],
            "prices": [
                {
                    "amount": 35,
                    "currency": "USD",
                    "is_default": true,
                    "is_enabled": true
                }
            ],
            "media_list": [],
            "vc_prices": [],
            "is_enabled": true,
            "is_show_in_store": true,
            "regions": [],
            "limits": {
                "per_user": null,
                "per_item": null,
                "recurrent_schedule": null
            },
            "periods": [],
            "inventory_options": {
                "consumable": true,
                "expiration_period": null
            }
        }
    ],
    "virtual_currency_packages": [
        {
            "item_id": 441982,
            "sku": "small_gold_pack_test_import",
            "type": "bundle",
            "name": {
                "en": "Small gold pack"
            },
            "bundle_type": "virtual_currency_package",
            "description": {
                "en": "Gold x100"
            },
            "image_url": "https://cdn3.xsolla.com/img/misc/images/ba43c46ea75fd5713c210f5736993a92.png",
            "vc_prices": [],
            "regional_prices": [],
            "prices": [
                {
                    "amount": 5,
                    "currency": "USD",
                    "is_default": true,
                    "is_enabled": true
                }
            ],
            "is_enabled": true,
            "is_show_in_store": true,
            "regions": [],
            "limits": {
                "per_user": null,
                "per_item": null,
                "recurrent_schedule": null
            },
            "periods": [],
            "attributes": [],
            "long_description": null,
            "media_list": [],
            "order": 100000000,
            "is_free": false,
            "groups": [],
            "content": [
                {
                    "sku": "Gem_test_import",
                    "quantity": 100
                }
            ]
        }
    ],
    "bundles": [
        {
            "item_id": 684024,
            "sku": "start_pack_test_import_test_import",
            "type": "bundle",
            "name": {
                "en": "Legendary Start Pack"
            },
            "bundle_type": "standard",
            "description": {
                "en": "Crystal x 1\nGem x 1"
            },
            "image_url": "https://cdn3.xsolla.com/img/misc/merchant/default-dc-image.png",
            "regional_prices": [],
            "prices": [
                {
                    "amount": 20,
                    "currency": "USD",
                    "is_default": true,
                    "is_enabled": true
                }
            ],
            "virtual_prices": [],
            "is_enabled": true,
            "is_show_in_store": true,
            "regions": [],
            "limits": {
                "per_user": null,
                "per_item": null,
                "recurrent_schedule": null
            },
            "periods": [],
            "attributes": [],
            "long_description": null,
            "media_list": [],
            "order": 5,
            "is_free": false,
            "groups": [
                "my_test_group"
            ],
            "content": [
                {
                    "sku": "Gem_test_import",
                    "quantity": 1
                },
                {
                    "sku": "event_access_test_import",
                    "quantity": 1
                }
            ]
        }
    ]
}

  1. Upload the full file to the corresponding field in the import window.
  2. If there are errors during import, a list of these errors and recommendations for correction will be displayed in the import window. Make the necessary changes to the file and upload it again.

After successful upload, the items with the specified SKUs will be created, updated, or disabled.

Note
You can import items using the Import items via JSON file API call.
To avoid errors during import, follow the recommendations above for filling in the file.

Export of the item catalog

To export an item or item catalog to a JSON file:

  1. Open the project in the Publisher Account.
  2. In the side menu, click Store and go to the Virtual currency, Virtual items, or Bundles section.
  3. Click Export items.

  1. Choose the action:
    • Export all items — the entire catalog of all types of items of this project will be exported. For example, if you navigate to the Virtual Currency section and export all items, the JSON file will unload virtual currencies, virtual currency packages, virtual items, game key packages of your project.
    • Export only selected items — in the opened window select the items that should be exported.

  1. Click Export.

The JSON file download will start automatically.

Import catalog from external platforms

You can import items and subscriptions from external platforms and synchronize user inventory.

Notice
After import, you can synchronize changes made to the item catalog and subscriptions in the import source and Xsolla in the following ways:If the catalog cannot be imported, configure the item and subscriptions catalog in Publisher Account or using API methods.

Import catalog from Google Play

Notice

Before you start importing, check that Google Play Android Developer API is enabled in your Google Play project. Visit https://console.developers.google.com/apis/api/androidpublisher.googleapis.com/overview?project={project_id}, where project_id — your project ID in Google Play. If this API disabled, enable it. The settings will take time to apply, so the import may fail if you try immediately after enabling the settings. Wait a few minutes and retry.

  1. Open your project in Publisher Account.
  2. Click Store in the side menu.
  3. In the Catalog Management pane, click Configure.
  4. In the Integration with external platforms pane, click Configure.
  5. In the Google Play pane, click Configure.
  6. Specify Application ID — your app’s ID from Google Play.
Note
You can find Application ID on the Google Play Console. In the side menu, click All apps. Find the needed app in the table. Its ID will be specified in the App column, next to the name and logo.
  1. Upload JSON with a private key.
Note
A private key is generated when you create your service account.

  1. Go to the Google Play Console, in the side menu click Users and permissions and add service account as a new user with the role of Android Management User. This requires you to have the Project IAM admin role.

  1. Click Save.
  2. Click Start import. Catalog import will begin immediately.
Note
SKU corresponds to Product ID in the source of import.
  1. To sell virtual items in the web store created by Site Builder, configure item groups in Publisher Account and assign one or more of them to each item.
  2. To display item images, upload them to your Publisher Account.
Note
For Bangladesh users, catalog prices will be displayed in the default currency (USD), rather than in BDT.

Import catalog from App Store

Note
Only products with the Approved status in App Store Connect will be imported. In the Store section of your Publisher Account, imported items will be displayed with the Partially Available status. To make the items visible, you need to change the status to Available.
Before importing a catalog from the App Store, you need to obtain the following data:

Get Application ID

To get your Application ID in App Store Connect:
  1. Log in to App Store Connect.
  2. Go to the Apps section.

  3. Open your application’s page.
  4. Navigate to General Information > App Information.
  5. In the General Information copy Application ID in Apple ID field.

Get API Key and Issuer ID

Issuer ID in App Store Connect is used for interaction with Apple API, including the App Store Connect API. It is required for setting up API keys to automate tasks such as app management, analytics data retrieval, and other operations in App Store Connect.

API Key is a unique identifier used to authenticate API requests in App Store Connect API and ensure secure access to Apple Developer Account data and functionality.

To get the Issuer ID and API Key in App Store Connect:

  1. Log in to App Store Connect and go to the Users and Access section.
  2. Open the Integrations tab.
  3. In the side menu Keys click App Store Connect API.
  4. Go to the Team Keys tab. Click the + icon to create a new API key.

  5. In the Generate API Key window, assign a name to the key and set the access level for this key.
  6. Click Generate.

  7. The newly created key will appear in the list of active API keys. Download it as a P8 file and copy the Key ID.

  8. In the Team Keys tab, copy the Issuer ID.

Import a catalog from the App Store

  1. Open your Publisher Account and go to Store > Catalog management > Integration with external platforms > App Store.
  2. Provide the data got in App Store Connect:
    • Application ID
    • Private key file (P8)
    • Issuer ID
    • Key ID.
  3. Click Start import. The catalog import will begin automatically.

To sell virtual items in the web store created using Site Builder, create item groups in your Publisher Account and assign one or more groups to each virtual item.

To display item images, you need to upload them by editing the imported item in Store > Virtual Items.

Note
The SKU of a product corresponds to the Product ID in the import source.

Import catalog from PlayFab

Notice
Supported PlayFab API version: Economy v1.

PlayFab offers game developers ready-to-use server solutions to manage catalogs and monetization. After integration with PlayFab, you can import a catalog from PlayFab to Store for using Xsolla solutions.

Note
You’ll need a project ID and a secret project key in PlayFab. Also, the catalog you want to import to Xsolla, should be set up in PlayFab as basic (Base).

  1. Open your project in Publisher Account.
  2. Click Store in the side menu.
  3. In the Catalog Management pane, click Configure.
  4. In the Integration with external platforms pane, click Configure.
  5. In the PlayFab pane, click Configure.
  6. In the Item import tab specify:
  7. Click Save.
  8. Synchronize user inventory with PlayFab (optionally):
    1. Go to the Inventory synchronization and specify:
    2. Set the Synchronize user inventory with PlayFab toggle to On.
    3. Click Save.
  9. Go to the Item import tab and click Start import. Catalog import will start automatically.
  10. To sell virtual items in the web store created by Site Builder, configure item groups in Publisher Account and assign one or more of them to each item.
  11. To display item images, upload them to your Publisher Account.

To check if the import completed successfully, go to the Store section in the side menu and make sure that items, currency, and bundles are enabled on the Virtual currency, Virtual items, and Bundles tabs.

Notice
When you check the import results, please consider that a virtual currency package is a bundle containing only one currency. PlayFab uses virtual currency RM (Real money) which is equivalent to real currency — 1 cent (100 RM = 1 USD). For example, if you import 400 RM from PlayFab, you will see 4 USD in your Publisher Account.

Reimport catalog

When reimporting the catalog, you need to consider that:

  • Items that are already in the Store will be updated.
  • Items that are not available in the Store will be added.
  • Items that have already been removed from the source of import will remain in the Store. You can delete them in your Publisher Account or via API.

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(); 
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!