eSIM Channel API v1
eSIM Channel API · v1

eSIM サードパーティ統合 API

旅行会社・代理店・自社サービスに弊社の eSIM 商品を組み込むための REST API。商品取得・注文作成・払戻・Webhook 通知を 1 つの API キーで完結します。

はじめに

eSIM Channel API は RESTful + JSON 形式の HTTPS API です。全リクエストに X-Channel-Api-Key ヘッダで弊社発行のキーを設定してください。日時は ISO 8601 UTC、金額は JPY (整数円) で表現します。

💡
ベース URL: https://api.esimsenmon.com/v1 (本番環境)

クイックスタート

最初の API リクエストを送るまでの 5 ステップ:

  1. API キー発行依頼: 弊社運営に「API 連携希望」とご連絡ください。打ち合わせ後に専用キーを発行します。
  2. キーの保管: 発行時に ck_live_xxxxxxxxxxxxxxxxxxxxxxxx 形式の平文キーを 1 度だけ返却します。貴社のシークレット管理システムで安全に保管してください。
  3. 商品一覧の取得: 下記 curl の YOUR_KEY を実際のキーに置換して実行すると、貴社チャネルで販売可能な商品が確認できます。
  4. 注文の作成: 商品 sku を送信すると、注文を即時作成して eSIM 発行を開始します (貴社側で決済済の前提)。
  5. Webhook URL の登録: 注文確定・払戻通知を受け取る URL を弊社運営にお知らせください。
最初の API コール
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"])

レスポンス例:

response
{
  "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:esimeSIM カード詳細・残量の参照GET /esim/[cardId]
read:analytics売上・分析データの参照(将来追加予定)
write:refunds払戻の申請POST /orders/[id]/refund
💡
scope の追加: 運用開始後に scope を追加したい場合は弊社運営までご連絡ください。通常は当日中に追加可能で、キーの再発行は不要です。

IP allowlist (送信元 IP 制限)

貴社サーバの送信元 IP を弊社にお知らせいただければ、当該 API キーの接続元を制限します。CIDR (例: 203.0.113.0/24) と単一 IP (例: 203.0.113.1) の両方をサポートし、複数登録も可能です。IP 制限を設けない運用も可能ですので、貴社のセキュリティポリシーに合わせてご選択ください。

⚠️
CloudFront / Cloudflare 等のプロキシを経由したリクエストの場合、弊社は X-Forwarded-For ヘッダの先頭値を送信元 IP として判定します。中間プロキシの IP を allowlist に登録しないようご注意ください。

レート制限

API キーの既定レートは 1 分あたり 100 リクエストです。超過時は HTTP 429 + Retry-After ヘッダを返しますので、貴社側で指数バックオフ + 再試行を実装してください。上限引き上げが必要な場合は弊社運営までご相談ください。

残量は以下のレスポンスヘッダで確認できます:

ヘッダ内容
X-RateLimit-Limit1 分あたりの上限
X-RateLimit-Remaining現在ウィンドウの残量
X-RateLimit-Resetリセット Unix timestamp (秒)
Retry-After(429 時のみ) 秒数

エンドポイント

全エンドポイントは https://api.esimsenmon.com/v1/channel 配下に配置されています。

GET/meアカウント情報取得

リクエストに使用された API キーと、紐づくチャネル (貴社) のメタ情報を返します。接続テストおよびキーの有効性確認に使用してください。必要 scope: なし

GET /me
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 オブジェクトで全言語版も返却するため、貴社側で都度切替も可能です。

Accept-Language header
curl https://api.esimsenmon.com/v1/channel/products \
  -H "X-Channel-Api-Key: $KEY" \
  -H "Accept-Language: en"

レスポンス各 item の主なフィールド:

fieldtype説明
skustring商品 SKU (注文作成時のキー)
namestring商品名 (リクエストの Accept-Language に応じた言語で返却)
contentMdstring商品説明 Markdown (リクエストの Accept-Language に応じた言語で返却)
priceJpyint商品価格 (円)
totalGbLimitint合計 GB
validityDaysint有効日数
cardCountLimitint発行可能 eSIM 枚数
coverageCountriesstring[]対応国コード一覧 (ISO 3166-1 alpha-2、cardTypes から集約・重複排除済)
cardTypesobject[]この商品が発行する eSIM カードの詳細リスト (詳細は下表)
translationsobject全言語版の name / contentMd。キーは ja / en / zh-CN / ko。貴社で言語切替に利用ください。

cardTypes[] の各要素:

fieldtype説明
typestringlocal / roaming_32 / roaming_110
productTypestring | null商品タイプ (上流原始値): "1"=無制限プラン / "2"=総量プラン / "3"=日単位プラン (記載以外の値が返る可能性あり)
usageLocationstring | null使用エリア (例: Japan)
countrystring | null国コード ISO 3166-1 alpha-2 (例: JP)。マルチ国漫遊カードは null
operatorstring | null通信事業者 (例: NTT DOCOMO)
apnstring | nullAPN 名 (例: internet)。設定不要なカードは null
networkTypesstring | null対応ネットワーク (例: 4G/5G)
usageMethodstring | null回線使用方式 (例: ローカル回線 / ローミング回線)
cardCategoryint | nullプラン区分: 1=直営データプラン / 2=再販プラン / 3=キャリア純粋プラン
isRechargeableboolチャージ可能か
validityDayModeint | null有効期間の計算方式: 1=自然日 / 2=24時間制
validityTimezonestring | null有効期間のタイムゾーン (validityDayMode=1 のみ有効。例: UTC+8)
dailyResetTimezonestring | 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

POST /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 フィールド:

fieldtype説明
sku requiredstring商品 SKU (/products から取得)
quantity int数量 (既定 1)
externalOrderRef requiredstring貴社側の注文 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

POST /orders/{id}/refund
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

GET /recharge-options
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

GET /esim/{cardId}/recharge-options
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

POST /esim/{cardId}/recharge
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 のいずれか):

フィールド説明
rechargePlanCodestring漫遊カード用GET /recharge-options で取得した kind="roaming" 項目の rechargePlanCodesku と排他。
capacityGbnumber漫遊カード用。チャージ容量 (GB, > 0)。caller が自由に決定可能。rechargePlanCode と同時指定が必要。
skustringローカルカード用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 に中性化メッセージを含む
recharge.fulfilled — webhook body
{
  "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.statuseSIM の状態が変化した時点 (有効化 / 失効)。<strong>購読不要・既定で配信</strong>
esim.usageeSIM の使用量 (used) または状態が変化した時点。<strong>購読不要・既定で配信</strong>
esim.usage_alert顧客の eSIM 使用量が閾値超過

Payload 仕様

全イベントは共通の封筒 (envelope) 構造で配信されます。<code>type</code> でイベント種別を判定し、<code>data</code> 内に各イベント固有のフィールドが格納されます。

共通フィールド (全イベント)

各イベント payload には以下の共通フィールドが含まれます:

fieldtype説明
idstringイベント一意 ID (例: evt_01HZX...)。冪等な重複排除キーとして使用してください。
typestringイベント種別 (order.fulfilled / order.refunded / esim.status / esim.usage / esim.usage_alert / recharge.fulfilled / recharge.failed)
occurredAtstringイベント発生日時 (ISO 8601 UTC)
dataobjectイベント固有のデータ。詳細は各イベント表を参照。

order.fulfilled — eSIM 発行完了

注文作成後に eSIM の発行が完了した時点で配信されます。data 内のフィールド:

fieldtype説明
orderIdstring弊社の注文 ID
externalOrderRefstring | null注文作成時に貴社からご指定いただいた値 (未指定時は null)
skustring商品 SKU
quantityint数量
statusstringfulfilled
amountJpyint注文金額 (円)
sandboxboolテスト用 sandbox API キーで作成された注文か
createdAtstring注文作成日時 (ISO 8601 UTC)
paidAtstring | null弊社で paid ステータスにマークされた日時 (ISO 8601 UTC)
fulfilledAtstring | nulleSIM 発行完了日時 (ISO 8601 UTC)
esimsarray発行された eSIM カードの配列。各要素のフィールドは下表をご参照ください。

esims[] 各要素のフィールド

fieldtype説明
cardIdstringeSIM カード ID (以降の API 操作に使用)
iccidstring | nullICCID (19-20 桁)。発行直後で未割当の場合は null
eidstring | nullEID (32 桁)。端末に紐付け済みの場合のみ返却
cidstring | nullCID (eSIM 識別子、上流連携用)
cardTypestringlocal / roaming_32 / roaming_110
activationCodestring | nullアクティベーションコード (例: 1$rsp.example.com$ABC-123-XYZ)。SM-DP+ アドレスはこの値の先頭から解析可
lpaUristring | nullLPA 形式の URI (例: LPA:1$rsp.example.com$ABC-123-XYZ)。貴社でこの値から QR コード画像を生成してください
statusstringeSIM 状態 (pending / active / suspended / refunded 等)
activatedAtstring | nullエンドユーザが実際に有効化した日時 (ISO 8601 UTC)。未有効化なら null。statusTimeline に有効化 (status=1) があればその権威時刻、無い場合は弊社が有効化を検出した時刻を返します。
expiresAtstring | null有効期限 (ISO 8601 UTC)。有効化未済なら null。確定値は statusTimeline の失効 (status=2) ノードを参照してください。上流から失効通知を受信するまでは暫定の見積り値を返すことがあり、商品が自然日方式 (validityDayMode=1) の場合は最終的な失効時刻 (validityTimezone の暦日締め) と数時間ずれることがあります。validityDays × 24時間 の固定枠では計算しないでください。
totalGbnumber | null総データ量 (GB)。総量型は容量、毎日 / 無制限は null
usedGbnumber現時点の累計使用量 (GB)
planTypestring商品種別: total (総量) / daily (毎日) / unlimited (無制限)
remainingGbnumber | null残量 (GB) = totalGbusedGb。総量型のみ。毎日 / 無制限は null
dailyQuotaGbnumber | null毎日型のみ: 1日あたりの割当容量 (GB)。他は null
todayUsedGbnumber | null毎日型のみ: 当日使用量 (GB、リセット時区基準)。他は null
todayRemainingGbnumber | null毎日型のみ: 当日残量 (GB) = dailyQuotaGbtodayUsedGb。他は null
upstreamStatusstring | null上流データプラン状態の生値: 0 未開通 / 1 開通済 / 2 失効。
statusTimelinearray状態時間線 [{status, at}] (status: 1 有効化 / 2 失効、at: ISO 8601 UTC)。未開通カードは空配列 []。有効化 / 失効の権威時刻はここで取得。
installationStatusstring | nulleSIM Profile のインストール状態。upstreamStatus (データプラン状態) とは別軸です。AVAILABLE / DOWNLOADED / INSTALLED / ENABLED / DISABLED / DELETED / ERROR / UNAVAILABLE / UNKNOWN のいずれか。未取得時は null
order.fulfilled — webhook body
{
  "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 等) も全て含まれ、突き合わせを容易にします。
追加される返金専用フィールド:

fieldtype説明
orderIdstring弊社の注文 ID
externalOrderRefstring | null注文作成時に貴社からご指定いただいた値
refundRequestIdstring払戻申請 ID
refundAmountJpyint返金金額 (円)
refundedAtstring払戻 (refunded マーク) を実行した日時 (ISO 8601 UTC)。弊社 DB 上のステータス変更時刻であり、貴社側の実返金完了時刻とは異なる場合があります。
reasonstring | null払戻申請時に指定された理由
order.refunded — webhook body
{
  "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%) を超えた時点で配信されます。
⚠️ 本イベントは現在ベータ版です。上流データソースとの接続が安定していないため、データの正確性は保証できません。参考用途に留め、本番の課金や通知ロジックには組み込まないでください。正式版は今後のアップデートで提供予定です。

fieldtype説明
cardIdstringeSIM カード ID
iccidstringICCID
orderIdstring紐づく注文 ID
totalGbnumber総データ量 (GB)
usedGbnumber現時点の使用量 (GB)
remainingGbnumber残りデータ量 (GB)
thresholdnumber発火閾値 (0.8 = 80%、0.95 = 95% など)
esim.usage_alert — webhook body
{
  "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.statusactivated / expired を判定してください。
冪等性: 同一カードに対し同じ状態が複数回届く可能性があります。cardId + status で冪等に処理してください。

fieldtype説明
cardIdstringeSIM カード ID (/v1/channel/esim/{cardId} で照会可能)
activationCodestring | nullアクティベーションコード
iccidstring | nullICCID
statusstringactivated (有効化) または expired (失効)
cardStatusstring弊社内部ステータス (active / expired / suspended 等)
activatedAtstring | null有効化日時 (ISO 8601 UTC)。status=activated 時に値が入ります。statusTimeline に有効化 (status=1) があればその権威時刻、無い場合は検出時刻。
expiresAtstring | null失効日時 (ISO 8601 UTC)。status=expired 時に値が入ります(statusTimeline の失効権威時刻と一致)
upstreamStatusstring | null上流データプラン状態の生値 (0 未開通 / 1 開通済 / 2 失効)。
statusTimelinearray状態時間線 [{status, at}] (有効化/失効の権威時刻、ISO 8601 UTC)。未開通は []
installationStatusstring | nulleSIM Profile のインストール状態。upstreamStatus (データプラン状態) とは別軸です。AVAILABLE / DOWNLOADED / INSTALLED / ENABLED / DISABLED / DELETED / ERROR / UNAVAILABLE / UNKNOWN のいずれか。未取得時は null
externalOrderRefstring | null注文作成時に貴社が指定した値
esim.status — webhook body
{
  "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 は精度保持のため文字列で送出します。

fieldtype説明
cardIdstringeSIM カード ID (/v1/channel/esim/{cardId} で照会可能)
activationCodestring | nullアクティベーションコード
iccidstring | nullICCID
cardStatusstring弊社内部ステータス (active / expired / suspended 等)
usedBytesstring累計使用量 (バイト)。精度保持のため文字列
usedGbnumber累計使用量 (GB)
totalGbnumber | null総容量 (GB)。無制限 / チャージ可能カードは null
remainingGbnumber | null残量 (GB) = totalGbusedGb。総量型のみ。毎日 / 無制限は null
planTypestring商品種別: total (総量) / daily (毎日) / unlimited (無制限)
dailyQuotaGbnumber | null毎日型のみ: 1日あたりの割当容量 (GB)
todayUsedGbnumber | null毎日型のみ: 当日使用量 (GB、リセット時区基準)
todayRemainingGbnumber | null毎日型のみ: 当日残量 (GB) = dailyQuotaGbtodayUsedGb
upstreamStatusstring | null上流データプラン状態の生値: 0 未開通 / 1 開通済 / 2 失効。
statusTimelinearray状態時間線 [{status, at}] (status: 1 有効化 / 2 失効、at: ISO 8601 UTC)。未開通カードは空配列 []
installationStatusstring | nulleSIM Profile のインストール状態。upstreamStatus (データプラン状態) とは別軸です。AVAILABLE / DOWNLOADED / INSTALLED / ENABLED / DISABLED / DELETED / ERROR / UNAVAILABLE / UNKNOWN のいずれか。未取得時は null
lastUsageSyncAtstring | null最終同期日時 (ISO 8601 UTC)
expiresAtstring | null有効期限 (ISO 8601 UTC)。確定値は statusTimeline の失効 (status=2) を参照。失効通知の受信前は暫定の見積り値の場合があり、商品が自然日方式 (validityDayMode=1) なら validityTimezone の暦日締めと数時間ずれることがあります。
externalOrderRefstring | null注文作成時に貴社が指定した値
esim.usage — webhook body
{
  "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"
  }
}

署名検証

Node.js
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();
});
🔁
再送ポリシー: 貴社の受信エンドポイントが 3xx/4xx/5xx を返した場合、または 10 秒以内に応答が無い場合、弊社は指数バックオフで最大 5 回まで再送します。同一イベントが複数回到達する可能性があるため、id による重複排除を必ず実装してください。

エラー

リクエストが失敗した場合、HTTP ステータスコードと共に以下の形式でレスポンスが返ります。<code>error.code</code> ごとに分岐処理を実装してください。

error response
{
  "error": {
    "code": "INSUFFICIENT_SCOPE",
    "message": "この API キーは \"write:orders\" 権限を持っていません"
  }
}
HTTPerror.code説明
400VALIDATION_ERRORリクエスト body / query が不正
401UNAUTHORIZEDAPI キー欠落 / 無効 / 取消済
403INSUFFICIENT_SCOPEscope 不足
403IP_NOT_ALLOWEDIP allowlist 不一致
403PAYG_NOT_REFUNDABLEPAYG 精算チャネルは個別注文の払戻処理不可 (月次の使用量精算で完結)
403FORBIDDEN他チャネルのリソースへのアクセス (ownership 不一致)
400PRODUCT_NOT_AVAILABLE当該商品が貴社チャネルで取扱不可
400PRODUCT_NOT_SELLING当該商品が販売停止中
400ALREADY_REFUNDED既に払戻済の注文に再度払戻申請
400INVALID_STATE払戻不可なステータスの注文 (paid / fulfilled / fulfilling 以外)
500REFUND_FAILED払戻処理中の内部エラー
404NOT_FOUNDリソース不存在
409ALREADY_EXISTS同一 channel + 同一 externalOrderRef で注文が既に存在 (message に既存 orderId 含む)
429RATE_LIMITレート制限超過 (Retry-After 参照)
500INTERNAL_ERRORサーバ内部エラー (運営に連絡)

更新履歴

日付変更
2026-06-30expiresAt / activatedAt の時刻仕様を明確化 (確定値は statusTimeline 権威時刻、自然日商品は validityDayMode=1 で UTC+8 暦日締め) + エラーコード追記 (FORBIDDEN 等) + 各種記述修正
2026-06-10商品 cardTypes に validityDayMode / validityTimezone / dailyResetTimezone 追加
2026-05-25v1: IP allowlist + チャネル別レート制限 + ドキュメントポータル公開
2026-05-15POST /orders を eSIM 即時発行方式に変更 (決済ページ経由不要)
2026-05-01GET /products + scope 権限体系

サポート

導入相談・トラブル: support@esimsenmon.com