Tổng Kho eSIM
送信Webhook・8イベント

Webhook

POST /v1/webhooksでURLを登録し、PUT /v1/webhooks/{id}で更新します。登録時はCHECK_HEALTHに2xxを返す必要があります。APIキーとは別の専用シークレットで署名します。

正しい状態の基準はRESTです。イベントを取り逃してもGET /v1/orders?updated_since=…で照合できるよう設計してください。

webhook-events.ja.json

イベント一覧

event_type発生条件主要データ項目
order.completed注文確定、eSIMの準備完了
order_idexternal_refitems[] (order_item_id, iccid)
order.failed注文未完了(開通処理失敗など)
order_idexternal_refreason
esim.deliveredeSIMを発行し、インストール情報を用意した時

`order_id`と`external_ref`で照合します。`lpa`はPOST直前に復号し、配信記録に平文保存しません。QR画像URLは送らないため、`lpa`から生成するか`GET /v1/esims/{id}`で`qr_code_base64`を取得してください。

order_item_idorder_idexternal_reficcidlpa
esim.activatedeSIMのインストール・開通時(smdp enabled/in_use)

`order_id`と注文時の`external_ref`でeSIMを自社注文と照合してください。

order_item_idorder_idexternal_reficcidactivated_at
esim.usage_threshold使用量が75%/90%に到達

`order_id`と`external_ref`で注文と照合します。新たに超えた最高値だけ送信します(0→95%なら90のみ)。`threshold`は少なくともこの値を超えた意味です。

order_item_idorder_idexternal_refthreshold (75/90)used_bytesdata_bytes
esim.expiring期限の3日前/1日前

`order_id`と注文時の`external_ref`でeSIMを自社注文と照合してください。

order_item_idorder_idexternal_refdays_remaining (3/1)expires_at
wallet.low_balanceウォレットが25%/10%の警告基準に到達

`threshold`は百分率(25/10)で、実値がある時だけ含めます。不明なら省略するため`balance`を自分で比較してください。VND金額を`threshold`に入れません。

threshold (25/10)balancecurrency
catalog.updatedカタログ変更:追加、編集、非表示、基本価格変更、在庫切れ

組織ごとに価格が異なるため価格は含みません。`GET /v1/catalog/packages`で取得してください。短時間(既定10分)の変更を1つの`changes[]`にまとめ、同一プランは1件に集約します。数百件の同期でも数百のWebhookは発生しません。テストと本番の両方に適用します。

changes[] (package_code, change: price|availability|package, occurred_at)change_count
json
{
  "event_id": "018f3c00-0000-7000-8000-0000000000c1",
  "event_type": "ping",
  "occurred_at": "2026-07-11T07:29:00Z",
  "is_testmode": true,
  "data": {
    "message": "TongKho eSIM webhook health check"
  }
}

ペイロードと署名ヘッダー

全Webhookは同じ形式です。`HMAC-SHA256(webhook_secret, timestamp\nraw_body)`を小文字hexで`X-TKE-Webhook-Signature`に設定します。24時間のローテーション中は`X-TKE-Webhook-Signature-Old`も付けます。少なくとも1回配信のため、`event_id`で重複排除してください。

json
{
  "event_id": "018f3c00-0000-7000-8000-0000000000b0",
  "event_type": "order.completed",
  "occurred_at": "2026-07-11T07:30:00Z",
  "is_testmode": false,
  "data": {
    "order_id": "018f2b00-0000-7000-8000-00000000009a",
    "external_ref": "partner-cart-9931",
    "items": [
      {
        "order_item_id": "018f2b00-0000-7000-8000-000000000001",
        "iccid": "8984012345678901234"
      }
    ]
  }
}
フィールド説明
data種類別のペイロード(下記参照)。
event_idイベントごとに固定の一意なUUID(重複排除用)。
event_typeイベントの種類。
is_testmodeテストキーによる生成時はtrue。
occurred_atISO-8601 UTC.

カタログ同期: catalog.updated

プランの追加・変更・非表示、原価・在庫の変更時に発生し、変更をまとめた配列 changes[] で送ります。多数の更新でも 1回の 配信にまとめます。

json
{
  "event_id": "018f3c00-0000-7000-8000-0000000000c1",
  "event_type": "catalog.updated",
  "occurred_at": "2026-07-11T08:10:00Z",
  "is_testmode": false,
  "data": {
    "changes": [
      {
        "package_code": "THAY-BANG-MA-GOI-CUA-BAN",
        "change": "price",
        "occurred_at": "2026-07-11T08:02:11Z"
      },
      {
        "package_code": "VN_10GB_30D",
        "change": "availability",
        "occurred_at": "2026-07-11T08:04:52Z"
      },
      {
        "package_code": "JP_3GB_7D",
        "change": "package",
        "occurred_at": "2026-07-11T08:09:30Z"
      }
    ],
    "change_count": 3
  }
}
価格を含めない設計

販売価格は 組織ごとに異なります 。共通価格の配信は不正確で情報漏洩にもなるため、このイベントは 同期のきっかけです :次を呼び出し GET /v1/catalog/packages?market=… 価格を更新してください。

change は3つの値を取ります: price (原価変更)、 availability (在庫あり・なし)、 package (新規・更新・非表示)。未知の値も同期のきっかけとして扱ってください。

署名・再試行・重複排除のキー event_id は通常イベントと同じです。テストと本番は次で分離します: is_testmode.

Webhook署名を検証

X-TKE-Signatureはwebhook_secretと本文の生バイトを使うHMAC-SHA256です。

text
signing_string = timestamp + "\n" + raw_body   # timestamp = header X-TKE-Webhook-Timestamp
signature      = HMAC_SHA256(webhook_secret, signing_string)   → hex lowercase

# リプレイ防止に時刻差±300秒を確認。
# 受信した正確なバイトに署名し、JSONを再シリアライズしない。

再試行ポリシー

1 phút→5 phút→30 phút→2 giờ→6 giờ

2xx以外の応答や5秒のタイムアウト時は24 giờの間、指数的に再試行します:1 phút → 5 phút → 30 phút → 2 giờ → 6 giờ。

Webhookの4つの指針

1. 非同期処理と即時200応答
ペイロードをキューに入れ、1秒以内に200を返します。重い同期処理は避けてください。5秒でタイムアウトします。
2. 冪等性と重複排除
少なくとも1回配信されるため、event_idやdata.order_id / data.order_item_idで重複を排除します。
3. 本番とテストを分離
設定はキーごとに独立しています。テストデータを本番DBに入れないようURLを分けてください。
4. RESTで定期的に照合
長時間の障害でイベントが欠落することがあります。GET /v1/orders?updated_since=…で定期的に照合してください。

各フィールドの注意点

esim.delivered.lpa はPOST直前に復号し平文保存しません。LPAやGET /v1/esims/{id}からQRを取得してください。

esim.usage_threshold: は新たに超えた最大閾値だけ送ります(0→95%ではthreshold=90)。

wallet.low_balance.threshold は割合(25/10)で、VNDの金額ではありません。

catalog.updated は価格や在庫詳細を含まず、プランコードと変更種別だけです。