eSIM サードパーティ統合 API
旅行会社・代理店・自社サービスに弊社の eSIM 商品を組み込むための REST API。商品取得・注文作成・払戻・Webhook 通知を 1 つの API キーで完結します。
はじめに
eSIM Channel API は RESTful + JSON 形式の HTTPS API です。全リクエストに X-Channel-Api-Key ヘッダで弊社発行のキーを設定してください。日時は ISO 8601 UTC、金額は JPY (整数円) で表現します。
https://api.esimsenmon.com/v1 (本番環境)クイックスタート
最初の API リクエストを送るまでの 5 ステップ:
- API キー発行依頼: 弊社運営に「API 連携希望」とご連絡ください。打ち合わせ後に専用キーを発行します。
- キーの保管: 発行時に
ck_live_xxxxxxxxxxxxxxxxxxxxxxxx形式の平文キーを 1 度だけ返却します。貴社のシークレット管理システムで安全に保管してください。 - 商品一覧の取得: 下記 curl の
YOUR_KEYを実際のキーに置換して実行すると、貴社チャネルで販売可能な商品が確認できます。 - 注文の作成: 商品 sku を送信すると、注文を即時作成して eSIM 発行を開始します (貴社側で決済済の前提)。
- Webhook URL の登録: 注文確定・払戻通知を受け取る URL を弊社運営にお知らせください。
curl https://api.esimsenmon.com/v1/channel/products \
-H "X-Channel-Api-Key: ck_live_YOUR_KEY"const res = await fetch(
"https://api.esimsenmon.com/v1/channel/products",
{ headers: { "X-Channel-Api-Key": "ck_live_YOUR_KEY" } },
);
const { data } = await res.json();
console.log(data);import requests
r = requests.get(
"https://api.esimsenmon.com/v1/channel/products",
headers={"X-Channel-Api-Key": "ck_live_YOUR_KEY"},
)
print(r.json()["data"])レスポンス例:
{
"data": [
{
"sku": "FAM-100GB-365D-2C",
"name": "100GB ファミリープラン",
"contentMd": "> 100GB 自由に組み合わせ ...",
"category": "family",
"totalGbLimit": 100,
"cardCountLimit": 2,
"validityDays": 365,
"priceJpy": 14900,
"badge": null,
"featured": false,
"sortOrder": 0
}
]
}認証
貴社からの全 API リクエストには、X-Channel-Api-Key HTTP ヘッダで弊社発行のキーを設定してください。キー未指定・無効・失効済の場合は 401 UNAUTHORIZED を返します。
キー形式
発行するキーは ck_live_ + 24 文字 base62 = 計 32 文字です。先頭 12 文字 (ck_live_xxxx) は識別用 prefix として弊社管理画面に表示されます。完全な平文キーは発行時に 1 度だけ返却し、それ以降は再表示できません。紛失時は新規発行 + 旧キー失効を弊社運営までご依頼ください。
スコープ (Scope)
発行するキーには複数の scope (権限) が紐づいており、エンドポイントごとに要求される scope が異なります。発行時には用途に応じた最小限の scope のみを付与しますので、想定するユースケースを事前にお知らせください。
| Scope | 説明 | 対象エンドポイント |
|---|---|---|
read:products | 取扱商品の参照 | GET /products |
read:orders | 注文の参照 | GET /orders, GET /orders/[id] |
write:orders | 注文の作成 | POST /orders |
read:esim | eSIM カード詳細・残量の参照 | GET /esim/[cardId] |
read:analytics | 売上・分析データの参照 | (将来追加予定) |
write:refunds | 払戻の申請 | POST /orders/[id]/refund |
IP allowlist (送信元 IP 制限)
貴社サーバの送信元 IP を弊社にお知らせいただければ、当該 API キーの接続元を制限します。CIDR (例: 203.0.113.0/24) と単一 IP (例: 203.0.113.1) の両方をサポートし、複数登録も可能です。IP 制限を設けない運用も可能ですので、貴社のセキュリティポリシーに合わせてご選択ください。
X-Forwarded-For ヘッダの先頭値を送信元 IP として判定します。中間プロキシの IP を allowlist に登録しないようご注意ください。レート制限
API キーの既定レートは 1 分あたり 100 リクエストです。超過時は HTTP 429 + Retry-After ヘッダを返しますので、貴社側で指数バックオフ + 再試行を実装してください。上限引き上げが必要な場合は弊社運営までご相談ください。
残量は以下のレスポンスヘッダで確認できます:
| ヘッダ | 内容 |
|---|---|
X-RateLimit-Limit | 1 分あたりの上限 |
X-RateLimit-Remaining | 現在ウィンドウの残量 |
X-RateLimit-Reset | リセット Unix timestamp (秒) |
Retry-After | (429 時のみ) 秒数 |
エンドポイント
全エンドポイントは https://api.esimsenmon.com/v1/channel 配下に配置されています。
GET/me— アカウント情報取得
リクエストに使用された API キーと、紐づくチャネル (貴社) のメタ情報を返します。接続テストおよびキーの有効性確認に使用してください。必要 scope: なし
curl https://api.esimsenmon.com/v1/channel/me \
-H "X-Channel-Api-Key: $KEY"{
"data": {
"channel": { "slug": "yuria", "name": "ゆりあストア", "type": "kol", "active": true },
"apiKey": { "name": "本番用", "scopes": ["read:products", "read:orders", "write:orders"] }
}
}GET/products— 商品一覧取得
貴社チャネルで販売可能な商品の一覧を返します (弊社側で非公開設定の商品は含まれません)。必要 scope: read:products
多言語対応 (Accept-Language)
リクエストヘッダ Accept-Language でレスポンスの name / contentMd の言語を切り替えできます。対応言語: ja / en / zh-CN / ko。指定言語の翻訳が無い場合は ja にフォールバックします。同時に translations オブジェクトで全言語版も返却するため、貴社側で都度切替も可能です。
curl https://api.esimsenmon.com/v1/channel/products \
-H "X-Channel-Api-Key: $KEY" \
-H "Accept-Language: en"レスポンス各 item の主なフィールド:
| field | type | 説明 |
|---|---|---|
sku | string | 商品 SKU (注文作成時のキー) |
name | string | 商品名 (リクエストの Accept-Language に応じた言語で返却) |
contentMd | string | 商品説明 Markdown (リクエストの Accept-Language に応じた言語で返却) |
priceJpy | int | 商品価格 (円) |
totalGbLimit | int | 合計 GB |
validityDays | int | 有効日数 |
cardCountLimit | int | 発行可能 eSIM 枚数 |
coverageCountries | string[] | 対応国コード一覧 (ISO 3166-1 alpha-2、cardTypes から集約・重複排除済) |
cardTypes | object[] | この商品が発行する eSIM カードの詳細リスト (詳細は下表) |
translations | object | 全言語版の name / contentMd。キーは ja / en / zh-CN / ko。貴社で言語切替に利用ください。 |
cardTypes[] の各要素:
| field | type | 説明 |
|---|---|---|
type | string | local / roaming_32 / roaming_110 |
productType | string | null | 商品タイプ (上流原始値): "1"=無制限プラン / "2"=総量プラン / "3"=日単位プラン (記載以外の値が返る可能性あり) |
usageLocation | string | null | 使用エリア (例: Japan) |
country | string | null | 国コード ISO 3166-1 alpha-2 (例: JP)。マルチ国漫遊カードは null |
operator | string | null | 通信事業者 (例: NTT DOCOMO) |
apn | string | null | APN 名 (例: internet)。設定不要なカードは null |
networkTypes | string | null | 対応ネットワーク (例: 4G/5G) |
usageMethod | string | null | 回線使用方式 (例: ローカル回線 / ローミング回線) |
cardCategory | int | null | プラン区分: 1=直営データプラン / 2=再販プラン / 3=キャリア純粋プラン |
isRechargeable | bool | チャージ可能か |
validityDayMode | int | null | 有効期間の計算方式: 1=自然日 / 2=24時間制 |
validityTimezone | string | null | 有効期間のタイムゾーン (validityDayMode=1 のみ有効。例: UTC+8) |
dailyResetTimezone | string | null | 日次データリセットのタイムゾーン記述 (例: UTC+8 00:00 — そのタイムゾーンの 00:00 にリセット) |
{
"data": [
{
"sku": "FAM-100GB-365D-2C",
"name": "100GB ファミリープラン",
"contentMd": "> 100GB 自由に組み合わせ ...",
"totalGbLimit": 100,
"cardCountLimit": 2,
"validityDays": 365,
"priceJpy": 14900,
"coverageCountries": ["JP", "KR", "TW", "SG", "TH", "MY", "VN", "PH", "ID", "..."],
"cardTypes": [
{
"type": "local",
"productType": "2",
"usageLocation": "Japan",
"country": "JP",
"operator": "NTT DOCOMO",
"apn": "internet",
"networkTypes": "4G/5G",
"usageMethod": "ローカル回線",
"cardCategory": 2,
"isRechargeable": true,
"validityDayMode": 1,
"validityTimezone": "UTC+8",
"dailyResetTimezone": "UTC+8 00:00"
},
{
"type": "roaming_32",
"productType": "1",
"usageLocation": "Asia 32-country roaming",
"country": null,
"operator": "3HK",
"apn": null,
"networkTypes": "4G",
"usageMethod": "ローミング回線",
"cardCategory": 1,
"isRechargeable": false,
"validityDayMode": 2,
"validityTimezone": null,
"dailyResetTimezone": "UTC+8 00:00"
}
],
"translations": {
"ja": { "name": "100GB ファミリープラン", "contentMd": "..." },
"en": { "name": "100GB Family Plan", "contentMd": "..." },
"zh-CN": { "name": "100GB 家庭套餐", "contentMd": "..." },
"ko": { "name": "100GB 패밀리 플랜", "contentMd": "..." }
}
}
]
}POST/orders— 注文作成 (eSIM 発行)
貴社が既に終端ユーザから代金を受領済の前提で、本 API は eSIM 発行のみを行います (弊社側での決済は発生しません)。リクエスト成功時に注文 (status: paid) を即時作成し、eSIM 発行処理を開始します。
⚠️ 注意: 弊社から終端ユーザへ直接連絡することはありません。発行完了時に order.fulfilled webhook で QR コード / LPA URI / アクティベーションコードを貴社にプッシュしますので、QR コードと設定方法を終端ユーザへお届けするのは貴社の責任となります。必要 scope: write:orders
curl -X POST https://api.esimsenmon.com/v1/channel/orders \
-H "X-Channel-Api-Key: $KEY" \
-H "Content-Type: application/json" \
-d '{
"sku": "FAM-100GB-365D-2C",
"quantity": 1,
"externalOrderRef": "YOUR-ORDER-12345",
"customerEmail": "customer@example.com"
}'{
"data": {
"orderId": "cm0xxxxxxxxxxxxxxx",
"status": "paid",
"amount": 14900,
"fulfillment": "pending",
"message": "eSIM 発行完了時に order.fulfilled webhook で通知"
}
}リクエスト body フィールド:
| field | type | 説明 |
|---|---|---|
sku required | string | 商品 SKU (/products から取得) |
quantity | int | 数量 (既定 1) |
externalOrderRef required | string | 貴社側の注文 ID (1〜200 文字、冪等キーとして機能)。同一チャネル内で同じ値を再送信した場合は新規作成せず、<code>ALREADY_EXISTS</code> エラーで既存の orderId を返します。後続の webhook でもこの値を原様にて返却します。 |
customerEmail | string | 終端顧客のメールアドレス (任意)。注文に記録されます。 |
GET/orders— 注文一覧取得
貴社チャネル経由の注文一覧を新しい順で返します。各注文には発行済 eSIM の詳細 (cardId / iccid / eid / activationCode / lpaUri / 残量等) も含まれます。必要 scope: read:orders
クエリパラメータ: ?status=pending|paid|fulfilling|fulfilled|failed|refunded ステータス絞り込み / ?externalOrderRef=YOUR-ORDER-12345 貴社注文 ID の完全一致 / ?cursor=<orderId> + ?limit=50 (最大 100) カーソルベースページング。
{
"data": [
{
"orderId": "cm0xxxxxxxxxxxxxxx",
"externalOrderRef": "YOUR-ORDER-12345",
"sku": "FAM-100GB-365D-2C",
"productName": "100GB ファミリープラン",
"quantity": 1,
"amountJpy": 14900,
"status": "fulfilled",
"sandbox": false,
"createdAt": "2026-05-24T08:12:33.000Z",
"paidAt": "2026-05-24T08:12:33.000Z",
"fulfilledAt": "2026-05-24T08:14:01.000Z",
"esims": [
{
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"iccid": "8981100012345678901",
"eid": null,
"cid": "1234567890",
"cardType": "local",
"activationCode": "1$rsp.example.com$ABC-123-XYZ-789",
"lpaUri": "LPA:1$rsp.example.com$ABC-123-XYZ-789",
"status": "active",
"activatedAt": "2026-05-25T03:10:00.000Z",
"expiresAt": "2027-05-24T08:14:01.000Z",
"planType": "total",
"totalGb": 50,
"usedGb": 12.4,
"remainingGb": 37.6,
"dailyQuotaGb": null,
"todayUsedGb": null,
"todayRemainingGb": null
}
]
}
],
"meta": { "nextCursor": "cm0yyyy...", "hasMore": true }
}GET/orders/{id}— 注文詳細取得
指定した注文 1 件の詳細を返します。レスポンス構造は GET /orders 一覧の各要素と同一で、発行済 eSIM カードの完全な詳細 (cardId / iccid / eid / cid / activationCode / lpaUri / 残量等) を含みます。注文ステータスが failed の場合は failureReason も付加されます。必要 scope: read:orders
{
"data": {
"orderId": "cm0xxxxxxxxxxxxxxx",
"externalOrderRef": "YOUR-ORDER-12345",
"sku": "FAM-100GB-365D-2C",
"productName": "100GB ファミリープラン",
"quantity": 1,
"amountJpy": 14900,
"status": "fulfilled",
"sandbox": false,
"createdAt": "2026-05-24T08:12:33.000Z",
"paidAt": "2026-05-24T08:12:33.000Z",
"fulfilledAt": "2026-05-24T08:14:01.000Z",
"failureReason": null,
"esims": [
{
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"iccid": "8981100012345678901",
"eid": null,
"cid": "1234567890",
"cardType": "local",
"activationCode": "1$rsp.example.com$ABC-123-XYZ-789",
"lpaUri": "LPA:1$rsp.example.com$ABC-123-XYZ-789",
"status": "active",
"activatedAt": "2026-05-25T03:10:00.000Z",
"expiresAt": "2027-05-24T08:14:01.000Z",
"totalGb": 50,
"usedGb": 12.4
}
]
}
}POST/orders/{id}/refund— 払戻申請
指定の注文を refunded ステータスにマークし、未払の commission を取消し、order.refunded webhook を貴社にプッシュします。
⚠️ 注意: 本 API は 弊社 DB 上のステータス変更と通知のみを行います。チャネル API 経由の注文は貴社が終端ユーザから直接代金を受領しているため、弊社では Stripe / Komoju 等の決済データを保持しておらず、終端ユーザへの実際の返金処理は貴社で実施してください。
🚫 PAYG (従量精算) チャネルは本 API を呼び出さないでください。月次の使用量精算で完結するため、個別注文の返金概念がありません。誤って呼び出された場合は 403 PAYG_NOT_REFUNDABLE を返します。
備考: 現状、eSIM カード自体の作廃 (失効) はまだ実装していません (今後のリリースで対応予定)。必要 scope: write:refunds
curl -X POST https://api.esimsenmon.com/v1/channel/orders/cm0xxxxxxxxxxxxxxx/refund \
-H "X-Channel-Api-Key: $KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "customer_request" }'{
"data": {
"refundRequestId": "rrq_a3f8x2qp7c5d9e1b4f6a8c2d",
"orderId": "cm0xxxxxxxxxxxxxxx",
"externalOrderRef": "YOUR-ORDER-12345",
"status": "refunded",
"refundAmountJpy": 14900,
"refundedAt": "2026-05-25T03:00:00.000Z",
"reason": "customer_request"
}
}HTTP/1.1 403 Forbidden
{
"error": {
"code": "PAYG_NOT_REFUNDABLE",
"message": "PAYG 結算のチャネルでは個別注文の返金処理を行いません (月次の使用量精算のみ)"
}
}eSIM API
GET/esim/{cardId}— eSIM 詳細・QR 取得
1 枚の eSIM の詳細を返します。終端ユーザ端末への設定に必要な LPA URI (この値から QR コードを生成)、アクティベーションコード、現在の残量データが含まれます。
国別データ量内訳 countryUsage: 多国漫遊カード (cardType=roaming_32 / roaming_110) では、国/地域ごとの使用量・総量・残量 (GB + MB) の配列を返します (countryName は日本語名優先)。単国 (local) カードや国別用量が無い場合は空配列 []。必要 scope: read:esim
curl https://api.esimsenmon.com/v1/channel/esim/card_01HZX7Z8K9P3B0M4QXYAR6V0AT \
-H "X-Channel-Api-Key: $KEY"{
"data": {
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"orderId": "cm0xxxxxxxxxxxxxxx",
"externalOrderRef": "YOUR-ORDER-12345",
"sku": "FAM-100GB-365D-2C",
"iccid": "8981100012345678901",
"eid": null,
"cid": "1234567890",
"cardType": "local",
"activationCode": "1$rsp.example.com$ABC-123-XYZ-789",
"lpaUri": "LPA:1$rsp.example.com$ABC-123-XYZ-789",
"status": "active",
"activatedAt": "2026-05-25T03:10:00.000Z",
"expiresAt": "2027-05-24T08:14:01.000Z",
"planType": "total",
"totalGb": 50,
"usedGb": 12.4,
"remainingGb": 37.6,
"countryUsage": [
{ "countryName": "マレーシア", "usedMb": 459.36, "usedGb": 0.46, "totalMb": 20000, "totalGb": 20, "remainingGb": 19.54 },
{ "countryName": "香港", "usedMb": 3339.56, "usedGb": 3.34, "totalMb": 6000, "totalGb": 6, "remainingGb": 2.66 }
]
}
}GET/esim/{cardId}/usage-daily— 日別使用量履歴取得
対象カードの使用量を日単位で返します。各要素は date (UTC 基準の暦日、YYYY-MM-DD) ごとの合計使用量 usedGb と、国/地域別の内訳 countries[] (mcc / countryName 日本語名 / countryNameEn / usedGb) を含みます。使用実績が無い日はレスポンスに含まれません。
⚠️ データ反映の遅延について: SoftBank 回線商品の使用量データは、キャリア側の仕様により確定値の反映まで約 2 日程度の遅延が発生します (弊社側では変更できません)。そのため、リアルタイムの正確な使用量としてのご利用は推奨いたしません。精算時の照合用データとしてのご利用を推奨します。貴社にて終端ユーザ向けに使用量照会機能を提供される場合は、データ反映に遅延がある旨を必ず注記してください。必要 scope: read:esim
クエリパラメータ: ?days=30 — 直近何日分を返すか (1〜90、既定 30)。
curl "https://api.esimsenmon.com/v1/channel/esim/card_01HZX7Z8K9P3B0M4QXYAR6V0AT/usage-daily?days=30" \
-H "X-Channel-Api-Key: $KEY"{
"data": {
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"days": 30,
"timezone": "UTC",
"series": [
{
"date": "2026-06-28",
"usedGb": 0.412,
"countries": [
{ "mcc": "440", "countryName": "日本", "countryNameEn": "Japan", "usedGb": 0.412 }
]
},
{
"date": "2026-06-29",
"usedGb": 1.087,
"countries": [
{ "mcc": "440", "countryName": "日本", "countryNameEn": "Japan", "usedGb": 0.885 },
{ "mcc": "454", "countryName": "香港", "countryNameEn": "Hong Kong", "usedGb": 0.202 }
]
}
]
}
}GET/esim/{cardId}/recharge-records— 充值記録履歴取得
対象カードのチャージ履歴を、実際にチャージされた容量 dataGb (真実の GB) 付きで新しい順に返します。各要素は country (国名・日本語) / productName / dataGb / status (0 待充值 / 1 成功 / 2 失敗 / 3 処理中) / statusLabel / rechargeTime (YYYY-MM-DD HH:mm:ss・UTC+8) / cid を含みます。
用途: GET /upstream-orders の明細は 1 チャージ = 1 明細で容量を持たず、明細数から GB を復元できないケース (上流が複数 GB のチャージを「1GB」1 明細で返す) があります。本エンドポイントは上流の真実の充値容量を返すため、チャージ容量の照合・訂正に使用してください。
注意: 同一チャージが上流で複数行に分かれることがあるため、(country, rechargeTime, dataGb, status) が同一の行は 1 件に畳んで返します。発券前 (activationCode 未確定) のカードは空配列 [] を返します。必要 scope: read:esim
curl "https://api.esimsenmon.com/v1/channel/esim/card_01HZX7Z8K9P3B0M4QXYAR6V0AT/recharge-records" \
-H "X-Channel-Api-Key: $KEY"{
"data": {
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"records": [
{
"country": "スウェーデン",
"productName": "スウェーデン 0日間 13GB",
"dataGb": 13,
"status": 1,
"statusLabel": "success",
"rechargeTime": "2026-06-02 11:19:18",
"cid": "89851000000008671227"
},
{
"country": "中国",
"productName": "中国 0日間 6GB",
"dataGb": 6,
"status": 1,
"statusLabel": "success",
"rechargeTime": "2026-06-02 11:10:48",
"cid": "89851000000008671227"
}
]
}
}データチャージ API
既に発行済の eSIM カードに対し、追加のデータ容量を 同期処理でチャージします。漫遊カード (3HK / CSL / SoftBank 等) と日本ローカルカード (docomo) の両方に 1 つのエンドポイントで対応。caller は GET /recharge-options でカードに合うプラン一覧を取得し、選択した項目を POST /recharge に渡すだけです。X-Channel-Api-Key の sandbox キー (ck_test_) を使用すると上流発行を skip して即座に fulfilled になります。必要 scope: read:recharges / write:recharges。
GET/recharge-options— チャージプラン全件一覧 (カード不要)
カードを指定せず、取扱可能なチャージプランを全件返します。商品同期と同じく、定期的にこのエンドポイントを取得してローカルにキャッシュする用途に最適です (発行済カードを必要としません)。
クエリ kind=roaming|local|all (既定 all) と resource=3HK|CSL|docomo … (省略時は全 resource) で絞り込めます。各 item の形式は per-card 版と同一 (kind により漫遊/ローカルが切替) で、漫遊は resource フィールドも付与します。
取得した rechargePlanCode / sku は、後で対象カードの POST /esim/{cardId}/recharge にそのまま渡せます。
注: 全件版は当チャネルで上架 (enabled) 済の項目のみを返し、sellPriceJpyPerGb / sellPriceJpy (売価) を付与します。per-card 版は当該カードに該当する項目を上架フィルタ無し・原価ベースで返すため、両者のフィールドは完全一致ではありません。必要 scope: read:recharges
curl "https://api.esimsenmon.com/v1/channel/recharge-options?kind=all" \
-H "X-Channel-Api-Key: $KEY"{
"data": [
{
"kind": "roaming",
"rechargePlanCode": "116000",
"resource": "3HK",
"country": "フランス",
"countryEn": "France",
"countryCode": 208,
"suggestedCapacityGb": null,
"days": null,
"costJpyPerGb": 147
},
{
"kind": "local",
"sku": "desim-46553-japan-esim-total-0D-5G",
"resource": "docomo",
"productName": "0日間5GB",
"country": "Japan",
"addedGb": 5,
"days": 0,
"amountJpy": 507
}
],
"meta": {
"kind": "all",
"resource": null,
"total": 2
}
}GET/esim/{cardId}/recharge-options— チャージ可能プラン一覧 (カード別)
対象カードに対してチャージ可能なプラン一覧を返します。カードの種類によって自動的にデータソースが切り替わります:
漫遊カード (cardType=roaming32 / roaming110): 国別のチャージプラン一覧 (rechargePlanCode + 国 + 推奨容量 + 単価) を返します。caller はその中から国を選んで capacityGb (GB) を指定して POST します。
ローカルカード (cardType=local): 固定容量パッケージ一覧 (sku + 容量 + 一括価) を返します。caller は sku をそのまま POST に渡します。meta.cardType / meta.resource も同時に返却します。必要 scope: read:recharges
curl https://api.esimsenmon.com/v1/channel/esim/card_01HZX7Z8K9P3B0M4QXYAR6V0AT/recharge-options \
-H "X-Channel-Api-Key: $KEY"{
"data": [
{
"kind": "roaming",
"rechargePlanCode": "116000",
"country": "フランス",
"countryEn": "France",
"countryCode": 208,
"suggestedCapacityGb": null,
"days": null,
"costJpyPerGb": 147
},
{
"kind": "roaming",
"rechargePlanCode": "116004",
"country": "イタリア",
"countryEn": "Italy",
"countryCode": 222,
"suggestedCapacityGb": null,
"days": null,
"costJpyPerGb": 113
}
],
"meta": {
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"cardType": "roaming32",
"resource": "3HK",
"activated": true
}
}{
"data": [
{
"kind": "local",
"sku": "desim-46553-japan-esim-total-0D-5G",
"productName": "0日間5GB",
"country": "Japan",
"addedGb": 5,
"days": 0,
"amountJpy": 507
},
{
"kind": "local",
"sku": "desim-46554-japan-esim-total-0D-10G",
"productName": "0日間10GB",
"country": "Japan",
"addedGb": 10,
"days": 0,
"amountJpy": 800
}
],
"meta": {
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"cardType": "local",
"resource": "docomo",
"activated": true
}
}POST/esim/{cardId}/recharge— チャージ実行
1 endpoint で漫遊カード/ローカルカード両方のチャージを実行します。Body の構造は 2 種類のうち 1 つだけを指定:
漫遊カード: { rechargePlanCode, capacityGb, externalRechargeRef } — 国別のチャージプランを指定し、容量 GB を自由に決定
ローカルカード: { sku, externalRechargeRef } — 容量・期間が固定の SKU パッケージを直接指定
同期処理で、レスポンス時にはチャージ処理と端末側 EsimCard.allocatedGb 加算が完了しています。externalRechargeRef は冪等キー —— 同一値で再送した場合は新規実行せず既存結果を返します (alreadyExists: true)。失敗時は同 ref では再試行不可、新しい ref で再投してください。
レスポンス主要フィールド: rechargeId (チャージ ID) / status (fulfilled=成功 / failed=失敗) / alreadyExists (bool、冪等再送時 true) / addedGb (加算した GB) / amountJpy (金額) / cardId / 失敗時のみ failureReason (中性化メッセージ)。
返金について: チャージは終端ユーザ課金を伴わない記録のため、注文 API のような払戻 (refund) 概念はありません。失敗レコードは status:"failed" として残ります。必要 scope: write:recharges
curl -X POST https://api.esimsenmon.com/v1/channel/esim/card_01HZX7Z8K9P3B0M4QXYAR6V0AT/recharge \
-H "X-Channel-Api-Key: $KEY" \
-H "Content-Type: application/json" \
-d '{
"rechargePlanCode": "116000",
"capacityGb": 5,
"externalRechargeRef": "YOUR-RECHARGE-12345"
}'{
"data": {
"rechargeId": "rch_01HZX9F8K2N4P0M3QWY1ARV0BT",
"status": "fulfilled",
"kind": "roaming",
"sandbox": false,
"alreadyExists": false,
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"addedGb": 5,
"amountJpy": 733,
"externalRechargeRef": "YOUR-RECHARGE-12345",
"rechargePlanCode": "116000",
"country": "フランス",
"sku": null,
"topupAcceptSn": "TS20260528031000XYZ",
"addPackAcceptSn": null,
"failureReason": null
}
}curl -X POST https://api.esimsenmon.com/v1/channel/esim/card_01HZX7Z8K9P3B0M4QXYAR6V0AT/recharge \
-H "X-Channel-Api-Key: $KEY" \
-H "Content-Type: application/json" \
-d '{
"sku": "desim-46553-japan-esim-total-0D-5G",
"externalRechargeRef": "YOUR-RECHARGE-67890"
}'{
"data": {
"rechargeId": "rch_01HZX9F8K2N4P0M3QWY1ARV0CU",
"status": "fulfilled",
"kind": "local",
"sandbox": false,
"alreadyExists": false,
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"addedGb": 5,
"amountJpy": 507,
"externalRechargeRef": "YOUR-RECHARGE-67890",
"rechargePlanCode": null,
"country": "Japan",
"sku": "desim-46553-japan-esim-total-0D-5G",
"topupAcceptSn": null,
"addPackAcceptSn": null,
"failureReason": null
}
}{
"data": {
"rechargeId": "rch_01HZX9F8K2N4P0M3QWY1ARV0BT",
"status": "failed",
"kind": "roaming",
"sandbox": false,
"alreadyExists": false,
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"addedGb": 5,
"amountJpy": 733,
"externalRechargeRef": "YOUR-RECHARGE-12345",
"rechargePlanCode": "116000",
"country": "フランス",
"sku": null,
"topupAcceptSn": null,
"addPackAcceptSn": null,
"failureReason": "チャージ処理に失敗しました。同じ externalRechargeRef では再試行できません。新しい ref で再投してください。"
}
}リクエスト body フィールド (漫遊は rechargePlanCode + capacityGb、ローカルは sku のいずれか):
| フィールド | 型 | 説明 |
|---|---|---|
rechargePlanCode | string | 漫遊カード用。GET /recharge-options で取得した kind="roaming" 項目の rechargePlanCode。sku と排他。 |
capacityGb | number | 漫遊カード用。チャージ容量 (GB, > 0)。caller が自由に決定可能。rechargePlanCode と同時指定が必要。 |
sku | string | ローカルカード用。GET /recharge-options で取得した kind="local" 項目の sku。容量はプラン側で固定。rechargePlanCode と排他。 |
externalRechargeRef必須 | string | 貴社側のチャージ請求 ID (1〜200 文字、冪等キー)。同値で再送すると既存結果を返却。失敗時は新しい ref で再試行してください (同一 ref では再試行不可)。 |
GET/recharges— チャージ一覧取得
自チャネル経由のチャージ履歴を新しい順で返します。必要 scope: read:recharges
クエリパラメータ: ?status=pending|fulfilling|fulfilled|failed / ?cardId=<cardId> / ?externalRechargeRef=YOUR-RECHARGE-12345 / ?cursor=<rechargeId> + ?limit=50 (最大 100)。
GET/recharges/{rechargeId}— チャージ詳細取得
指定したチャージ 1 件の詳細を返します。レスポンス構造は GET /recharges 一覧の各要素と同一。ownership は channelSlug で検証され、別チャネルのチャージ ID を指定した場合は 403 FORBIDDEN を返します。必要 scope: read:recharges
Recharge Webhook イベント
上記 POST /recharge の処理完了時 (sandbox / live 両方)、以下のいずれかのイベントを設定済 webhook URL に配信します (詳細は下の Webhooks セクション参照)。冪等の再呼出 (alreadyExists: true) では再配信されません。
| イベント | 発火タイミング |
|---|---|
recharge.fulfilled | 上流発行に成功し、カード残量への加算が完了した時点 |
recharge.failed | 上流発行が失敗した時点。data.failureReason に中性化メッセージを含む |
{
"id": "evt_a3f8x2qp7c5d9e1b4f6a",
"type": "recharge.fulfilled",
"occurredAt": "2026-05-27T03:10:05.000Z",
"data": {
"rechargeId": "rch_01HZX9F8K2N4P0M3QWY1ARV0BT",
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"sku": "JP-LOCAL-10GB-RECHG",
"addedGb": 10,
"amountJpy": 1980,
"status": "fulfilled",
"sandbox": false,
"externalRechargeRef": "YOUR-RECHARGE-12345",
"createdAt": "2026-05-27T03:10:00.000Z",
"fulfilledAt": "2026-05-27T03:10:05.000Z"
}
}Webhook
注文確定・払戻完了などのイベントが発生すると、弊社から貴社の登録 URL に HTTP POST で通知します。Payload は JSON で、以下のリクエストヘッダを付与します: X-Channel-Webhook-Signature (HMAC-SHA256 hex 署名)、X-Channel-Webhook-Event (イベント type と同値)、X-Channel-Webhook-Version (現状 1)。改ざん防止のため、処理前に必ず署名検証を行ってください。
イベント種別
| event | 発火タイミング |
|---|---|
order.fulfilled | 注文の eSIM 発行完了 |
order.refunded | 払戻完了 |
esim.status | eSIM の状態が変化した時点 (有効化 / 失効)。<strong>購読不要・既定で配信</strong> |
esim.usage | eSIM の使用量 (used) または状態が変化した時点。<strong>購読不要・既定で配信</strong> |
esim.usage_alert | 顧客の eSIM 使用量が閾値超過 |
Payload 仕様
全イベントは共通の封筒 (envelope) 構造で配信されます。<code>type</code> でイベント種別を判定し、<code>data</code> 内に各イベント固有のフィールドが格納されます。
共通フィールド (全イベント)
各イベント payload には以下の共通フィールドが含まれます:
| field | type | 説明 |
|---|---|---|
id | string | イベント一意 ID (例: evt_01HZX...)。冪等な重複排除キーとして使用してください。 |
type | string | イベント種別 (order.fulfilled / order.refunded / esim.status / esim.usage / esim.usage_alert / recharge.fulfilled / recharge.failed) |
occurredAt | string | イベント発生日時 (ISO 8601 UTC) |
data | object | イベント固有のデータ。詳細は各イベント表を参照。 |
order.fulfilled — eSIM 発行完了
注文作成後に eSIM の発行が完了した時点で配信されます。data 内のフィールド:
| field | type | 説明 |
|---|---|---|
orderId | string | 弊社の注文 ID |
externalOrderRef | string | null | 注文作成時に貴社からご指定いただいた値 (未指定時は null) |
sku | string | 商品 SKU |
quantity | int | 数量 |
status | string | fulfilled |
amountJpy | int | 注文金額 (円) |
sandbox | bool | テスト用 sandbox API キーで作成された注文か |
createdAt | string | 注文作成日時 (ISO 8601 UTC) |
paidAt | string | null | 弊社で paid ステータスにマークされた日時 (ISO 8601 UTC) |
fulfilledAt | string | null | eSIM 発行完了日時 (ISO 8601 UTC) |
esims | array | 発行された eSIM カードの配列。各要素のフィールドは下表をご参照ください。 |
esims[] 各要素のフィールド
| field | type | 説明 |
|---|---|---|
cardId | string | eSIM カード ID (以降の API 操作に使用) |
iccid | string | null | ICCID (19-20 桁)。発行直後で未割当の場合は null |
eid | string | null | EID (32 桁)。端末に紐付け済みの場合のみ返却 |
cid | string | null | CID (eSIM 識別子、上流連携用) |
cardType | string | local / roaming_32 / roaming_110 |
activationCode | string | null | アクティベーションコード (例: 1$rsp.example.com$ABC-123-XYZ)。SM-DP+ アドレスはこの値の先頭から解析可 |
lpaUri | string | null | LPA 形式の URI (例: LPA:1$rsp.example.com$ABC-123-XYZ)。貴社でこの値から QR コード画像を生成してください |
status | string | eSIM 状態 (pending / active / suspended / refunded 等) |
activatedAt | string | null | エンドユーザが実際に有効化した日時 (ISO 8601 UTC)。未有効化なら null。statusTimeline に有効化 (status=1) があればその権威時刻、無い場合は弊社が有効化を検出した時刻を返します。 |
expiresAt | string | null | 有効期限 (ISO 8601 UTC)。有効化未済なら null。確定値は statusTimeline の失効 (status=2) ノードを参照してください。上流から失効通知を受信するまでは暫定の見積り値を返すことがあり、商品が自然日方式 (validityDayMode=1) の場合は最終的な失効時刻 (validityTimezone の暦日締め) と数時間ずれることがあります。validityDays × 24時間 の固定枠では計算しないでください。 |
totalGb | number | null | 総データ量 (GB)。総量型は容量、毎日 / 無制限は null |
usedGb | number | 現時点の累計使用量 (GB) |
planType | string | 商品種別: total (総量) / daily (毎日) / unlimited (無制限) |
remainingGb | number | null | 残量 (GB) = totalGb − usedGb。総量型のみ。毎日 / 無制限は null |
dailyQuotaGb | number | null | 毎日型のみ: 1日あたりの割当容量 (GB)。他は null |
todayUsedGb | number | null | 毎日型のみ: 当日使用量 (GB、リセット時区基準)。他は null |
todayRemainingGb | number | null | 毎日型のみ: 当日残量 (GB) = dailyQuotaGb − todayUsedGb。他は null |
upstreamStatus | string | null | 上流データプラン状態の生値: 0 未開通 / 1 開通済 / 2 失効。 |
statusTimeline | array | 状態時間線 [{status, at}] (status: 1 有効化 / 2 失効、at: ISO 8601 UTC)。未開通カードは空配列 []。有効化 / 失効の権威時刻はここで取得。 |
installationStatus | string | null | eSIM Profile のインストール状態。upstreamStatus (データプラン状態) とは別軸です。AVAILABLE / DOWNLOADED / INSTALLED / ENABLED / DISABLED / DELETED / ERROR / UNAVAILABLE / UNKNOWN のいずれか。未取得時は null。 |
{
"id": "evt_a3f8x2qp7c5d9e1b4f6a8c2d",
"type": "order.fulfilled",
"occurredAt": "2026-05-24T08:14:01.000Z",
"data": {
"orderId": "cm0xxxxxxxxxxxxxxx",
"externalOrderRef": "YOUR-ORDER-12345",
"sku": "FAM-100GB-365D-2C",
"quantity": 1,
"status": "fulfilled",
"amountJpy": 14900,
"sandbox": false,
"createdAt": "2026-05-24T08:12:33.000Z",
"paidAt": "2026-05-24T08:12:33.000Z",
"fulfilledAt": "2026-05-24T08:14:01.000Z",
"esims": [
{
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"iccid": "8981100012345678901",
"eid": null,
"cid": "1234567890",
"cardType": "local",
"activationCode": "1$rsp.example.com$ABC-123-XYZ-789",
"lpaUri": "LPA:1$rsp.example.com$ABC-123-XYZ-789",
"status": "active",
"activatedAt": "2026-05-24T08:14:01.000Z",
"expiresAt": "2027-05-24T08:14:01.000Z",
"totalGb": 50,
"usedGb": 0
},
{
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AU",
"iccid": "8981100012345678902",
"eid": null,
"cid": "1234567891",
"cardType": "local",
"activationCode": "1$rsp.example.com$DEF-456-UVW-012",
"lpaUri": "LPA:1$rsp.example.com$DEF-456-UVW-012",
"status": "active",
"activatedAt": null,
"expiresAt": "2027-05-24T08:14:01.000Z",
"totalGb": 50,
"usedGb": 0
}
]
}
}order.refunded — 払戻完了
貴社からの払戻申請が承認・実行された時点で配信されます。data には払戻情報に加えて order.fulfilled と同じ注文詳細フィールド (sku / quantity / amountJpy / sandbox / createdAt / paidAt / fulfilledAt / esims 等) も全て含まれ、突き合わせを容易にします。
追加される返金専用フィールド:
| field | type | 説明 |
|---|---|---|
orderId | string | 弊社の注文 ID |
externalOrderRef | string | null | 注文作成時に貴社からご指定いただいた値 |
refundRequestId | string | 払戻申請 ID |
refundAmountJpy | int | 返金金額 (円) |
refundedAt | string | 払戻 (refunded マーク) を実行した日時 (ISO 8601 UTC)。弊社 DB 上のステータス変更時刻であり、貴社側の実返金完了時刻とは異なる場合があります。 |
reason | string | null | 払戻申請時に指定された理由 |
{
"id": "evt_b4f8x2qp7c5d9e1b4f6a8c3e",
"type": "order.refunded",
"occurredAt": "2026-05-25T03:00:00.000Z",
"data": {
"orderId": "cm0xxxxxxxxxxxxxxx",
"externalOrderRef": "YOUR-ORDER-12345",
"sku": "FAM-100GB-365D-2C",
"quantity": 1,
"status": "refunded",
"amountJpy": 14900,
"sandbox": false,
"createdAt": "2026-05-24T08:12:33.000Z",
"paidAt": "2026-05-24T08:12:33.000Z",
"fulfilledAt": "2026-05-24T08:14:01.000Z",
"esims": [
{
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"iccid": "8981100012345678901",
"eid": null,
"cid": "1234567890",
"cardType": "local",
"activationCode": "1$rsp.example.com$ABC-123-XYZ-789",
"lpaUri": "LPA:1$rsp.example.com$ABC-123-XYZ-789",
"status": "refunded",
"activatedAt": "2026-05-24T08:14:01.000Z",
"expiresAt": "2027-05-24T08:14:01.000Z",
"totalGb": 50,
"usedGb": 0
}
],
"refundRequestId": "rrq_a3f8x2qp7c5d9e1b4f6a8c2d",
"refundAmountJpy": 14900,
"refundedAt": "2026-05-25T02:59:55.000Z",
"reason": "customer_request"
}
}esim.usage_alert — 使用量が閾値を超過 (ベータ版)
終端ユーザの eSIM 使用量が事前設定の閾値 (例: 80% / 95%) を超えた時点で配信されます。
⚠️ 本イベントは現在ベータ版です。上流データソースとの接続が安定していないため、データの正確性は保証できません。参考用途に留め、本番の課金や通知ロジックには組み込まないでください。正式版は今後のアップデートで提供予定です。
| field | type | 説明 |
|---|---|---|
cardId | string | eSIM カード ID |
iccid | string | ICCID |
orderId | string | 紐づく注文 ID |
totalGb | number | 総データ量 (GB) |
usedGb | number | 現時点の使用量 (GB) |
remainingGb | number | 残りデータ量 (GB) |
threshold | number | 発火閾値 (0.8 = 80%、0.95 = 95% など) |
{
"id": "evt_01HZX9XY0123456789ABCDEFGH",
"type": "esim.usage_alert",
"occurredAt": "2026-08-15T12:34:56.000Z",
"data": {
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"iccid": "8981100012345678901",
"orderId": "cm0xxxxxxxxxxxxxxx",
"totalGb": 50,
"usedGb": 40.2,
"remainingGb": 9.8,
"threshold": 0.8
}
}esim.status — eSIM 状態変化 (有効化 / 失効)
eSIM の状態が変化した時点で配信されます。弊社が上流から受信した eSIM の有効化 / 失効 (期限切れ・終了) 通知を、貴社の登録 webhook URL へ転送するものです。
本イベントは購読設定が不要で、既定ですべてのチャネルに配信されます (注文系イベントと異なり、個別の購読登録は要りません)。data.status で activated / expired を判定してください。
冪等性: 同一カードに対し同じ状態が複数回届く可能性があります。cardId + status で冪等に処理してください。
| field | type | 説明 |
|---|---|---|
cardId | string | eSIM カード ID (/v1/channel/esim/{cardId} で照会可能) |
activationCode | string | null | アクティベーションコード |
iccid | string | null | ICCID |
status | string | activated (有効化) または expired (失効) |
cardStatus | string | 弊社内部ステータス (active / expired / suspended 等) |
activatedAt | string | null | 有効化日時 (ISO 8601 UTC)。status=activated 時に値が入ります。statusTimeline に有効化 (status=1) があればその権威時刻、無い場合は検出時刻。 |
expiresAt | string | null | 失効日時 (ISO 8601 UTC)。status=expired 時に値が入ります(statusTimeline の失効権威時刻と一致) |
upstreamStatus | string | null | 上流データプラン状態の生値 (0 未開通 / 1 開通済 / 2 失効)。 |
statusTimeline | array | 状態時間線 [{status, at}] (有効化/失効の権威時刻、ISO 8601 UTC)。未開通は []。 |
installationStatus | string | null | eSIM Profile のインストール状態。upstreamStatus (データプラン状態) とは別軸です。AVAILABLE / DOWNLOADED / INSTALLED / ENABLED / DISABLED / DELETED / ERROR / UNAVAILABLE / UNKNOWN のいずれか。未取得時は null。 |
externalOrderRef | string | null | 注文作成時に貴社が指定した値 |
{
"id": "evt_01HZX9XY0123456789ABCDEFGH",
"type": "esim.status",
"occurredAt": "2026-08-15T12:34:56.000Z",
"data": {
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"activationCode": "13A88CEC786444A8F3E8F2E76DF47F28",
"iccid": "8981100012345678901",
"status": "activated",
"cardStatus": "active",
"activatedAt": "2026-08-15T12:34:56.000Z",
"expiresAt": null,
"externalOrderRef": "your-ref-123"
}
}esim.usage — eSIM 使用量の更新
eSIM の使用量 (used) または状態が変化した時点で配信されます。弊社が上流から取得した最新の使用量を、貴社の登録 webhook URL へ転送します。
本イベントは購読設定が不要で、既定ですべてのチャネルに配信されます。変化が無い同期では配信しません。
冪等性: 同一カードに対し複数回届く可能性があります。cardId + usedBytes で冪等に処理してください。usedBytes は精度保持のため文字列で送出します。
| field | type | 説明 |
|---|---|---|
cardId | string | eSIM カード ID (/v1/channel/esim/{cardId} で照会可能) |
activationCode | string | null | アクティベーションコード |
iccid | string | null | ICCID |
cardStatus | string | 弊社内部ステータス (active / expired / suspended 等) |
usedBytes | string | 累計使用量 (バイト)。精度保持のため文字列 |
usedGb | number | 累計使用量 (GB) |
totalGb | number | null | 総容量 (GB)。無制限 / チャージ可能カードは null |
remainingGb | number | null | 残量 (GB) = totalGb − usedGb。総量型のみ。毎日 / 無制限は null |
planType | string | 商品種別: total (総量) / daily (毎日) / unlimited (無制限) |
dailyQuotaGb | number | null | 毎日型のみ: 1日あたりの割当容量 (GB) |
todayUsedGb | number | null | 毎日型のみ: 当日使用量 (GB、リセット時区基準) |
todayRemainingGb | number | null | 毎日型のみ: 当日残量 (GB) = dailyQuotaGb − todayUsedGb |
upstreamStatus | string | null | 上流データプラン状態の生値: 0 未開通 / 1 開通済 / 2 失効。 |
statusTimeline | array | 状態時間線 [{status, at}] (status: 1 有効化 / 2 失効、at: ISO 8601 UTC)。未開通カードは空配列 []。 |
installationStatus | string | null | eSIM Profile のインストール状態。upstreamStatus (データプラン状態) とは別軸です。AVAILABLE / DOWNLOADED / INSTALLED / ENABLED / DISABLED / DELETED / ERROR / UNAVAILABLE / UNKNOWN のいずれか。未取得時は null。 |
lastUsageSyncAt | string | null | 最終同期日時 (ISO 8601 UTC) |
expiresAt | string | null | 有効期限 (ISO 8601 UTC)。確定値は statusTimeline の失効 (status=2) を参照。失効通知の受信前は暫定の見積り値の場合があり、商品が自然日方式 (validityDayMode=1) なら validityTimezone の暦日締めと数時間ずれることがあります。 |
externalOrderRef | string | null | 注文作成時に貴社が指定した値 |
{
"id": "evt_01HZX9XY0123456789ABCDEFGH",
"type": "esim.usage",
"occurredAt": "2026-08-15T12:34:56.000Z",
"data": {
"cardId": "card_01HZX7Z8K9P3B0M4QXYAR6V0AT",
"activationCode": "13A88CEC786444A8F3E8F2E76DF47F28",
"iccid": "8981100012345678901",
"cardStatus": "active",
"usedBytes": "207554117",
"usedGb": 0.193,
"planType": "daily",
"totalGb": null,
"remainingGb": null,
"dailyQuotaGb": 1,
"todayUsedGb": 0.193,
"todayRemainingGb": 0.807,
"lastUsageSyncAt": "2026-08-15T12:34:56.000Z",
"expiresAt": null,
"externalOrderRef": "your-ref-123"
}
}署名検証
import crypto from "node:crypto";
function verifyWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected),
);
}
// Express 例
app.post("/webhook", express.raw({ type: "*/*" }), (req, res) => {
const sig = req.header("X-Channel-Webhook-Signature");
if (!verifyWebhook(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).end();
}
const event = JSON.parse(req.body);
// process event...
res.status(200).end();
});id による重複排除を必ず実装してください。エラー
リクエストが失敗した場合、HTTP ステータスコードと共に以下の形式でレスポンスが返ります。<code>error.code</code> ごとに分岐処理を実装してください。
{
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "この API キーは \"write:orders\" 権限を持っていません"
}
}| HTTP | error.code | 説明 |
|---|---|---|
| 400 | VALIDATION_ERROR | リクエスト body / query が不正 |
| 401 | UNAUTHORIZED | API キー欠落 / 無効 / 取消済 |
| 403 | INSUFFICIENT_SCOPE | scope 不足 |
| 403 | IP_NOT_ALLOWED | IP allowlist 不一致 |
| 403 | PAYG_NOT_REFUNDABLE | PAYG 精算チャネルは個別注文の払戻処理不可 (月次の使用量精算で完結) |
| 403 | FORBIDDEN | 他チャネルのリソースへのアクセス (ownership 不一致) |
| 400 | PRODUCT_NOT_AVAILABLE | 当該商品が貴社チャネルで取扱不可 |
| 400 | PRODUCT_NOT_SELLING | 当該商品が販売停止中 |
| 400 | ALREADY_REFUNDED | 既に払戻済の注文に再度払戻申請 |
| 400 | INVALID_STATE | 払戻不可なステータスの注文 (paid / fulfilled / fulfilling 以外) |
| 500 | REFUND_FAILED | 払戻処理中の内部エラー |
| 404 | NOT_FOUND | リソース不存在 |
| 409 | ALREADY_EXISTS | 同一 channel + 同一 externalOrderRef で注文が既に存在 (message に既存 orderId 含む) |
| 429 | RATE_LIMIT | レート制限超過 (Retry-After 参照) |
| 500 | INTERNAL_ERROR | サーバ内部エラー (運営に連絡) |
更新履歴
| 日付 | 変更 |
|---|---|
| 2026-06-30 | expiresAt / activatedAt の時刻仕様を明確化 (確定値は statusTimeline 権威時刻、自然日商品は validityDayMode=1 で UTC+8 暦日締め) + エラーコード追記 (FORBIDDEN 等) + 各種記述修正 |
| 2026-06-10 | 商品 cardTypes に validityDayMode / validityTimezone / dailyResetTimezone 追加 |
| 2026-05-25 | v1: IP allowlist + チャネル別レート制限 + ドキュメントポータル公開 |
| 2026-05-15 | POST /orders を eSIM 即時発行方式に変更 (決済ページ経由不要) |
| 2026-05-01 | GET /products + scope 権限体系 |
サポート
導入相談・トラブル: support@esimsenmon.com