APIを使用したカタログ作成と更新の自動化

注意
PlayFab、App Store、Google Play などの外部システムを使用している場合は、説明に従ってデータをインポートしてください。

Shop Builder APIコールを利用することで、カタログの作成と更新を自動化できます。自動化により、多くの時間を費やすことなくカタログを最新の状態に保つことが可能です。

これにより、以下のメンテナンスまたは更新にかかる時間を短縮できます:

  • 大量のアイテムを含むカタログ
  • 現地価格
お知らせ

ユーザーエンゲージメントを維持するためには、アイテムカタログを作成した後もエクソーラ側で最新の状態に保つことが重要です。アイテムの追加や価格の変更など、お客様側で更新が発生した場合には、エクソーラ側のカタログを更新することをお勧めします。

次のことができます:

基本認証は、アイテムやプロモーションを作成または更新するためのAPIコールに使用されます。Authorization:Basic <your_authorization_basic_key>を渡し、そこで、<your_authorization_basic_key>マーチャントID:APIキーペア、はBase64規格に基づいてエンコードされています。パブリッシャーアカウントに移動して、以下のパラメータを見つかります:

  • マーチャントIDは以下の場所で表示されます:
    • 会社設定 > 会社セクション。
    • パブリッシャーアカウントページのブラウザーアドレスバーのURL。URLは以下の形式があります:https://publisher.xsolla.com/<merchant_id>/

アイテムの作成と更新

エクソーラは以下のタイプのインゲームアイテムをサポートしています:

  • 仮想アイテム
  • 仮想通貨
  • 仮想通貨パッケージ
  • バンドル

統合を簡素化するために(例えば、モバイルアプリケーションなど)、あらゆるゲーム内購入ロジックを実装できるユニバーサルなタイプである仮想アイテムを使用できます。これにより、データ処理が統一され、カタログ構成の冗長性を避けることができます。

複数のアイテムを作成する必要がある場合は、必要なアイテムタイプのAPIメソッドを必要な回数だけ呼び出すスクリプトを作成することができます。

お知らせ

アイテムリクエストに対する応答で返されるパラメータのリストは、カタログを更新する際に渡す必要のあるパラメータのリストとは異なります。必須パラメータおよび更新されたパラメータに加えて、アイテム更新コールで、アイテムリクエストに対する応答で返されるパラメータを渡します。

例:

仮想アイテムを取得するコールでは、ユーザーの制限データを持つlimitsオブジェクトが返されます。アイテムの価格または名称だけを更新したい場合は、仮想アイテムを更新するコールでlimitsオブジェクトの現在のデータを渡します。limitsオブジェクトを渡さない場合、仮想アイテムを更新するコールでアイテムがアップデートされた後、制限データは削除されます。

カタログにアイテムを追加するには、以下のAPIコールを使用します:

カタログを更新するには:

  1. 以下のAPIコールを使用してカタログからデータを取得します:
  2. 以下のAPIコールで新しいパラメータ値を渡します:

API経由でアイテムを自動作成するためのスクリプト

システムからのデータに基づいて複数のアイテムを作成する必要がある場合は、APIを使用してこのプロセスを自動化できます。

次のことを行う必要があります:

アイテムグループを使用したい場合は、事前にパブリッシャーアカウントで作成してください。

複数のタイプのアイテムを使用する場合は、次の順序で作成する必要があります:

  1. パブリッシャーアカウントのアイテムグループ。
  2. 仮想通貨。
  3. 仮想アイテム。
  4. 仮想通貨パッケージ。
  5. バンドル。

以下は仮想アイテムを作成するメソッドを繰り返し呼び出して仮想アイテムを作成するスクリプトの例です。

スクリプトはJavaScriptとJavaScriptランタイムNode.jsを使って開発されています。

  1. エクソーラにHTTPリクエストを送信するために、“node-fetch”モジュールのfetch関数をインポートします。
Copy
Full screen
Small screen
1import fetch from "node-fetch";
  1. リクエスト認証に必要な定数を設定します。の代わりに、プロジェクトIDとAPIキーの値を挿入し、これらは後続のAPIリクエストで使用するためにBase64でエンコードされます。
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. APIのレート制限を超えないように、リクエスト送信時に遅延メカニズムを実装してください。以下の方法があります:
    • リクエスト間に固定の遅延を設定するために、ヘルパー関数sleepを使用します。
    • 指数関数的なバックオフを実装するために、ヘルパー関数delayを使用します。この場合、繰り返されるリクエスト間の待機時間は、429 Too Many Requestsのエラーが発生するたびに増加し、負荷を分散するための追加のランダム値(ジッター)が加算されます。
固定遅延オプション:
Copy
Full screen
Small screen
1function sleep(ms) {
2
3   return new Promise(resolve => setTimeout(resolve, ms));
4
5}

指数関数的バックオフオプション:

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. システムからアイテムデータを取得にはシステム固有のgetItems関数を実装します。
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. 仮想アイテムを作成するAPIコールのデータフォーマットに従ってアイテムデータをフォーマットするには、システム固有のprepareData関数を実装します。
Copy
Full screen
Small screen
1function prepareData(items) {
2
3   // format items in accordance with API requirements
4
5   return formattedItems;
6
7}
  1. POSTリクエストをXsolla APIに送信して仮想アイテムを作成するcreateItem関数を追加します。
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. 指定したSKUの仮想アイテムが存在するかどうかを確認するcheckItemExist関数を追加します。この関数はエクソーラのAPIにGETリクエストを送信します:
    • 指定されたSKUのアイテムが見つからない場合は、404のHTTPコードの応答が受信され、作成する必要があります。
    • 200のHTTPコードを含む応答を受信した場合、指定されたSKUを持つアイテムが見つかり、作成する必要はありません。
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. アイテムのリストを処理し、エクソーラ側にシステムのSKUを持つアイテムが存在するかどうかを確認するcreateItems関数を追加します。該当するSKUを持つアイテムがない場合、関数はアイテムを作成します。進行状況がコンソールに表示されます。
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. 正しい順序で上記のすべての関数を呼び出すrun関数を追加します。
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}

完全なコードは:

この記事は役に立ちましたか?
ありがとうございます!
改善できることはありますか? メッセージ
申し訳ありません
この記事が参考にならなかった理由を説明してください。 メッセージ
ご意見ありがとうございました!
あなたのメッセージを確認し、体験を向上させるために利用させていただきます。
最終更新日: 2026年2月13日

誤字脱字などのテキストエラーを見つけましたか? テキストを選択し、Ctrl+Enterを押します。

問題を報告する
当社は常にコンテンツを見直しています。お客様のご意見は改善に役立ちます。
フォローアップ用のメールをご提供してください
ご意見ありがとうございました!
フィードバックを送信できませんでした
後でもう一度お試しいただくか、doc_feedback@xsolla.comまでお問い合わせください。