方法 5:API 連携
自社開発の受注システムがある場合や、他の 4 つでは要件を満たせない場合に選びます。モール連携・ERP 連携との違いはひとつだけ、この方法だけコードを書く必要があることです。 件数が多いだけで開発は避けたいなら方法 2:一括インポート、受注がモールや外部 ERP にあるなら方法 3〜4:自動連携へ。
API を選ぶべきケース
| 受注がどこにあるか | おすすめ |
|---|---|
| Amazon・Shopify・楽天などの販売モール | モール連携、開発不要 |
| 利用中の外部 ERP | ERP 連携、開発不要 |
| 件数が多くて手入力が追いつかないだけ | 一括インポート、開発不要 |
| 自社開発の受注システム、項目やタイミングを作り込みたい | API 連携 |
事前に用意するもの
| 必要なもの | 入手先 |
|---|---|
appKey / appSecret | OMS 右上のアバター → API信息(API 情報)(/userCenter/apiKeys) |
| API ドキュメント | https://apidoc-oms.xlwms.com/ |
| ベース URL | https://api.xlwms.com/openapi/ |
この画面は App Key / App Secret / 備考 / 作成日時 / 作成者 の一覧で、鍵は既定でマスク表示されます。右上には**開発験签工具(署名検証ツール)**のボタンがあり、公式の検証ページへ直接移動できます。
appSecret は署名鍵です。自社サーバー側にのみ保管し、フロントエンドやアプリに埋め込まないでください。リクエストの署名
すべてのリクエストに署名 authcode が必要で、アルゴリズムは HmacSHA256 です。
- 業務パラメータ
dataの項目を**辞書順(大文字小文字を区別しない)**に並べ替えて JSON 化する appKey+ 並べ替えたdata+reqTimeの順に区切り文字なしで連結するappSecretを鍵として HmacSHA256 を計算し、16 進数文字列に変換したものがauthcode
渡し方にも注意が必要です。authcode は URL クエリ、appKey / data / reqTime は POST ボディで送ります。
| パラメータ | 位置 | 説明 |
|---|---|---|
authcode | URL クエリ | 上記で算出した署名 |
appKey | POST ボディ | OMS 管理画面で発行された key |
reqTime | POST ボディ | 10 桁の UNIX タイムスタンプ(秒) |
data | POST ボディ | 業務パラメータ。作成 API では配列 |
reqTime が 5 分を超えたリクエストはサーバー側で拒否されます。 署名を使い回さず、サーバーの時刻ずれにも注意してください。署名が合わないときは公式の検証ツール
ドキュメントサイトにオンライン検証ツールがあります。appKey・data・reqTime を貼り付けて比較すれば、並べ替え・シリアライズ・連結のどこで食い違っているかがすぐ分かります。
署名のサンプルコード
ドキュメントに沿った最小構成です。接続テストの前に必ず公式の検証ツールで一度突き合わせてください。
// Node.js 18+
import crypto from 'node:crypto'
function sign({ appKey, appSecret, data, reqTime }) {
// 1. data 内字段按字典序(不区分大小写)排序后序列化
const sortedData = JSON.stringify(sortKeys(data))
// 2. 三段直接拼接,没有分隔符
const raw = `${appKey}${sortedData}${reqTime}`
// 3. HmacSHA256 后转十六进制
return crypto.createHmac('sha256', appSecret).update(raw).digest('hex')
}
function sortKeys(value) {
if (Array.isArray(value)) return value.map(sortKeys)
if (value && typeof value === 'object') {
return Object.fromEntries(
Object.keys(value)
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
.map((k) => [k, sortKeys(value[k])])
)
}
return value
}
const appKey = process.env.OMS_APP_KEY
const appSecret = process.env.OMS_APP_SECRET
const reqTime = String(Math.floor(Date.now() / 1000))
const data = [
{
whCode: 'TEST',
thirdOrderNo: 'SO-20260903-0001',
subOrderType: 1,
logisticsChannel: 'T_YAMATO_BIN',
receiver: '佐藤 健太',
telephone: '09012345678',
countryRegionCode: 'JP',
provinceName: '東京都',
cityName: '渋谷区',
postCode: '150-0002',
addressOne: '渋谷 3-15-7',
isSubmit: 1,
itemList: [{ sku: 'APP-TSHIRT-006', quantity: 1 }]
}
]
const authcode = sign({ appKey, appSecret, data, reqTime })
const res = await fetch(
`https://api.xlwms.com/openapi/v1/outboundOrder/create?authcode=${authcode}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ appKey, reqTime, data })
}
)
console.log(await res.json())# Python 3
import hashlib, hmac, json, os, time, requests
def sort_keys(value):
if isinstance(value, list):
return [sort_keys(v) for v in value]
if isinstance(value, dict):
return {k: sort_keys(value[k]) for k in sorted(value, key=str.lower)}
return value
def sign(app_key, app_secret, data, req_time):
sorted_data = json.dumps(sort_keys(data), ensure_ascii=False, separators=(',', ':'))
raw = f'{app_key}{sorted_data}{req_time}'
return hmac.new(app_secret.encode(), raw.encode(), hashlib.sha256).hexdigest()
app_key, app_secret = os.environ['OMS_APP_KEY'], os.environ['OMS_APP_SECRET']
req_time = str(int(time.time()))
data = [{
'whCode': 'TEST',
'thirdOrderNo': 'SO-20260903-0001',
'subOrderType': 1,
'logisticsChannel': 'T_YAMATO_BIN',
'receiver': '佐藤 健太',
'telephone': '09012345678',
'countryRegionCode': 'JP',
'provinceName': '東京都',
'cityName': '渋谷区',
'postCode': '150-0002',
'addressOne': '渋谷 3-15-7',
'isSubmit': 1,
'itemList': [{'sku': 'APP-TSHIRT-006', 'quantity': 1}],
}]
authcode = sign(app_key, app_secret, data, req_time)
r = requests.post(
'https://api.xlwms.com/openapi/v1/outboundOrder/create',
params={'authcode': authcode},
json={'appKey': app_key, 'reqTime': req_time, 'data': data},
)
print(r.json())ドロップシッピング出庫受注の作成
POST /v1/outboundOrder/create、1 回あたり最大 100 件。
主な項目(完全な仕様は公式ドキュメントを参照):
| 項目 | 必須 | 画面上の項目 | 説明 |
|---|---|---|---|
whCode | ✳︎ | 倉庫 | 倉庫コード、最大 30 |
thirdOrderNo | ✳︎ | —— | 外部番号。グローバルに一意、最大 100 |
subOrderType | ✳︎ | —— | 1 = 商品単位、2 = 箱単位 |
logisticsChannel | ✳︎ | 物流チャンネル | チャンネルコード(例:T_YAMATO_BIN) |
referOrderNo | 参照番号 | 自社システムの番号 | |
platformOrderNo | プラットフォーム受注番号 | モール側の注文番号 | |
isSubmit | —— | 0 = ドラフト保存(既定)、1 = そのまま提出 | |
remark | 備考 | API は 255 まで。ただし配送業者側は全角 32 まで | |
receiver | ✳︎ | 受取人 | |
telephone | 電話番号 | API では任意。ただしヤマト・佐川は必須 | |
countryRegionCode | ✳︎ | 国・地域 | 日本は JP 固定 |
provinceName | ✳︎ | 都道府県 | 日本は都道府県名(例:東京都) |
provinceCode | ✳︎ | 都道府県 | 米国・カナダ・オーストラリアでは必須 |
cityName | ✳︎ | 都市名 | 日本は市区町村 |
postCode | ✳︎ | 郵便番号 | |
addressOne | ✳︎ | アドレス1 | API は 255 まで。ただし配送業者側は全角 16 まで |
addressTwo | アドレス2 | 同上、全角 16 まで | |
district | 市区町村(区/县) | 日本宛では空欄 | |
itemList[].sku | ✳︎ | SKU | |
itemList[].quantity | ✳︎ | 出庫数 |
isSubmit で受注の行き先が決まります。1 なら即提出となり、その後の分岐は配送業者次第です——ヤマトは倉庫処理中へ直行、佐川はドラフトの「提出待ち」で止まります。STEP 6 を参照。作成後に使う API
| 用途 | API |
|---|---|
| 出庫受注の一覧をページング取得 | getParcelOutboundOrders |
| 出庫受注の詳細取得(ステータス・追跡番号の取得) | getOutboundOrder |
| 出庫受注の一括キャンセル(非同期) | batchCancelOutboundOrder |
| 出庫受注の集約ステータス取得(キャンセル結果の確認) | selectBizStatus |
| 追跡番号・送り状の更新(自社送り状を使う場合) | updateTrackNoAndLabel |
| 出庫受注へのメッセージ・添付の追加 | replyBigOutboundMessage |
必ず避けたい 3 つの落とし穴
重要 HTTP 500 は作成失敗を意味しません。 公式ドキュメントに、ネットワーク異常時は失敗と断定できないと明記されています。闇雲に再送すると受注が二重に作成されます。詳細取得 API でthirdOrderNo を照会し、作成されていないことを確認してから再送してください。注意 code: 200 はリクエストの成功を示すだけで、各受注が作成できたかは別です。1 件ごとの結果は data[].success と data[].msg を確認してください。注意 thirdOrderNo はグローバルに一意です。冪等キーとして使えば、同じ外部番号での再送で二重作成を防げます。リトライ処理の安全網になります。品揃え転送(ToB)は別の API
このページはすべてドロップシッピング(小包出庫受注)の話です。品揃え転送出庫(ToB)は別系統で、createBigOutboundOrder(商品単位)と createBoxStockOutboundOrder(箱単位)を使います。照会・キャンセルの API も別です。
仕様は公式ドキュメントが正
このページはドロップシッピング出庫受注を連携する際の主な流れと、つまずきやすい点だけをまとめたものです。項目の完全な仕様・エラーコード・他業務の API は公式ドキュメントをご覧ください:https://apidoc-oms.xlwms.com/