業務システム

NetSuiteの連携とAPI:SOAP廃止後のREST・RESTletの使い分けとOAuth 2.0・同時実行数の設計

NetSuiteの連携とAPI:SOAP廃止後のREST・RESTletの使い分けとOAuth 2.0・同時実行数の設計

NetSuiteの連携とAPIを選ぶとき、最初に確かめるのはSOAPの期限です。OracleはSOAP Webサービスを2028.2で停止すると公表しており、これから作る連携はSuiteTalk REST WebサービスとOAuth 2.0で組むのが前提になります。本記事では、REST・SuiteQL・RESTletの使い分け、ユーザー操作の要らないクライアント資格情報フロー(M2M)での接続、外部IDのupsertでEC受注を二重に取り込まない書き方、サービスティア別の同時実行数とリトライの設計を、コード付きで整理しました。netsuite連携でよく聞かれるバックアップの取り方とファイル容量の上限も、2026年10月時点のOracle公式ヘルプに沿って扱います。

まとめ:NetSuite連携は新規ならREST+OAuth 2.0、同時実行数から設計する

新しく作る連携は、レコードの登録・更新をSuiteTalk REST、差分の取り出しをSuiteQL、複数の処理を1回で済ませたい部分だけをRESTletで書く構成が基本です。SOAPは既存連携の保守に限り、2027年中に置き換えの計画を立てます。

認証はOAuth 2.0のクライアント資格情報フローを使い、証明書の期限(最長2年)を運用表に載せます。外部から取り込む伝票や顧客には外部IDを付け、PUTのupsertで送れば、再送しても二重登録になりません。

流量の設計は、アカウントの同時実行数から逆算します。RESTとRESTletは同じ枠を分け合うため、夜間バッチとEC連携を同じ時間に重ねると、上限超過のエラーが起きます。リトライを最初から組み込むことがOracleの要求事項です。

NetSuiteの連携方式をSOAP停止の期限と処理の種類で選び分ける手順

NetSuiteには外部とつなぐ入口が複数あり、名前も似ています。

REST・SuiteQL・RESTlet・SOAPの役割と向く処理、注意点の比較

主な入口を、向く処理と注意点で比べると次のとおりです。

方式 中身 向く処理 注意点
SuiteTalk REST 標準のレコードAPI マスタと伝票の登録・更新 同時実行数を共有
SuiteQL(REST経由) SQLでの照会 差分の抽出と集計 最大10万件
RESTlet SuiteScriptの独自API 複数レコードを1回で処理 5,000ユニット
SOAP 旧来のWebサービス 既存連携の保守 2028.2で停止
CSVインポート 画面からの一括取込 初期移行と単発の登録 人手が残る

実務の優先順位は、まずRESTとSuiteQLで足りるかを確かめ、足りない処理だけをRESTletにすることです。RESTletは自社でコードを持つことになり、NetSuiteのリリースごとに動作確認の対象が増えます。

SOAPは2028.2で停止、2027.1以降は2025.2エンドポイントだけが残る

Oracleの公式ヘルプ「NetSuite Versioning and WSDL Versioning Overview」によると、最後に予定されたSOAPのエンドポイントは2025.2で、それ以降は必要が生じた場合に限られます。2027.1のリリースからサポートされるのは2025.2のエンドポイントだけになり、2028.2のリリースでSOAPはNetSuiteから無くなります。既存のSOAP連携が動くのは、その前のリリースまでです。

同じページは、SOAPの後継をSuiteTalk RESTとし、新しく作る連携はすべてRESTとOAuth 2.0で認証するよう求めています。手元にSOAPの連携があるなら、まずWSDLの版を調べます。2025.2より古い版を使っていれば、2027.1の時点でサポートの対象から外れる計算です。操作ごとの置き換え先はSOAPからRESTへの移行ガイドにまとまっています。

OAuth 2.0のクライアント資格情報フローでNetSuite REST APIに接続

サーバー同士の連携では、人がログインして同意する画面を挟めません。NetSuiteはこの用途にクライアント資格情報フロー(Machine to Machine、M2M)を用意しています。

機能の有効化から統合レコード、証明書のマッピングまでの設定手順

設定は管理者が画面で行います。REST Webサービスの前提条件とOAuth 2.0 Client Credentials Setupの手順を、作業順に並べると次のとおりです。

  1. Setup > Company > Enable Featuresを開き、SuiteCloudタブでREST Web ServicesとOAuth 2.0にチェックを入れる
  2. 連携専用のロールを作り、対象レコードの権限とOAuth 2.0でのログイン権限を付ける
  3. Setup > Integration > Manage Integrationsで統合レコードを作り、Client Credentials (Machine to Machine) Grantとスコープにチェックを入れて、表示されたクライアントIDを控える
  4. 手元で鍵ペアと自己署名証明書を作る
  5. Setup > Integration > Manage Authentication > OAuth 2.0 Client Credentials (M2M) Setupで、エンティティ・ロール・アプリを選び、証明書の公開側をアップロードして証明書IDを控える

手順4の鍵は、EC鍵なら256・384・521ビット、RSA鍵なら3072か4096ビットと公式の証明書条件で決まっています。OpenSSLでEC鍵(256ビット)の証明書を作るコマンドは次のとおりです。

openssl req -new -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
  -nodes -days 730 -keyout private.pem -out public.pem \
  -subj "/CN=netsuite-m2m-ec-sync"

アップロードするのはpublic.pemだけで、private.pemは連携サーバーの秘密情報として保管します。ロールの権限の切り方はNetSuiteの権限とロール設計を解説した記事で扱っています。

JWTに署名してアクセストークンを取得するPythonの実装例

トークンの取得は、秘密鍵で署名したJWTをトークンエンドポイントへPOSTするだけです。公式ヘルプ「The Request Token Structure」によると、ヘッダーのkidは手順5の証明書ID、ペイロードのissは統合レコードのクライアントID、audはトークンエンドポイントのURLで、expはiatから60分未満にします。

import time
import uuid

import jwt  # pip install "pyjwt[crypto]" requests
import requests

ACCOUNT = "1234567"  # Setup > Company > Company Information の Company URLs で確認
CLIENT_ID = "統合レコードのクライアントID"
CERT_ID = "M2M設定画面の証明書ID"
BASE = f"https://{ACCOUNT}.suitetalk.api.netsuite.com/services/rest"
TOKEN_URL = f"{BASE}/auth/oauth2/v1/token"


def get_token() -> str:
    now = int(time.time())
    with open("private.pem", "rb") as f:
        key = f.read()
    assertion = jwt.encode(
        {"iss": CLIENT_ID, "scope": "rest_webservices", "aud": TOKEN_URL,
         "iat": now, "exp": now + 300, "jti": str(uuid.uuid4())},
        key, algorithm="ES256", headers={"kid": CERT_ID, "typ": "JWT"},
    )
    r = requests.post(TOKEN_URL, data={
        "grant_type": "client_credentials",
        "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
        "client_assertion": assertion,
    }, timeout=30)
    r.raise_for_status()
    return r.json()["access_token"]  # expires_in は 3600 秒

署名方式は鍵に合わせ、EC鍵ならES256〜ES512、RSA鍵ならPS256〜PS512から選びます。RESTletも同じトークンで呼ぶなら、scopeは"restlets,rest_webservices"のカンマ区切りです。REST WebサービスのURLの公式ヘルプのとおり、アカウントIDはCompany URLsサブタブで確かめ、連携側の設定値にします。本番とサンドボックスでクライアントIDと証明書も別に作り、環境変数でまとめて切り替えると、本番へテストデータを流す事故を防げます。

証明書の最長2年とトークン60分の失効に備えた運用の組み込み方

トークンエンドポイントの公式ヘルプによると、アクセストークンの有効期間は60分で、リフレッシュトークンは返りません。期限が切れたら、新しいJWTを作ってフローをやり直します。上のコードを、期限の5分前に取り直すキャッシュで包んでおけば足ります。

止まりやすいのは証明書の側です。有効期間は最長2年で、期限の2か月前・1か月前・14日前に管理者へメールが届く仕組みです。宛先が退職者なら、誰も気付かないまま連携が止まります。有効な証明書は統合レコード・エンティティ・ロールの組み合わせごとに5枚まで持てるので、期限の1か月前に新しい証明書を追加し、連携側のkidを切り替えてから古い証明書を失効させる手順を運用表に書いておきます。

REST APIでレコードを登録・更新し、SuiteQLで差分を取り出す実装

認証が通ったら、書き込みと読み出しの2つの道筋を作ります。どちらも同じアカウント別のURLを使います。

外部IDとPUTのupsertでEC受注の顧客を二重登録せずに取り込む

連携で起きがちな事故は、通信の途中で切れた登録を再送し、同じ顧客や伝票が2件できることです。公式ヘルプ「Using the Upsert Operation」は、URLに外部IDを入れてPUTで送ると、レコードが無ければ作成し、あれば更新すると説明しています。ECの会員番号を外部IDにした例です。

def upsert_customer(token: str, member: dict) -> None:
    url = f"{BASE}/record/v1/customer/eid:EC-{member['member_no']}"
    body = {
        "companyName": member["company"],
        "email": member["email"],
        "subsidiary": {"id": "1"},  # OneWorld では所属子会社の内部ID が要る
    }
    r = requests.put(url, json=body,
                     headers={"Authorization": f"Bearer {token}"}, timeout=60)
    r.raise_for_status()

同じ会員番号で何度送っても、NetSuite側の顧客は1件のままです。外部IDに接頭辞(例のEC-)を付けておくと、別の連携が同じ番号体系を使っていても衝突しません。外部IDを持つレコードの種類でしか使えない点と、外部IDを書き込む連携を種類ごとに1つに絞る点は、設計表に書いておきます。

SuiteQLのlimitとoffsetで差分を取得し、10万件を超える場合の逃がし先

読み出しはSuiteQLが近道です。公式ヘルプ「Executing SuiteQL Queries Through REST Web Services」のとおり、Prefer: transientヘッダーは必須で、件数と開始位置はURLのlimitとoffsetで渡します。前日以降に更新された顧客を取り出す例です(callは次章のリトライ付き関数)。

def fetch_changed_customers(token: str, since: str) -> list:
    q = ("SELECT id, entityid, companyname, email, lastmodifieddate "
         "FROM customer "
         f"WHERE lastmodifieddate >= TO_DATE('{since}', 'YYYY-MM-DD') "
         "ORDER BY id")
    rows, offset = [], 0
    while True:
        r = call("POST", f"{BASE}/query/v1/suiteql", token,
                 params={"limit": 1000, "offset": offset},
                 json={"q": q}, headers={"Prefer": "transient"})
        data = r.json()
        rows += data["items"]
        offset += data["count"]
        if data["count"] == 0 or offset >= data["totalResults"]:
            return rows

ORDER BYで並びを固定しないと、ページの境目で行が重複したり抜けたりします。sinceは自前のジョブが渡す日付に限り、外部の入力をそのまま埋め込まないでください。SuiteQLで返せるのは最大10万件で、それを超える抽出には同じページがSuiteAnalytics Connect(NetSuite2.comデータソース)を案内しています。

NetSuiteの同時実行数とガバナンス制限から逆算する連携の流量設計

本番で詰まる原因の大半は、コードではなく流量です。アカウント全体の同時実行数を、すべての連携で分け合います。

サービスティア別の同時実行数とSuiteCloud Plusで増える上限の計算

公式ヘルプ「Concurrency Governance Limits Based on Service Tiers and SuiteCloud Plus Licenses」が示す基本の上限は次のとおりです。

契約の区分 サービスティア 基本の上限
2020年6月以降の新契約 Standard 5
2020年6月以降の新契約 Premium 15
2020年6月以降の新契約 Enterprise・Ultimate 20
従来の契約 Shared・3 5
従来の契約 2 10
従来の契約 1・1+ 15
従来の契約 0 20

SuiteCloud Plusのライセンス1本ごとに上限は10増えます。Premiumで1本なら25です。開発用とパートナー用のアカウントは常に5で、ライセンスを足しても増えません。SuiteCloud Plusの公式ヘルプは、この上限がRESTとRESTletの合計に掛かると明記しています。自社の値はSetup > Integration > Integration Governanceで確かめられます。ライセンスの費用感はNetSuiteの料金・プランの決まり方を解説した記事を参照してください。

上限超過のエラーを再試行する実装と、夜間バッチを分散させる設計

Oracleのよくある質問は、上限を超えたリクエストはエラーになり、連携側でリトライを組み込む必要があるとしています。超過時のエラーの公式ヘルプに載っているのはRESTletとSOAPの形式で、RESTletはHTTP 400とエラーコードSSS_REQUEST_LIMIT_EXCEEDEDを返します。REST Webサービスの形式は同じページに書かれていないため、次の例ではHTTPの慣例どおり429も再試行の対象にしました。

import random


def call(method: str, url: str, token: str, **kw) -> requests.Response:
    headers = {"Authorization": f"Bearer {token}", **kw.pop("headers", {})}
    for attempt in range(6):
        r = requests.request(method, url, headers=headers, timeout=60, **kw)
        limited = r.status_code in (429, 503) or (
            r.status_code == 400 and "SSS_REQUEST_LIMIT_EXCEEDED" in r.text)
        if not limited:
            r.raise_for_status()
            return r
        time.sleep(min(2 ** attempt, 60) + random.random())
    raise RuntimeError(f"concurrency limit: gave up after retries ({url})")

待ち時間に乱数を足しているのは、複数のワーカーが同じ瞬間に再送して、また上限に当たるのを避けるためです。設計の段階では、上限15のアカウントならEC連携に5、夜間の会計連携に5、残りを予備に回すといった配分を表にしておきます。

RESTletの5,000ユニットと10MB、スクリプト種別ごとの使用量の上限

RESTletは自由度が高い代わりに、1回の呼び出しで使える量が決まっています。公式ヘルプ「RESTlet Governance and Security」によると上限は1スクリプトあたり5,000ユニットで、入出力は文字列1つにつき10MBまでが保証範囲です。スクリプト種別ごとの上限では、Suiteletやユーザーイベントが1,000、スケジュールスクリプトが10,000、Map/Reduceは全体の上限が無く処理単位で管理されます。出荷の確定を1回の呼び出しで済ませるRESTletの例です。

/**
 * @NApiVersion 2.1
 * @NScriptType Restlet
 */
define(['N/record', 'N/runtime', 'N/error'], (record, runtime, error) => {
  const post = (body) => {
    if (!body.salesOrderId || !body.trackingNo) {
      throw error.create({ name: 'MISSING_PARAM', message: 'salesOrderId and trackingNo are required' });
    }
    const fulfillment = record.transform({
      fromType: record.Type.SALES_ORDER,
      fromId: body.salesOrderId,
      toType: record.Type.ITEM_FULFILLMENT,
      isDynamic: true
    });
    fulfillment.setValue({ fieldId: 'memo', value: 'tracking:' + body.trackingNo });
    const id = fulfillment.save();
    return { fulfillmentId: id, remainingUsage: runtime.getCurrentScript().getRemainingUsage() };
  };
  return { post };
});

応答に残りのユニット数を返しておくと、本番の負荷で上限に近づいているかを連携側のログから追えます。数百件をまとめて受ける作りにすると5,000ユニットを超えるため、1回の呼び出しで扱う件数に上限を設けます。

EC・販売管理とNetSuiteをつなぐデータの持ち主とバックアップの設計

どのデータをどちらが正とするかが曖昧だと、同期のたびに値が上書きし合います。

受注・在庫・顧客・出荷のデータをEC側とNetSuite側のどちらに置くかの設計表

EC・販売管理とNetSuiteをつなぐ場合の、よくある持ち主の分け方です。

データ 正とする側 流れる向き 同期の契機
商品マスタ NetSuite NetSuiteからEC 変更時
在庫数 NetSuite NetSuiteからEC 定期(例:15分)
受注 EC ECからNetSuite 注文確定時
顧客 EC ECからNetSuite 受注と同時
出荷と追跡番号 NetSuite NetSuiteからEC 出荷確定時

1つのデータの正は必ず片側に置き、逆向きの書き込みを作らないことが原則です。在庫を両側で更新すると、同期の間に売れた分で数が合わなくなります。EC側の受注や在庫の機能はEC受注管理システムの機能と導入判断を解説した記事と多店舗の在庫連携と受注同期を解説した記事にまとめています。

Full CSV Exportだけでは足りないバックアップと、SuiteQLでの定期退避

NetSuiteのバックアップとしてまず挙がるのはFull CSV Exportです。公式ヘルプ「Exporting Selected Lists and Reports as CSV Files」によると、場所はSetup > Import/Export > Export Tasks > Full CSV Exportで、使えるのは管理者ロールだけです。ただし同じページは、すべてのデータを書き出すわけではないと明記しており、対象は顧客・仕入先・品目・取引明細のレポートなど一覧に挙がった種類に限られます。

監査や移行に備えて手元に持ちたいなら、前章のSuiteQLの関数を日次で回し、内部IDごと自社の保管先へ書き出すほうが確実です。内部IDを残しておけば、取引と顧客の関係を後から組み立て直せます。10万件を超える取引は、SuiteAnalytics Connectに切り替えます。

ファイルキャビネットの容量10GBとサービスティア別の上限の確認方法

連携で受け取った請求書PDFや画像をNetSuiteのファイルキャビネットに置く設計なら、容量も見積もります。公式ヘルプ「Uploading Files to the File Cabinet」によると、追加で購入していなければアカウントの総容量は10GBです。使用量は、Billing Information権限を持つユーザーがSetup > Company > View Billing InformationのFile Cabinet Sizeの行で確かめます。

サービスティアの公式表では、ファイル容量の上限はStandardで100GB、Premiumで1,000GB、Enterpriseで2,000GB、Ultimateで4,000GBまでです。上限を超えると、ファイル容量に限り90日の猶予が付きます。1件あたり数百KBのPDFでも、月に数万件を取り込めば数年で10GBに届くため、原本は外部のストレージに置き、NetSuiteにはURLだけを持たせる設計も選択肢に入れます。

NetSuite連携を自社で実装する条件と、導入支援に任せる場面の判断

分かれ目は、自社で保守を持ち続けられるかどうかです。

既製コネクタで済ませる会社と、REST・RESTletを自作すべき会社の境目

接続先がShopifyや主要モールだけで、受注と在庫の同期に業務独自の判定が無い会社は、既製コネクタを選びます。この規模でM2M認証やRESTletを自作するのは過剰で、証明書の更新とリリース対応の手間だけが残ります。目安は、項目の変換ルールをコネクタの設定画面で表せるかどうかです。同じ考え方はSalesforceのAPI方式の選定とコール上限の設計を解説した記事でも扱いました。

次のいずれかに当てはまるなら、RESTとSuiteQLを軸に自作します。自社の倉庫システムや独自の販売管理とつなぐ場合、受注ごとに与信や配送区分を判定する場合、上限15前後のアカウントで複数の連携が同時実行数を取り合う場合です。製品全体の位置づけや導入判断はNetSuiteの機能・料金構造とIPO準備企業に選ばれる理由を解説した記事にまとめています。

SOAPの既存連携を抱える会社が2027年までに済ませる棚卸しと相談の段階

SOAPの連携が残っている会社は、2027.1より前に、連携ごとのWSDLの版・使っている操作・呼び出し頻度を一覧にします。2025.2より古い版は2027.1でサポートの対象外になり、2025.2も2028.2で使えなくなるスケジュールです。移行ガイドの対応表で置き換え先が無い操作は、RESTletで作り直す前提で工数を見積もります。

認証の切り替え、同時実行数の配分、SOAPからの移行を導入・刷新のプロジェクトに含めて進めたい場合は、Oracle NetSuite導入支援サービスで連携の棚卸しから相談を受け付けています。汎用的なAPI連携の作り方はREST・認証・エラー処理を扱うAPI連携の実装手順も参考になります。

よくある質問

NetSuiteの連携とAPIについて、設計の段階でよく出る質問に答えます。

NetSuiteのREST APIを使うには何を有効にすればよいですか?

Setup > Company > Enable FeaturesのSuiteCloudタブで、REST Web ServicesとOAuth 2.0にチェックを入れるのが出発点です。機能を有効にしただけでは呼び出せません。連携に使うロールに、対象レコードの権限とOAuth 2.0のアクセストークンでログインする権限を付け、統合レコードを作って初めてトークンを取得できる状態になります。

トークンベース認証(TBA)の連携はそのまま使い続けられますか?

2026年10月時点の公式ヘルプにはTBAを前提にした記述が残っていますが、Oracleは新しく作る連携をRESTとOAuth 2.0で組むよう求めています。SOAPとTBAの組み合わせで動く連携も、2028.2のSOAP停止の対象です。認証より先にAPIの方式を移すことになるため、RESTへ移す際に認証もOAuth 2.0へまとめて切り替えれば、試験は1回で済みます。

NetSuiteのデータをバックアップする方法はありますか?

標準機能としてはFull CSV Exportがあり、管理者ロールで主要な一覧をCSVのZIPにまとめて書き出せます。ただ、全データの複製ではありません。取引まで含めて退避したいなら、SuiteQLを日次で回して内部IDごと自社の保管先へ書き出す方法が確実で、10万件を超える量ならSuiteAnalytics Connectに切り替えます。

NetSuiteのファイル容量が上限を超えるとどうなりますか?

上限を超えると、画面にバナーが出て管理者へメールが届きます。ファイル容量に限っては90日の猶予があり、その間に容量の追加購入か不要ファイルの整理を進める流れです。総容量は追加購入が無ければ10GBで、使用量はView Billing InformationのFile Cabinet Sizeの行で分かります。

同時実行数の上限を超えないために連携側でできることは何ですか?

最初にSetup > Integration > Integration Governanceで自社の上限を確かめ、連携ごとの持ち分を決めてください。そのうえで、待ち時間を延ばしながら再送するリトライを全連携に入れ、夜間バッチの開始時刻をずらします。RESTletは1回に扱う件数を絞るのが効果的です。それでも足りない場合の手段が、上限を10ずつ増やすSuiteCloud Plusの追加です。

関連記事

お気に入りに入れた記事の一覧

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.23 テックブログ Renta!不正アクセスでサービス停止:再開未定の現状と運営側の停止判断・証拠保全・段階的再開
  2. 2026.07.09 テックブログ Muse Imageとは?Metaの画像生成AIの使い方・API料金(1枚0.01ドル)と日本での提供状況【2026年10月】
  3. 2026.10.22 テックブログ Tomcatのバージョン一覧とサポート期限【2026年10月】最新版11.0.27、9.0系は2027年3月末終了・9.1系は2030年末まで
  4. 2026.10.24 テックブログ ブラストメール不正アクセス:配信先288件の漏えいと利用企業の報告・通知の手順
  5. 2025.12.10 コラム 今の50代は何世代?バブル世代・団塊ジュニア・氷河期の境目と特徴

RELATED POSTS 関連記事

目次