Tổng Kho eSIM
OpenAPI 2.4.0・30件の操作

APIリファレンス

バックエンド生成の仕様から/v1のパス、パラメーター、スキーマ、列挙値、エラーを表示します。

本番

https://api.tongkhoesim.com/v1

テストモード

https://api-testing.tongkhoesim.com/v1

本番:api.tongkhoesim.com / tke_live_(パートナー)またはtke_member_live_(許可された会員)。テスト:api-testing.tongkhoesim.com / tke_test_ / tke_member_test_(パートナー/会員)。

共通の規則

次の6個の規則は30件すべての操作に適用されます。

認証

GETを含むすべての操作で4個のヘッダー(X-TKE-Key · X-TKE-Timestamp · X-TKE-Nonce · X-TKE-Signature)によるHMAC-SHA256署名が必要です。

レスポンス形式
成功:{ ok: true, data }。エラー:{ ok: false, error: { code, message, field?, meta?, request_id } }。適切なHTTPステータスを使い、失敗に200は返しません。
データ型
金額は整数のVND(BIGINT)、データ量はカタログを含めバイト(data.total_bytes / data.daily_bytes)です。日時はISO-8601 UTCで、表示時に変換します。
レート制限
429のRetry-AfterとX-RateLimit-Limit / Remaining / Resetを参照してください。制限はキーごとに設定されます。
request_id
すべてのレスポンスのX-Request-Idとエラーのerror.request_idを記録してください。サポートでの調査に必要です。
Idempotency-Key

24時間以内の同じキーと本文は再課金せず元の結果を返します。api_key_id単位で、5件の操作(POST /v1/orders, POST /v1/orders/bulk, POST /v1/esims/{id}/cancel, POST /v1/esims/{id}/change-plan, POST /v1/esims/{id}/refund-requests)に必須です。

2種類のページネーション

形式と終了条件が異なるため、それぞれに対応してください。

オフセット・page / page_size

GET /v1/webhooks/deliveriesのみで使用し、page、page_size、totalを返します。

範囲外でもHTTP 200、items: []と実際のtotalを返します。空の一覧かtotalに達したら終了します。

カーソル・cursor / next_cursor

/v1/catalog/packages、/v1/orders、/v1/esims、/v1/esims/{id}/plan-optionsで使用します。updated_sinceはordersとesimsのみ対応します。

next_cursorがない、または現在のカーソルと同じなら終了します。dataに項目自体がない場合もあります。

無効なカーソルとHTTP 200の注意点

無効なカーソルは既存クライアントとの互換性のため先頭に戻ります。next_cursor !== nullだけでは1ページ目を無限に繰り返します。

javascript
let cursor = null;
const seen = new Set();

while (true) {
  const params = new URLSearchParams({ page_size: "200" });
  if (cursor) params.set("cursor", cursor);

  // callSignedは4個のX-TKE-*ヘッダーを追加する関数です(HMAC参照)。
  const page = await callSigned("GET", `/v1/orders?${params}`);
  for (const order of page.data.items) await handle(order);

  const next = page.data.next_cursor;
  if (!next || next === cursor || seen.has(next)) break;
  seen.add(next);
  cursor = next;
}

カタログ

2つの供給システムを共通化したプランカタログです。システムは別パスではなく、`market`フィールド(`domestic` | `international`)と`?market=`フィルターで区別します。 数量や`available`/`low`/`out_of_stock`などの在庫概念はありません。プランを表示し、供給できない注文は`POST /v1/orders`で`esim.out_of_stock`などを明確に返します。カタログでの事前告知はありません。 共通のカーソル方式です。`total`は集計が軽い場合(国内システムへの絞り込み)のみで、それ以外は`null`です。

GET/v1/catalog/packages

プラン一覧を取得

scope catalog:readget_catalog_packages

必要な権限スコープ: catalog:read.

組織向けプランカタログです。2つの供給システムを共通化し、?market=で絞り込みます。

実際に購入できるプランのみを返します。公開済み、供給元が販売中、キーの制限内、組織向け価格設定済みのすべてが必要です。価格未設定のプランは注文できないため表示しません。

カーソル方式:初回はcursorなしで呼び、以後next_cursorをそのまま渡し、nullまで繰り返します。page_size未満でも終端ではありません。

capabilitiesは実際の宣言のみを反映し、推測しません。未宣言は全フラグfalseです。確実に422となる機能を約束するより、利用可能なボタンの一部を省く方を選びます。

カタログには数量や在庫あり・なしなどの在庫概念がありません。供給元が対応できない注文は、POST /v1/ordersでesim.out_of_stockなどの明確なエラーを返すため、事前のフィールドから推測する必要はありません。

クエリパラメーター (18)

page_sizeinteger任意既定値 50min 1max 100

1ページの件数です。既定50、上限100。上限を超えてもエラーにせず100に制限します。

marketstring任意

供給システムはdomestic | internationalです。一覧にない値は全カタログではなくinternal.invalid_filter(400)を返し、誤記が無制限の絞り込みと誤認されないようにします。

countrystring任意

ISO-3166 alpha-2の国コード(例:VN)。この国を対象とするプランのみ。

regionstring任意

地域スラッグ(例:chau-a)。その地域の国を1つ以上含むプランと、すべてのグローバルプランが対象です。

qstring任意

公開コードとプラン名を自由検索します(部分一致、大文字小文字を区別しません)。

tagstring任意

1つの商品タグで絞り込みます。保存時と同様に余分な空白を除き、小文字とハイフンで正規化するため、Ban Leとban-leは同じタグです。

data_modelstring任意

データ形式:daily | fixed | unlimited。旧supports_topupを置き換えます。不明な値はinternal.invalid_filter(400)。

data_min_bytesinteger · int64任意

最低データ容量(バイト)です。日次プランは1日分の容量で比較し、無制限プランは下限条件を常に満たします。

data_max_bytesinteger · int64任意

最大データ容量(バイト)です。無制限プランは除外されます。無制限に上限は適用できず、含めると最小容量を探す利用者に無制限プランが表示されてしまうためです。

days_mininteger · int64任意

最低有効日数です。

days_maxinteger · int64任意

最大有効日数です。

price_mininteger · int64任意

組織向け価格と比較する最低価格(VND)です。サーバーでページ分割した後に適用されるため、件数が少なくても終端とは限りません。

price_maxinteger · int64任意

最高価格(VND)です。price_minと同じ規則に従います。

network_genstring任意

指定した通信世代(2g | 3g | 4g | 5g)の対応プランのみ。不明な値はinternal.invalid_filter(400)です。

hotspotstring任意
許可される値:truefalse

trueはWi-Fi共有対応の宣言あり、falseは非対応の宣言あり。未宣言(features.hotspot = null)はどちらにも一致しません。文字列true/falseのみ許可します。

appstring任意

少なくとも1つのOSでこのアプリに対応すると宣言したプランのみを取得します(app=tiktok)。未宣言は一致せず、情報がないことは保証ではありません。現在tiktokのみ有効で、ほかのコードはinternal.invalid_filter(400)です。

voicestring任意
許可される値:truefalse

trueは音声対応の宣言あり、falseは非対応の宣言あり。未宣言はどちらにも一致しません。文字列true/falseのみ許可します。

cursorstring任意

next_cursorをそのまま返してください。短いページでも終了せず、nullでのみ終了します。 キー制限、組織価格、価格条件はページ分割後に適用されます。カーソルには条件の指紋が含まれ、条件変更や破損時はcatalog.cursor_mismatch(400)となり、異なる検索結果の混在を防ぎます。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
itemsobject[]
—
capabilitiesobject

供給元の種類から推測せず、プランが実際に宣言した購入後の機能です。宣言がない場合は全項目falseとし、必ず422 capability.not_supportedになる操作を約束しません。

cancelobject
—
restrictionstring
null可

code_not_disclosedは誰もコードを見ていない場合のみ取消可能という意味です(顧客送信、画面表示、?include=lpaも含む)。実際の取消条件であり、システムが把握できないインストール有無を示しません。旧unused_onlyは不正確な表現でした。

code_not_disclosednull
supportedboolean
—
plan_changeobject
—
policyobject
null可

この供給元で新しいプランを追加チャージする際の動作です。nullはチャージ不可、または供給元の方針を未確認であることを示します。推測してはいけません。すべてfalseのオブジェクトは何もキャンセルしない保証となり、nullとは意味が異なります。

……

さらに深い項目はJSONの例を参照してください。

supportedboolean
—
usage_checkobject
—
supportedboolean
—
codestring

組織向けカタログのプランコード、すなわちpublic_skuです。供給元を切り替えてもプランごとに不変なので、照合キーに使えます。例は形式のみ正しく実際には使えません。GET /v1/catalog/packagesから実コードを取得してください。

coverageobject

プランの利用可能地域。

countriesstring[]

ISO-3166 alpha-2コードです。グローバルプラン(200か国を列挙しません)および対象国の宣言がないプランでは空になります。

country_countinteger

全件取得して配列を数えることなく、複数国対応プランを並べ替え・絞り込みできる対象国数です。

groupstring

対象範囲:国(country)、地域(region)、世界(global)。オープン列挙型のため不明な値は無視してください。

regionstring
null可

常にnullです。地域はプランではなく国に関連付けられます。?region=での絞り込みは利用できます。

dataobject

プランのデータ容量です。二重丸めを避けるため、すべてMB・GBではなくバイト単位です。

daily_bytesinteger · int64
null可

1日あたりのデータ容量(バイト)です。fixed・unlimitedプランではnullです。

labelstring

全画面と同じ関数で生成される、人が読める表示名です。

modelstring

容量計測方式:daily(1日単位)、fixed(全期間の総量)、unlimited。拡張可能な列挙型のため、クライアントは不明な値を無視してください。

dailyfixedunlimited
resetobject
null可

日次容量のリセット時点。夜遅く購入した場合の初日分に影響する販売情報です。nullは未宣言。

atstring
null可

timezoneの現地時刻でのリセット時刻です(00:00、00:00:01)。

notestring
null可
—
timezonestring
null可

リセット時刻のタイムゾーン(UTC+8、UTC+7)。

total_bytesinteger · int64
null可

全期間の総容量(バイト)。daily/unlimitedではnullです。日次容量と日数を掛けても供給元が保証する総量にはなりません。

descriptionstring
null可

プランの販売用説明。未作成の場合はnull。

description_enstring
null可

英語の説明。未提供の場合はnull。

featuresobject

機能をコード配列ではなく型付きオブジェクトで表します。[]ではテザリング非対応と不明を区別できませんが、falseとnullなら区別できます。

appsobject[]

OS別のアプリ対応状況です。

配列に存在しないアプリは情報不明であり、対応を意味しません。 一覧にあるものだけが供給元の宣言で、現在はTikTokのみです。

統合フィールドを設けないのは意図的です。実際のカタログでは2,465プランがiPhoneでTikTokに対応しますが、Androidでは非対応です。単一のフラグで「非対応」にまとめると、カタログの約3分の1を誤って扱うことになります。

androidstring

supported(対応宣言)、blocked(非対応宣言)、unknown(このOSの宣言なし)。オープン列挙型。

supportedblockedunknown
appstring

小文字のアプリコード(例:tiktok)。

iosstring

supported(対応宣言)、blocked(非対応宣言)、unknown(このOSの宣言なし)。オープン列挙型。

supportedblockedunknown
notestring
null可
—
hotspotboolean
null可

他の機器へのWi-Fi共有。nullは未宣言で、falseとは異なります。

kyc_requiredboolean
null可

利用前に本人確認(KYC)が必要です。nullは未宣言です。

smsboolean
null可

SMS。falseはSMSを受信できず、銀行のワンタイムパスワードも受信できません。nullは未宣言です。

voiceboolean
null可

音声通話。falseは供給元が音声非対応を宣言しており、データ専用回線は着信できません。nullは未宣言。

fupobject
null可

高速容量を使い切った後の動作。nullは速度制限の方針が未宣言です。

behaviorstring
null可

throttle(減速)、cutoff(切断)、null(未宣言)。オープン列挙型。

throttlecutoffnull
high_speed_bytesinteger · int64
null可

速度制限が始まるまでの高速通信量(バイト)。

notestring
null可
—
speed_kbpsinteger
null可

高速容量消費後の速度(kbps)です。回線停止または未宣言ならnullです。プラン全体の速度上限network.speed_cap_kbpsとは異なります。

marketstring

プランの供給システムです。拡張可能な列挙型のため不明値は無視してください。在庫の有無と販売後操作を決定します。domesticはキットを販売し、追加・取消・使用量照会に対応します。internationalは要求時に供給元へ注文するため在庫がありません。

domesticinternational
namestring
—
name_enstring
null可

英語名。未提供の場合はnull。

networkobject

プランが利用する通信網。

apnstring
null可

自動設定できない一部のAndroid端末で手動入力するAPNです。インストール手順に必要で、情報がなければ個別のサポート対応が必要になります。nullは未宣言です。

carriersobject[]

このプランが使用する通信事業者です。供給元ではなく、利用する無線ネットワークというeSIMの仕様です。

namestring
—
generationsstring[]
null可

利用可能な通信世代(["4g", "5g"])です。nullは未宣言であり、2G専用という意味ではありません。

speed_cap_kbpsinteger
null可

プラン全体の速度上限(kbps)です。高速容量消費後に適用するfup.speed_kbpsとは異なります。

priceobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
tagsstring[]

小文字・ハイフンで正規化した商品タグです。キーのカタログ制限にも使用します。現在タグ付きプランはなく、販売者が付与するまで?tag=は空一覧を返します。

validityobject

プランの有効期間と計測開始時点です。

daysinteger
—
install_by_daysinteger
null可

購入後にQRコードを読み取り、eSIMをインストールできる日数です。nullは未宣言であり、いつでもインストール可能という意味ではありません。

labelstring
—
reclaim_on_expiryboolean
null可

期限切れ時に供給元が契約を回収するため、追加チャージや変更ができなくなります。更新を販売する場合に重要です。nullは未宣言。

starts_whenstring
null可

計測開始:on_install(インストール時)、on_purchase(購入時)、またはnull。有効期限の算出に重要です。nullなら具体的な期限を約束しないでください。

on_installon_purchasenull
unused_valid_daysinteger
null可

未使用で保管できる期限までの日数です。nullは未宣言であり、無期限ではありません。保管期限とインストール期限は異なるため、install_by_daysとは別です。

modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
next_cursorstring
null可

次のページを取得する際は値をそのまま返してください。終了の唯一の合図はnullです。page_sizeより少ない件数でも続きがある場合があります。

page_sizeinteger
null可

サーバーがページに使用した、上限適用後の最大件数です。itemsの実際の要素数ではありません。

totalinteger · int64
null可

条件に一致する総プラン数。国際向けやmarket未指定など集計が高コストな場合はnull。キー制限と組織価格の判定前に集計するため、購入可能数ではなくカタログの一致数です。

warningsobject[]

一覧の理由。特記事項がなければ空です。固定コード:filtered_by_key_package_filters、filtered_by_provider_scope、no_price_for_org、price_filter_removed_rows、provider_disabled、capability_missing。それぞれキー制限、組織の供給元範囲、価格未設定、価格条件、供給元無効、機能未宣言を示します。countは対象行数、数値化できない場合はnullです。

codestring
—
filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing
countinteger · int64
null可
—
messagestring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failedinternal.invalid_filtercatalog.cursor_mismatch
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="GET"
REQ_PATH="/v1/catalog/packages"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "items": [
      {
        "capabilities": {
          "cancel": {
            "restriction": "code_not_disclosed",
            "supported": true
          },
          "plan_change": {
            "policy": {
              "note": "<note>",
              "requires_cancel_first": true,
              "stacking": true
            },
            "supported": true
          },
          "usage_check": {
            "supported": true
          }
        },
        "code": "TKE-VN-30D-X3K9F",
        "coverage": {
          "countries": [
            "CN"
          ],
          "country_count": 1,
          "group": "country",
          "region": "<region>"
        },
        "data": {
          "daily_bytes": 1073741824,
          "label": "1GB/ngày",
          "model": "daily",
          "reset": {
            "at": "00:00",
            "note": "<note>",
            "timezone": "UTC+8"
          },
          "total_bytes": null
        },
        "description": "<description>",
        "description_en": "<description_en>",
        "features": {
          "apps": [
            {
              "android": "blocked",
              "app": "tiktok",
              "ios": "supported",
              "note": "<note>"
            }
          ],
          "hotspot": true,
          "kyc_required": false,
          "sms": false,
          "voice": false
        },
        "fup": {
          "behavior": "throttle",
          "high_speed_bytes": 1048576,
          "note": "<note>",
          "speed_kbps": 128
        },
        "market": "international",
        "name": "eSIM Trung Quốc Mainland Multi - 1GB/ngày - 24 ngày",
        "name_en": "<name_en>",
        "network": {
          "apn": "e-ideas",
          "carriers": [
            {
              "name": "China Unicom"
            }
          ],
          "generations": [
            "4g",
            "5g"
          ],
          "speed_cap_kbps": 1
        },
        "price": {
          "amount": 273000,
          "currency": "VND"
        },
        "tags": [],
        "validity": {
          "days": 24,
          "install_by_days": 365,
          "label": "24 ngày",
          "reclaim_on_expiry": true,
          "starts_when": "on_install",
          "unused_valid_days": 1
        }
      }
    ],
    "mode": "live",
    "next_cursor": "eyJ1cGRhdGVkX2F0IjoiMjAyNi0wNy0xMVQwODoxMjozMFoifQ",
    "page_size": 50,
    "total": 128,
    "warnings": []
  },
  "ok": true
}
GET/v1/catalog/packages/{code}

プランを1件取得

scope catalog:readget_catalog_packages__code_

必要な権限スコープ: catalog:read.

公開コードで1つのプラン詳細を取得します。dataはGET /v1/catalog/packagesの項目と同じフィールドにmodeを加えたものです。詳細専用フィールドはなく、Package型は1つで対応できます。

参照できないコードは、コード不存在、キー制限外、組織価格なし、供給元との紐付け消失のすべてでpartner.package_not_visible(404)です。理由を区別すると、第三者による全カタログの列挙を許すためです。

パスパラメーター (1)

codestring必須

カタログのcode(public_sku)に当たるプランコードです。供給元を切り替えても不変で、照合キーとして保存できます。キー制限外や組織価格未設定のコードも、不存在と同じ404 partner.package_not_visibleです。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
partner.package_not_visible
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
CODE="THAY-BANG-CODE"

METHOD="GET"
REQ_PATH="/v1/catalog/packages/$CODE"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": null,
  "ok": true
}

注文

注文と照合

GET/v1/orders

注文一覧を取得(取得型照合)

scope orders:readget_orders

必要な権限スコープ: orders:read.

クエリパラメーター (5)

page_sizeinteger任意既定値 50min 1max 200

1ページの件数です。既定50、上限200。上限を超えてもエラーにせず200に制限します。

statusstring任意
許可される値:completedpending_providerprovider_failedcancelled

注文状態で絞り込みます。一覧にない値はinternal.invalid_filter(400)を返します。

external_refstring任意

注文確定時に送信した参照コードで絞り込みます(完全一致)。

updated_sincestring · date-time任意

ISO-8601 UTC形式です。updated_at >= updated_sinceの全レコードを昇順で返す、標準の取得型照合(§8.5)です。Webhookを取り逃しても状態から復元できます。形式不正はinternal.invalid_filter(400)です。

cursorstring任意

次ページにはnext_cursorをそのまま渡します。不正なカーソルはエラーにならず先頭から読み直します。これは形式変更時の互換性維持のためです。先頭ページで無限ループしないよう、返されたカーソルが送信値と異なることを確認してください。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
itemsobject[]
—
created_atstring · date-time
—
external_refstring
null可
—
fulfillment_statusstring
—
fulfilledpartially_fulfilledunfulfilled
idstring · uuid
—
item_countinteger · int64
—
netobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
public_refstring
null可
—
refundedobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
statusstring
—
totalobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
updated_atstring · date-time
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
next_cursorstring
null可

次のページを取得する際は値をそのまま返してください。終了の唯一の合図はnullです。page_sizeより少ない件数でも続きがある場合があります。

page_sizeinteger
null可

サーバーがページに使用した、上限適用後の最大件数です。itemsの実際の要素数ではありません。

totalinteger · int64
null可

条件に一致する件数です。集計コストが高い場合はnullになります。終端の判定には使用せず、next_cursorを確認してください。

warningsobject[]

一覧の理由。特記事項がなければ空です。固定コード:filtered_by_key_package_filters、filtered_by_provider_scope、no_price_for_org、price_filter_removed_rows、provider_disabled、capability_missing。それぞれキー制限、組織の供給元範囲、価格未設定、価格条件、供給元無効、機能未宣言を示します。countは対象行数、数値化できない場合はnullです。

codestring
—
filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing
countinteger · int64
null可
—
messagestring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failedinternal.invalid_filter
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="GET"
REQ_PATH="/v1/orders"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "items": [
      {
        "created_at": "2026-07-11T08:12:30Z",
        "external_ref": "po-1001",
        "fulfillment_status": "fulfilled",
        "id": "018f2b00-0000-7000-8000-00000000009a",
        "item_count": 2,
        "net": {
          "amount": 273000,
          "currency": "VND"
        },
        "public_ref": "TKE-DH-2A4C7Q",
        "refunded": {
          "amount": 273000,
          "currency": "VND"
        },
        "status": "completed",
        "total": {
          "amount": 273000,
          "currency": "VND"
        },
        "updated_at": "2026-07-11T09:03:11Z"
      }
    ],
    "mode": "live",
    "next_cursor": "eyJ1cGRhdGVkX2F0IjoiMjAyNi0wNy0xMVQwODoxMjozMFoifQ",
    "page_size": 50,
    "total": 128,
    "warnings": []
  },
  "ok": true
}
POST/v1/orders

注文を作成する(直接購入)

scope orders:writeIdempotency-Key必須post_orders

必要な権限スコープ: orders:write.

ヘッダー (1)

Idempotency-Keystring必須

クライアントが生成する文字列。同じキーと本文は1回だけ実行され、再試行は元の結果を返します。api_key_id単位(§11)なので、異なるキーは別の命令です。

リクエスト本文必須application/json

フィールド型制約説明
external_refstring
null可

応答とWebhookにそのまま返す任意の参照コード。

includestring[]
null可

追加ブロック:["lpa"]または["lpa","qr"]。省略するとitems[].installはnullで、すべてのeSIMの取消権を維持します。コードの返却は開示です。lpaを指定すると注文時点で取消可能期間が終了します。

invoice_buyerobject
null可

メンバーキー専用です。未指定なら組織やベトナム法人を必要としない消費者フローを使用します。指定時はfull_name、12桁の個人tax_code、購入時のaddress/email規則で検証します。企業向け請求書は購入後に申請します。テストモードではスナップショットの検証のみ行い、MISA請求書は発行しません。

addressstring
null可
—
emailstring
null可
—
full_namestring
null可
—
legal_namestring
null可
—
tax_codestring
null可
—
itemsobject[]
必須

購入するプランと数量の一覧です(eSIMは最大50件)。

package_codestring
必須

組織向けカタログのプランコード、すなわちpublic_skuです。供給元を切り替えてもプランごとに不変なので、照合キーに使えます。例は形式のみ正しく実際には使えません。GET /v1/catalog/packagesから実コードを取得してください。

quantityinteger
必須

このプランで購入するeSIMの数量(≥ 1)。

レスポンス

200確定済み注文の再送結果

24時間以内に同じIdempotency-Keyと本文で再実行すると、同一の本文を返し、再課金せず、Idempotent-Replayed: trueを付けます。新規確定は201です。成功をこのステータスだけで判定しないでください。

フィールド型制約説明
dataobject
必須

パートナー注文。

created_atstring · date-time
—
external_refstring
null可
—
fulfillment_statusstring

実際の納品状況で、statusとは別の軸です。3件中2件が納品、1件が失敗した場合もstatus=completedですが、fulfillment_status=partially_fulfilled、refunded_amount > 0になります。

fulfilledpartially_fulfilledunfulfilled
idstring · uuid

注文ID(UUID)。

idempotent_replayboolean
null可

過去の成功を冪等に再実行した場合に真となります。

invoice_nostring
null可

発行後の請求書番号です。

invoice_statusstring

注文のVAT請求書状態です。noneは未発行です。

nonependingissuingissuedfailedcancelled
itemsobject[]
—
cancellableobject

eSIMの取消可否と不可の理由。POST /v1/esims/{order_item_id}/cancelの前に確認してください。回答のため常に存在し、nullにはなりません。

allowedboolean
—
disclosed_atstring · date-time
null可

コードがシステム外に出た時刻(ISO-8601 UTC)。誰も見ていない間はnullです。未受領を理由に取消不可を争う場合の確認記録です。

reasonstring
null可

取消不可の理由:code_disclosed(送信・表示済み)、wrong_status(状態不適合)、expired(期限切れ)、not_supported(取消機能未宣言)。allowed = trueならnull。esim.not_cancellableのmeta.reasonと同じ用語です。

code_disclosedwrong_statusexpirednot_supportednull
external_refstring
null可

注文時に送信したexternal_refで、eSIMと注文を照合します。未指定で注文した場合はnull。

iccidstring
null可
—
idstring · uuid

全/v1/esims/{id}/…パスで使うeSIM IDで、Webhookのorder_item_idでもあります。ICCIDのみ分かる場合はGET /v1/esims?iccid=…でidを取得します。

installobject
null可

このeSIMのインストールに必要なすべての情報です。nullは未要求(include=lpaなし)を意味します。まだコードがない場合とは異なり、その場合はブロックが存在してlpa: nullになります。

このブロックを含む応答には常にCache-Control: no-storeが付きます。

android_urlstring
null可
—
apnstring
null可

自動設定できないときに入力するアクセスポイント名(APN)です。現バージョンでは常にnullで、不明を意味し、不要という意味ではありません。

ios_urlstring
null可
—
lpastring
null可

eSIMのアクティベーションコードで、販売可能な秘密情報です。この文字列だけでQRコードを生成できます。

matching_idstring
null可
—
qr_code_base64string
null可

QRコードのPNGデータURIです。詳細エンドポイントでinclude=qrを指定した場合のみ存在し、一覧には含みません(1行約11KB、100行で約1.1MB)。lpaからQRコードを生成してください。

smdp_addressstring
null可
—
msisdnstring
null可
—
order_idstring · uuid
—
package_codestring
null可

カタログのプランコードで、eSIMをカタログに紐付けるキーです。元プランがカタログから削除された場合のみnullです。

package_namestring

表示用の名称で、変更される場合があります。照合キーには使用しないでください。

planobject
null可

このeSIMに現在適用されているプラン。

current_codestring
—
expires_atstring · date-time
null可
—
started_atstring · date-time
null可
—
smdp_statusstring
null可
—
statusstring
—
updated_atstring · date-time
—
usageobject
null可

eSIMのデータ利用統計。未取得の場合はupdated_at = null。

expires_atstring · date-time
null可
—
remaining_bytesinteger · int64
null可
—
sourcestring
null可
—
pollwebhook
total_bytesinteger · int64
null可
—
updated_atstring · date-time
null可
—
used_bytesinteger · int64
null可
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
money_settledboolean

注文金額が精算済みか(返金処理中でないか)。falseの場合は請求書を発行できません。

netobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
public_refstring
null可

サポートへの問い合わせに使用する短い注文コードです。

refundedobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
statusstring
—
completedpending_providerprovider_failedcancelled
totalobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
okboolean
必須
—
true
201成功

成功

フィールド型制約説明
dataobject
必須

パートナー注文。

created_atstring · date-time
—
external_refstring
null可
—
fulfillment_statusstring

実際の納品状況で、statusとは別の軸です。3件中2件が納品、1件が失敗した場合もstatus=completedですが、fulfillment_status=partially_fulfilled、refunded_amount > 0になります。

fulfilledpartially_fulfilledunfulfilled
idstring · uuid

注文ID(UUID)。

idempotent_replayboolean
null可

過去の成功を冪等に再実行した場合に真となります。

invoice_nostring
null可

発行後の請求書番号です。

invoice_statusstring

注文のVAT請求書状態です。noneは未発行です。

nonependingissuingissuedfailedcancelled
itemsobject[]
—
cancellableobject

eSIMの取消可否と不可の理由。POST /v1/esims/{order_item_id}/cancelの前に確認してください。回答のため常に存在し、nullにはなりません。

allowedboolean
—
disclosed_atstring · date-time
null可

コードがシステム外に出た時刻(ISO-8601 UTC)。誰も見ていない間はnullです。未受領を理由に取消不可を争う場合の確認記録です。

reasonstring
null可

取消不可の理由:code_disclosed(送信・表示済み)、wrong_status(状態不適合)、expired(期限切れ)、not_supported(取消機能未宣言)。allowed = trueならnull。esim.not_cancellableのmeta.reasonと同じ用語です。

code_disclosedwrong_statusexpirednot_supportednull
external_refstring
null可

注文時に送信したexternal_refで、eSIMと注文を照合します。未指定で注文した場合はnull。

iccidstring
null可
—
idstring · uuid

全/v1/esims/{id}/…パスで使うeSIM IDで、Webhookのorder_item_idでもあります。ICCIDのみ分かる場合はGET /v1/esims?iccid=…でidを取得します。

installobject
null可

このeSIMのインストールに必要なすべての情報です。nullは未要求(include=lpaなし)を意味します。まだコードがない場合とは異なり、その場合はブロックが存在してlpa: nullになります。

このブロックを含む応答には常にCache-Control: no-storeが付きます。

android_urlstring
null可
—
apnstring
null可

自動設定できないときに入力するアクセスポイント名(APN)です。現バージョンでは常にnullで、不明を意味し、不要という意味ではありません。

ios_urlstring
null可
—
lpastring
null可

eSIMのアクティベーションコードで、販売可能な秘密情報です。この文字列だけでQRコードを生成できます。

matching_idstring
null可
—
qr_code_base64string
null可

QRコードのPNGデータURIです。詳細エンドポイントでinclude=qrを指定した場合のみ存在し、一覧には含みません(1行約11KB、100行で約1.1MB)。lpaからQRコードを生成してください。

smdp_addressstring
null可
—
msisdnstring
null可
—
order_idstring · uuid
—
package_codestring
null可

カタログのプランコードで、eSIMをカタログに紐付けるキーです。元プランがカタログから削除された場合のみnullです。

package_namestring

表示用の名称で、変更される場合があります。照合キーには使用しないでください。

planobject
null可

このeSIMに現在適用されているプラン。

current_codestring
—
expires_atstring · date-time
null可
—
started_atstring · date-time
null可
—
smdp_statusstring
null可
—
statusstring
—
updated_atstring · date-time
—
usageobject
null可

eSIMのデータ利用統計。未取得の場合はupdated_at = null。

expires_atstring · date-time
null可
—
remaining_bytesinteger · int64
null可
—
sourcestring
null可
—
pollwebhook
total_bytesinteger · int64
null可
—
updated_atstring · date-time
null可
—
used_bytesinteger · int64
null可
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
money_settledboolean

注文金額が精算済みか(返金処理中でないか)。falseの場合は請求書を発行できません。

netobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
public_refstring
null可

サポートへの問い合わせに使用する短い注文コードです。

refundedobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
statusstring
—
completedpending_providerprovider_failedcancelled
totalobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failedinternal.invalid_filter
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
402
wallet.insufficient_balance
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
partner.package_not_visible
409
esim.out_of_stockidempotency.conflict
422
invoice.buyer_invalid
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="POST"
REQ_PATH="/v1/orders"   # them query thi noi thang vao day TRUOC khi ky
BODY='{"external_ref":"po-1001","include":["lpa"],"invoice_buyer":{"address":"<address>","email":"<email>","full_name":"<full_name>","legal_name":"<legal_name>","tax_code":"TKE-VN-30D-X3K9F"},"items":[{"package_code":"TKE-VN-30D-X3K9F","quantity":2}]}'

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  --data-raw "$BODY"

レスポンス例

json
{
  "data": {
    "created_at": "2026-07-11T08:12:30Z",
    "external_ref": "po-1001",
    "fulfillment_status": "fulfilled",
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "idempotent_replay": true,
    "invoice_no": "<invoice_no>",
    "invoice_status": "none",
    "items": [
      {
        "cancellable": {
          "allowed": true,
          "disclosed_at": "2026-07-11T08:12:30Z",
          "reason": "code_disclosed"
        },
        "external_ref": "po-1001",
        "iccid": "8984012345678901234",
        "id": "018f2b00-0000-7000-8000-00000000009a",
        "install": {
          "android_url": "https://esimsetup.google.com/esim_qrcode_provisioning?data=LPA%3A1%24smdp.example.com%24MATCH-ABC123",
          "apn": "<apn>",
          "ios_url": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA%3A1%24smdp.example.com%24MATCH-ABC123",
          "lpa": "LPA:1$smdp.example.com$MATCH-ABC123",
          "matching_id": "MATCH-ABC123",
          "qr_code_base64": "<PNG base64 — đã rút gọn>",
          "smdp_address": "smdp.example.com"
        },
        "msisdn": "+84900000000",
        "order_id": "018f2b00-0000-7000-8000-00000000009a",
        "package_code": "TKE-VN-30D-X3K9F",
        "package_name": "Tên gói hiển thị",
        "plan": {
          "current_code": "TKE-VN-30D-X3K9F",
          "expires_at": "2026-08-10T00:00:00Z",
          "started_at": "2026-07-11T08:12:30Z"
        },
        "smdp_status": "released",
        "status": "delivered",
        "updated_at": "2026-07-11T09:03:11Z",
        "usage": {
          "expires_at": "2026-08-10T00:00:00Z",
          "remaining_bytes": 5368709120,
          "source": "poll",
          "total_bytes": 5368709120,
          "updated_at": "2026-07-11T09:03:11Z",
          "used_bytes": 5368709120
        }
      }
    ],
    "mode": "live",
    "money_settled": true,
    "net": {
      "amount": 273000,
      "currency": "VND"
    },
    "public_ref": "TKE-DH-2A4C7Q",
    "refunded": {
      "amount": 273000,
      "currency": "VND"
    },
    "status": "completed",
    "total": {
      "amount": 273000,
      "currency": "VND"
    }
  },
  "ok": true
}

リクエスト本文の例

json
{
  "external_ref": "po-1001",
  "include": [
    "lpa"
  ],
  "invoice_buyer": {
    "address": "<address>",
    "email": "<email>",
    "full_name": "<full_name>",
    "legal_name": "<legal_name>",
    "tax_code": "TKE-VN-30D-X3K9F"
  },
  "items": [
    {
      "package_code": "TKE-VN-30D-X3K9F",
      "quantity": 2
    }
  ]
}
GET/v1/orders/{id}

注文詳細とeSIM

scope orders:readget_orders__id_

必要な権限スコープ: orders:read.

パスパラメーター (1)

idstring必須

注文ID(UUID)。

クエリパラメーター (1)

includestring任意

追加ブロックをカンマ区切りで指定します。lpaはinstall、qrは詳細取得時のみinstall.qr_code_base64を返します。コードの返却は開示であり、対象の全eSIMを永続的に取消不可にします(cancellable.allowed = false、reason = code_disclosed)。顧客へすぐ渡す場合に要求し、後日渡す場合は省略して取消権を保ってください。不明な値はinternal.invalid_filter(400、field: "include")。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須

パートナー注文。

created_atstring · date-time
—
external_refstring
null可
—
fulfillment_statusstring

実際の納品状況で、statusとは別の軸です。3件中2件が納品、1件が失敗した場合もstatus=completedですが、fulfillment_status=partially_fulfilled、refunded_amount > 0になります。

fulfilledpartially_fulfilledunfulfilled
idstring · uuid

注文ID(UUID)。

idempotent_replayboolean
null可

過去の成功を冪等に再実行した場合に真となります。

invoice_nostring
null可

発行後の請求書番号です。

invoice_statusstring

注文のVAT請求書状態です。noneは未発行です。

nonependingissuingissuedfailedcancelled
itemsobject[]
—
cancellableobject

eSIMの取消可否と不可の理由。POST /v1/esims/{order_item_id}/cancelの前に確認してください。回答のため常に存在し、nullにはなりません。

allowedboolean
—
disclosed_atstring · date-time
null可

コードがシステム外に出た時刻(ISO-8601 UTC)。誰も見ていない間はnullです。未受領を理由に取消不可を争う場合の確認記録です。

reasonstring
null可

取消不可の理由:code_disclosed(送信・表示済み)、wrong_status(状態不適合)、expired(期限切れ)、not_supported(取消機能未宣言)。allowed = trueならnull。esim.not_cancellableのmeta.reasonと同じ用語です。

code_disclosedwrong_statusexpirednot_supportednull
external_refstring
null可

注文時に送信したexternal_refで、eSIMと注文を照合します。未指定で注文した場合はnull。

iccidstring
null可
—
idstring · uuid

全/v1/esims/{id}/…パスで使うeSIM IDで、Webhookのorder_item_idでもあります。ICCIDのみ分かる場合はGET /v1/esims?iccid=…でidを取得します。

installobject
null可

このeSIMのインストールに必要なすべての情報です。nullは未要求(include=lpaなし)を意味します。まだコードがない場合とは異なり、その場合はブロックが存在してlpa: nullになります。

このブロックを含む応答には常にCache-Control: no-storeが付きます。

android_urlstring
null可
—
apnstring
null可

自動設定できないときに入力するアクセスポイント名(APN)です。現バージョンでは常にnullで、不明を意味し、不要という意味ではありません。

ios_urlstring
null可
—
lpastring
null可

eSIMのアクティベーションコードで、販売可能な秘密情報です。この文字列だけでQRコードを生成できます。

matching_idstring
null可
—
qr_code_base64string
null可

QRコードのPNGデータURIです。詳細エンドポイントでinclude=qrを指定した場合のみ存在し、一覧には含みません(1行約11KB、100行で約1.1MB)。lpaからQRコードを生成してください。

smdp_addressstring
null可
—
msisdnstring
null可
—
order_idstring · uuid
—
package_codestring
null可

カタログのプランコードで、eSIMをカタログに紐付けるキーです。元プランがカタログから削除された場合のみnullです。

package_namestring

表示用の名称で、変更される場合があります。照合キーには使用しないでください。

planobject
null可

このeSIMに現在適用されているプラン。

current_codestring
—
expires_atstring · date-time
null可
—
started_atstring · date-time
null可
—
smdp_statusstring
null可
—
statusstring
—
updated_atstring · date-time
—
usageobject
null可

eSIMのデータ利用統計。未取得の場合はupdated_at = null。

expires_atstring · date-time
null可
—
remaining_bytesinteger · int64
null可
—
sourcestring
null可
—
pollwebhook
total_bytesinteger · int64
null可
—
updated_atstring · date-time
null可
—
used_bytesinteger · int64
null可
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
money_settledboolean

注文金額が精算済みか(返金処理中でないか)。falseの場合は請求書を発行できません。

netobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
public_refstring
null可

サポートへの問い合わせに使用する短い注文コードです。

refundedobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
statusstring
—
completedpending_providerprovider_failedcancelled
totalobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failedinternal.invalid_filter
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
internal.not_found
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="GET"
REQ_PATH="/v1/orders/$ID"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "created_at": "2026-07-11T08:12:30Z",
    "external_ref": "po-1001",
    "fulfillment_status": "fulfilled",
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "idempotent_replay": true,
    "invoice_no": "<invoice_no>",
    "invoice_status": "none",
    "items": [
      {
        "cancellable": {
          "allowed": true,
          "disclosed_at": "2026-07-11T08:12:30Z",
          "reason": "code_disclosed"
        },
        "external_ref": "po-1001",
        "iccid": "8984012345678901234",
        "id": "018f2b00-0000-7000-8000-00000000009a",
        "install": {
          "android_url": "https://esimsetup.google.com/esim_qrcode_provisioning?data=LPA%3A1%24smdp.example.com%24MATCH-ABC123",
          "apn": "<apn>",
          "ios_url": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA%3A1%24smdp.example.com%24MATCH-ABC123",
          "lpa": "LPA:1$smdp.example.com$MATCH-ABC123",
          "matching_id": "MATCH-ABC123",
          "qr_code_base64": "<PNG base64 — đã rút gọn>",
          "smdp_address": "smdp.example.com"
        },
        "msisdn": "+84900000000",
        "order_id": "018f2b00-0000-7000-8000-00000000009a",
        "package_code": "TKE-VN-30D-X3K9F",
        "package_name": "Tên gói hiển thị",
        "plan": {
          "current_code": "TKE-VN-30D-X3K9F",
          "expires_at": "2026-08-10T00:00:00Z",
          "started_at": "2026-07-11T08:12:30Z"
        },
        "smdp_status": "released",
        "status": "delivered",
        "updated_at": "2026-07-11T09:03:11Z",
        "usage": {
          "expires_at": "2026-08-10T00:00:00Z",
          "remaining_bytes": 5368709120,
          "source": "poll",
          "total_bytes": 5368709120,
          "updated_at": "2026-07-11T09:03:11Z",
          "used_bytes": 5368709120
        }
      }
    ],
    "mode": "live",
    "money_settled": true,
    "net": {
      "amount": 273000,
      "currency": "VND"
    },
    "public_ref": "TKE-DH-2A4C7Q",
    "refunded": {
      "amount": 273000,
      "currency": "VND"
    },
    "status": "completed",
    "total": {
      "amount": 273000,
      "currency": "VND"
    }
  },
  "ok": true
}
POST/v1/orders/{id}/resend

注文のメール・QRを再送

scope orders:writepost_orders__id__resend

必要な権限スコープ: orders:write.

パスパラメーター (1)

idstring必須

注文ID(UUID)。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
idstring · uuid

再送した注文のIDです。

modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
resent_atstring · date-time
—
resent_tostring

一部を伏せた受信先アドレス。パートナー向けには顧客の完全なメールアドレスを再表示しません。

okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
409
order.not_deliverable
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="POST"
REQ_PATH="/v1/orders/$ID/resend"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "mode": "live",
    "resent_at": "2026-07-11T08:12:30Z",
    "resent_to": "ab***@x.com"
  },
  "ok": true
}
POST/v1/orders/bulk

複数行を一括注文(1行につき1注文)

scope orders:writeIdempotency-Key必須post_orders_bulk

必要な権限スコープ: orders:write.

複数行を一括注文します。各行はPOST /v1/ordersと同じquote→commitを実行し、独立した1注文を作成します。

部分成功方式で、失敗行は他行を止めず、成功行だけを課金します。在庫切れ、残高不足、販売不可、乱用対策の制限などはlines[].errorに入り、バッチ全体のHTTP状態は変えません。途中で残高不足になっても、安価な行は購入できるため後続行を試します。

状態は常に200です。単一の新規リソースではなく行別の混合結果のため201ではなく、リクエスト内で完了するので202やポーリングもありません。

同じIdempotency-Keyと同じ本文で再実行すると既存バッチを読み、完了行の結果をそのまま返し、pending行だけを続行します。二重課金はありません。実行行がなければIdempotent-Replayed: trueです。同じキーで本文が異なるとidempotency.conflictです。

同じ組織の同内容バッチを10分以内に再送すると、キーが異なっても誤クリックの重複と見なし、旧バッチをIdempotent-Replayed: true付きで返して追加課金しません。本当に同じ商品を追加購入する場合は、署名対象本文のexternal_refを変更してください。バッチの区別と後日の照合にも使えます。全行が失敗して注文未作成のバッチは制限せず、10分後は通常どおり再注文できます。

行の参照はlines[].external_ref、バッチ参照は応答上部にそのまま返します。

応答にLPA/QRは含まず、各order_idでGET /v1/orders/{order_id}から取得します。

ヘッダー (1)

Idempotency-Keystring必須

クライアントが生成する文字列。同じキーと本文は1回だけ実行され、再試行は元の結果を返します。api_key_id単位(§11)なので、異なるキーは別の命令です。

リクエスト本文必須application/json

フィールド型制約説明
external_refstring
null可

バッチ全体の参照コードです。バッチ応答で返されます。

itemsobject[]
必須

各要素は独立した注文を1件作成します。行数上限は設定可能(既定100)で、超過時はinternal.limit_exceeded(422)。

external_refstring
null可

この行専用の参照コードです。行の結果にそのまま返されます。

package_codestring
必須

組織向けカタログのプランコード、すなわちpublic_skuです。供給元を切り替えてもプランごとに不変なので、照合キーに使えます。例は形式のみ正しく実際には使えません。GET /v1/catalog/packagesから実コードを取得してください。

quantityinteger
必須
—

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須

一括注文の結果です。部分成功方式で、失敗行は他行を止めず、done行のみ課金します。LPA/QRは含まず、各order_idでGET /v1/orders/{id}から取得します。

created_atstring · date-time
—
external_refstring
null可
—
failed_linesinteger
—
idstring · uuid
—
itemsobject[]
—
chargedobject
null可
—
errorobject
null可

実際のdomain.reasonエラーコード。例:wallet.insufficient_balance、esim.out_of_stock、order.package_not_allowed、wallet.velocity_exceeded。

codestring
—
messagestring
—
external_refstring
null可
—
line_nointeger

1始まりで、送信した順序と一致します。

order_idstring · uuid
null可
—
package_codestring
—
quantityinteger
—
statusstring
—
pendingdonefailed
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
statusstring

pendingは中断により未実行の行がある状態です。同じIdempotency-Keyで再度呼び出して残りを実行してください。

pendingcompletedpartialfailed
succeeded_linesinteger
—
total_chargedobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
total_linesinteger
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
partner.package_not_visible
409
idempotency.conflict
422
internal.limit_exceeded
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="POST"
REQ_PATH="/v1/orders/bulk"   # them query thi noi thang vao day TRUOC khi ky
BODY='{"external_ref":"batch-2026-001","items":[{"external_ref":"po-1001","package_code":"TKE-VN-30D-X3K9F","quantity":5}]}'

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  --data-raw "$BODY"

レスポンス例

json
{
  "data": {
    "created_at": "2026-07-11T08:12:30Z",
    "external_ref": "batch-2026-001",
    "failed_lines": 1,
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "items": [
      {
        "charged": null,
        "error": {
          "code": "TKE-VN-30D-X3K9F",
          "message": "<message>"
        },
        "external_ref": "po-1001",
        "line_no": 1,
        "order_id": "018f2b00-0000-7000-8000-00000000009a",
        "package_code": "TKE-VN-30D-X3K9F",
        "quantity": 2,
        "status": "pending"
      }
    ],
    "mode": "live",
    "status": "pending",
    "succeeded_lines": 1,
    "total_charged": {
      "amount": 273000,
      "currency": "VND"
    },
    "total_lines": 1
  },
  "ok": true
}

リクエスト本文の例

json
{
  "external_ref": "batch-2026-001",
  "items": [
    {
      "external_ref": "po-1001",
      "package_code": "TKE-VN-30D-X3K9F",
      "quantity": 5
    }
  ]
}
GET/v1/orders/bulk/{id}

一括注文の結果

scope orders:readget_orders_bulk__id_

必要な権限スコープ: orders:read.

送信済み一括注文の行別結果を再取得します。最初の応答を失っても本文を再送せず復旧できます。別組織・別環境(本番/テスト)のバッチは404です。

パスパラメーター (1)

idstring必須

POST /v1/orders/bulkが返すバッチID(UUID)です。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須

一括注文の結果です。部分成功方式で、失敗行は他行を止めず、done行のみ課金します。LPA/QRは含まず、各order_idでGET /v1/orders/{id}から取得します。

created_atstring · date-time
—
external_refstring
null可
—
failed_linesinteger
—
idstring · uuid
—
itemsobject[]
—
chargedobject
null可
—
errorobject
null可

実際のdomain.reasonエラーコード。例:wallet.insufficient_balance、esim.out_of_stock、order.package_not_allowed、wallet.velocity_exceeded。

codestring
—
messagestring
—
external_refstring
null可
—
line_nointeger

1始まりで、送信した順序と一致します。

order_idstring · uuid
null可
—
package_codestring
—
quantityinteger
—
statusstring
—
pendingdonefailed
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
statusstring

pendingは中断により未実行の行がある状態です。同じIdempotency-Keyで再度呼び出して残りを実行してください。

pendingcompletedpartialfailed
succeeded_linesinteger
—
total_chargedobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
total_linesinteger
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
internal.not_found
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="GET"
REQ_PATH="/v1/orders/bulk/$ID"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "created_at": "2026-07-11T08:12:30Z",
    "external_ref": "batch-2026-001",
    "failed_lines": 1,
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "items": [
      {
        "charged": null,
        "error": {
          "code": "TKE-VN-30D-X3K9F",
          "message": "<message>"
        },
        "external_ref": "po-1001",
        "line_no": 1,
        "order_id": "018f2b00-0000-7000-8000-00000000009a",
        "package_code": "TKE-VN-30D-X3K9F",
        "quantity": 2,
        "status": "pending"
      }
    ],
    "mode": "live",
    "status": "pending",
    "succeeded_lines": 1,
    "total_charged": {
      "amount": 273000,
      "currency": "VND"
    },
    "total_lines": 1
  },
  "ok": true
}

eSIM

eSIM記録、利用量、追加チャージ、取り消し

GET/v1/esims

eSIM一覧を取得(取得型照合)

scope esims:readget_esims

必要な権限スコープ: esims:read.

クエリパラメーター (8)

page_sizeinteger任意既定値 50min 1max 200

1ページの件数です。既定50、上限200。上限を超えてもエラーにせず200に制限します。

statusstring任意
許可される値:pendingavailablereservedsolddeliveredin_useused_upexpiredsuspendedcancelledprovider_failed

esim_statusで絞り込みます。一覧にない値は空配列ではなくinternal.invalid_filter(400)を返します。cancelledのlを1つ省いたcanceledなどの誤記を、該当するeSIMがないと誤認するのを防ぎます。

order_idstring · uuid任意

1つの注文に属するeSIMのみ。

iccidstring任意

ICCIDで絞り込みます(文字列、完全一致)。

external_refstring任意

注文時のexternal_refが完全一致する注文のすべてのeSIM。

updated_sincestring · date-time任意

ISO-8601 UTC形式です。updated_at >= updated_sinceの全レコードを昇順で返す、標準の取得型照合(§8.5)です。Webhookを取り逃しても状態から復元できます。形式不正はinternal.invalid_filter(400)です。

cursorstring任意

次ページにはnext_cursorをそのまま渡します。不正なカーソルはエラーにならず先頭から読み直します。これは形式変更時の互換性維持のためです。先頭ページで無限ループしないよう、返されたカーソルが送信値と異なることを確認してください。

includestring任意

追加ブロックをカンマ区切りで指定します。lpaはinstall、qrは詳細取得時のみinstall.qr_code_base64を返します。コードの返却は開示であり、対象の全eSIMを永続的に取消不可にします(cancellable.allowed = false、reason = code_disclosed)。顧客へすぐ渡す場合に要求し、後日渡す場合は省略して取消権を保ってください。不明な値はinternal.invalid_filter(400、field: "include")。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
itemsobject[]
—
cancellableobject

eSIMの取消可否と不可の理由。POST /v1/esims/{order_item_id}/cancelの前に確認してください。回答のため常に存在し、nullにはなりません。

allowedboolean
—
disclosed_atstring · date-time
null可

コードがシステム外に出た時刻(ISO-8601 UTC)。誰も見ていない間はnullです。未受領を理由に取消不可を争う場合の確認記録です。

reasonstring
null可

取消不可の理由:code_disclosed(送信・表示済み)、wrong_status(状態不適合)、expired(期限切れ)、not_supported(取消機能未宣言)。allowed = trueならnull。esim.not_cancellableのmeta.reasonと同じ用語です。

code_disclosedwrong_statusexpirednot_supportednull
external_refstring
null可

注文時に送信したexternal_refで、eSIMと注文を照合します。未指定で注文した場合はnull。

iccidstring
null可
—
idstring · uuid

全/v1/esims/{id}/…パスで使うeSIM IDで、Webhookのorder_item_idでもあります。ICCIDのみ分かる場合はGET /v1/esims?iccid=…でidを取得します。

installobject
null可

このeSIMのインストールに必要なすべての情報です。nullは未要求(include=lpaなし)を意味します。まだコードがない場合とは異なり、その場合はブロックが存在してlpa: nullになります。

このブロックを含む応答には常にCache-Control: no-storeが付きます。

android_urlstring
null可
—
apnstring
null可

自動設定できないときに入力するアクセスポイント名(APN)です。現バージョンでは常にnullで、不明を意味し、不要という意味ではありません。

ios_urlstring
null可
—
lpastring
null可

eSIMのアクティベーションコードで、販売可能な秘密情報です。この文字列だけでQRコードを生成できます。

matching_idstring
null可
—
qr_code_base64string
null可

QRコードのPNGデータURIです。詳細エンドポイントでinclude=qrを指定した場合のみ存在し、一覧には含みません(1行約11KB、100行で約1.1MB)。lpaからQRコードを生成してください。

smdp_addressstring
null可
—
msisdnstring
null可
—
order_idstring · uuid
—
package_codestring
null可

カタログのプランコードで、eSIMをカタログに紐付けるキーです。元プランがカタログから削除された場合のみnullです。

package_namestring

表示用の名称で、変更される場合があります。照合キーには使用しないでください。

planobject
null可

このeSIMに現在適用されているプラン。

current_codestring
—
expires_atstring · date-time
null可
—
started_atstring · date-time
null可
—
smdp_statusstring
null可
—
statusstring
—
updated_atstring · date-time
—
usageobject
null可

eSIMのデータ利用統計。未取得の場合はupdated_at = null。

expires_atstring · date-time
null可
—
remaining_bytesinteger · int64
null可
—
sourcestring
null可
—
pollwebhook
total_bytesinteger · int64
null可
—
updated_atstring · date-time
null可
—
used_bytesinteger · int64
null可
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
next_cursorstring
null可

次のページを取得する際は値をそのまま返してください。終了の唯一の合図はnullです。page_sizeより少ない件数でも続きがある場合があります。

page_sizeinteger
null可

サーバーがページに使用した、上限適用後の最大件数です。itemsの実際の要素数ではありません。

totalinteger · int64
null可

条件に一致する件数です。集計コストが高い場合はnullになります。終端の判定には使用せず、next_cursorを確認してください。

warningsobject[]

一覧の理由。特記事項がなければ空です。固定コード:filtered_by_key_package_filters、filtered_by_provider_scope、no_price_for_org、price_filter_removed_rows、provider_disabled、capability_missing。それぞれキー制限、組織の供給元範囲、価格未設定、価格条件、供給元無効、機能未宣言を示します。countは対象行数、数値化できない場合はnullです。

codestring
—
filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing
countinteger · int64
null可
—
messagestring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failedinternal.invalid_filter
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="GET"
REQ_PATH="/v1/esims"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "items": [
      {
        "cancellable": {
          "allowed": true,
          "disclosed_at": "2026-07-11T08:12:30Z",
          "reason": "code_disclosed"
        },
        "external_ref": "po-1001",
        "iccid": "8984012345678901234",
        "id": "018f2b00-0000-7000-8000-00000000009a",
        "install": {
          "android_url": "https://esimsetup.google.com/esim_qrcode_provisioning?data=LPA%3A1%24smdp.example.com%24MATCH-ABC123",
          "apn": "<apn>",
          "ios_url": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA%3A1%24smdp.example.com%24MATCH-ABC123",
          "lpa": "LPA:1$smdp.example.com$MATCH-ABC123",
          "matching_id": "MATCH-ABC123",
          "qr_code_base64": "<PNG base64 — đã rút gọn>",
          "smdp_address": "smdp.example.com"
        },
        "msisdn": "+84900000000",
        "order_id": "018f2b00-0000-7000-8000-00000000009a",
        "package_code": "TKE-VN-30D-X3K9F",
        "package_name": "Tên gói hiển thị",
        "plan": {
          "current_code": "TKE-VN-30D-X3K9F",
          "expires_at": "2026-08-10T00:00:00Z",
          "started_at": "2026-07-11T08:12:30Z"
        },
        "smdp_status": "released",
        "status": "delivered",
        "updated_at": "2026-07-11T09:03:11Z",
        "usage": {
          "expires_at": "2026-08-10T00:00:00Z",
          "remaining_bytes": 5368709120,
          "source": "poll",
          "total_bytes": 5368709120,
          "updated_at": "2026-07-11T09:03:11Z",
          "used_bytes": 5368709120
        }
      }
    ],
    "mode": "live",
    "next_cursor": "eyJ1cGRhdGVkX2F0IjoiMjAyNi0wNy0xMVQwODoxMjozMFoifQ",
    "page_size": 50,
    "total": 128,
    "warnings": []
  },
  "ok": true
}
GET/v1/esims/{id}

eSIMを1件取得

scope esims:readget_esims__id_

必要な権限スコープ: esims:read.

パスパラメーター (1)

idstring必須

販売済みeSIMの固定ID。再利用され得るICCIDとは異なります。

クエリパラメーター (1)

includestring任意

追加ブロックをカンマ区切りで指定します。lpaはinstall、qrは詳細取得時のみinstall.qr_code_base64を返します。コードの返却は開示であり、対象の全eSIMを永続的に取消不可にします(cancellable.allowed = false、reason = code_disclosed)。顧客へすぐ渡す場合に要求し、後日渡す場合は省略して取消権を保ってください。不明な値はinternal.invalid_filter(400、field: "include")。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
cancellableobject

eSIMの取消可否と不可の理由。POST /v1/esims/{order_item_id}/cancelの前に確認してください。回答のため常に存在し、nullにはなりません。

allowedboolean
—
disclosed_atstring · date-time
null可

コードがシステム外に出た時刻(ISO-8601 UTC)。誰も見ていない間はnullです。未受領を理由に取消不可を争う場合の確認記録です。

reasonstring
null可

取消不可の理由:code_disclosed(送信・表示済み)、wrong_status(状態不適合)、expired(期限切れ)、not_supported(取消機能未宣言)。allowed = trueならnull。esim.not_cancellableのmeta.reasonと同じ用語です。

code_disclosedwrong_statusexpirednot_supportednull
external_refstring
null可

注文時に送信したexternal_refで、eSIMと注文を照合します。未指定で注文した場合はnull。

iccidstring
null可
—
idstring · uuid

全/v1/esims/{id}/…パスで使うeSIM IDで、Webhookのorder_item_idでもあります。ICCIDのみ分かる場合はGET /v1/esims?iccid=…でidを取得します。

installobject
null可

このeSIMのインストールに必要なすべての情報です。nullは未要求(include=lpaなし)を意味します。まだコードがない場合とは異なり、その場合はブロックが存在してlpa: nullになります。

このブロックを含む応答には常にCache-Control: no-storeが付きます。

android_urlstring
null可
—
apnstring
null可

自動設定できないときに入力するアクセスポイント名(APN)です。現バージョンでは常にnullで、不明を意味し、不要という意味ではありません。

ios_urlstring
null可
—
lpastring
null可

eSIMのアクティベーションコードで、販売可能な秘密情報です。この文字列だけでQRコードを生成できます。

matching_idstring
null可
—
qr_code_base64string
null可

QRコードのPNGデータURIです。詳細エンドポイントでinclude=qrを指定した場合のみ存在し、一覧には含みません(1行約11KB、100行で約1.1MB)。lpaからQRコードを生成してください。

smdp_addressstring
null可
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
msisdnstring
null可
—
order_idstring · uuid
—
package_codestring
null可

カタログのプランコードで、eSIMをカタログに紐付けるキーです。元プランがカタログから削除された場合のみnullです。

package_namestring

表示用の名称で、変更される場合があります。照合キーには使用しないでください。

planobject
null可

このeSIMに現在適用されているプラン。

current_codestring
—
expires_atstring · date-time
null可
—
started_atstring · date-time
null可
—
smdp_statusstring
null可
—
statusstring
—
updated_atstring · date-time
—
usageobject
null可

eSIMのデータ利用統計。未取得の場合はupdated_at = null。

expires_atstring · date-time
null可
—
remaining_bytesinteger · int64
null可
—
sourcestring
null可
—
pollwebhook
total_bytesinteger · int64
null可
—
updated_atstring · date-time
null可
—
used_bytesinteger · int64
null可
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failedinternal.invalid_filter
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
internal.not_found
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="GET"
REQ_PATH="/v1/esims/$ID"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "cancellable": {
      "allowed": true,
      "disclosed_at": "2026-07-11T08:12:30Z",
      "reason": "code_disclosed"
    },
    "external_ref": "po-1001",
    "iccid": "8984012345678901234",
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "install": {
      "android_url": "https://esimsetup.google.com/esim_qrcode_provisioning?data=LPA%3A1%24smdp.example.com%24MATCH-ABC123",
      "apn": "<apn>",
      "ios_url": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA%3A1%24smdp.example.com%24MATCH-ABC123",
      "lpa": "LPA:1$smdp.example.com$MATCH-ABC123",
      "matching_id": "MATCH-ABC123",
      "qr_code_base64": "<PNG base64 — đã rút gọn>",
      "smdp_address": "smdp.example.com"
    },
    "mode": "live",
    "msisdn": "+84900000000",
    "order_id": "018f2b00-0000-7000-8000-00000000009a",
    "package_code": "TKE-VN-30D-X3K9F",
    "package_name": "Tên gói hiển thị",
    "plan": {
      "current_code": "TKE-VN-30D-X3K9F",
      "expires_at": "2026-08-10T00:00:00Z",
      "started_at": "2026-07-11T08:12:30Z"
    },
    "smdp_status": "released",
    "status": "delivered",
    "updated_at": "2026-07-11T09:03:11Z",
    "usage": {
      "expires_at": "2026-08-10T00:00:00Z",
      "remaining_bytes": 5368709120,
      "source": "poll",
      "total_bytes": 5368709120,
      "updated_at": "2026-07-11T09:03:11Z",
      "used_bytes": 5368709120
    }
  },
  "ok": true
}
POST/v1/esims/{id}/cancel

未使用のeSIMを取り消す

scope esims:writeIdempotency-Key必須post_esims__id__cancel

必要な権限スコープ: esims:write.

パスパラメーター (1)

idstring必須

販売済みeSIMの固定ID。再利用され得るICCIDとは異なります。

ヘッダー (1)

Idempotency-Keystring必須

クライアントが生成する文字列。同じキーと本文は1回だけ実行され、再試行は元の結果を返します。api_key_id単位(§11)なので、異なるキーは別の命令です。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
cancelled_atstring · date-time
—
esim_idstring · uuid
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
refund_suggestedboolean

trueは返金が担当者の承認待ちで、まだ送金されていない状態です。refunded.amount = 0を返金なしと解釈しないでください。

refundedobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
statusstring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
409
esim.not_cancellableidempotency.conflict
422
capability.not_supported
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="POST"
REQ_PATH="/v1/esims/$ID/cancel"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Idempotency-Key: $(uuidgen)"

レスポンス例

json
{
  "data": {
    "cancelled_at": "2026-07-11T08:12:30Z",
    "esim_id": "018f2b00-0000-7000-8000-000000000000",
    "mode": "live",
    "refund_suggested": true,
    "refunded": {
      "amount": 273000,
      "currency": "VND"
    },
    "status": "cancelled"
  },
  "ok": true
}
POST/v1/esims/{id}/change-plan

eSIMを追加チャージする

scope esims:writeIdempotency-Key必須post_esims__id__change-plan

必要な権限スコープ: esims:write.

パスパラメーター (1)

idstring必須

販売済みeSIMの固定ID。再利用され得るICCIDとは異なります。

ヘッダー (1)

Idempotency-Keystring必須

クライアントが生成する文字列。同じキーと本文は1回だけ実行され、再試行は元の結果を返します。api_key_id単位(§11)なので、異なるキーは別の命令です。

リクエスト本文必須application/json

フィールド型制約説明
package_codestring
必須

組織向けカタログのプランコード、すなわちpublic_skuです。供給元を切り替えてもプランごとに不変なので、照合キーに使えます。例は形式のみ正しく実際には使えません。GET /v1/catalog/packagesから実コードを取得してください。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須

eSIMプラン変更の結果です。

chargedobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
current_planobject
—
codestring
—
expires_atstring · date-time
null可
—
started_atstring · date-time
null可
—
esim_idstring · uuid
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
order_idstring · uuid
—
previous_planobject
null可
—
cancelled_atstring · date-time
null可
—
codestring
—
remaining_bytes_forfeitedinteger · int64
null可
—
warningstring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
402
wallet.insufficient_balance
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
partner.package_not_visible
409
esim.topup_not_supportedesim.topup_provider_mismatchesim.not_eligibleidempotency.conflict
422
capability.not_supported
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="POST"
REQ_PATH="/v1/esims/$ID/change-plan"   # them query thi noi thang vao day TRUOC khi ky
BODY='{"package_code":"TKE-VN-7D-P4M2Q"}'

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  --data-raw "$BODY"

レスポンス例

json
{
  "data": {
    "charged": {
      "amount": 273000,
      "currency": "VND"
    },
    "current_plan": {
      "code": "TKE-VN-30D-X3K9F",
      "expires_at": "2026-08-10T00:00:00Z",
      "started_at": "2026-07-11T08:12:30Z"
    },
    "esim_id": "018f2b00-0000-7000-8000-000000000000",
    "mode": "live",
    "order_id": "018f2b00-0000-7000-8000-00000000009a",
    "previous_plan": {
      "cancelled_at": "2026-07-11T08:12:30Z",
      "code": "TKE-VN-30D-X3K9F",
      "remaining_bytes_forfeited": 2147483648
    },
    "warning": "Dung lượng còn lại của gói cũ KHÔNG được cộng dồn."
  },
  "ok": true
}

リクエスト本文の例

json
{
  "package_code": "TKE-VN-7D-P4M2Q"
}
GET/v1/esims/{id}/plan-options

このeSIM用の有効な追加チャージプラン

scope esims:readget_esims__id__plan-options

必要な権限スコープ: esims:read.

このeSIMに有効な追加プランのみを返します。サーバーがidから供給元を調べ、その供給元のプランだけを抽出します。/v1ではprovider_idを公開しないため、サーバー側で異なる供給元のプラン選択を構造的に防止します。一覧にないコードでPOST /v1/esims/{id}/change-planを呼ぶと409 esim.topup_provider_mismatchです。

供給元が未登録のeSIM(単純インポートや元データ未取得)では、空一覧(total: 0)が正しい応答で、エラーではありません。

パスパラメーター (1)

idstring必須

販売済みeSIMの固定ID。再利用され得るICCIDとは異なります。

クエリパラメーター (2)

page_sizeinteger任意既定値 50min 1max 200

1ページの件数です。既定50、上限200。上限を超えてもエラーにせず200に制限します。

cursorstring任意

次ページにはnext_cursorをそのまま渡します。不正なカーソルはエラーにならず先頭から読み直します。これは形式変更時の互換性維持のためです。先頭ページで無限ループしないよう、返されたカーソルが送信値と異なることを確認してください。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須

このeSIMの供給元で絞り込んだ追加チャージ用プランです。各要素はカタログと同じ完全なPackageです。policyは現在の供給元の方針で、nullは未確認を表し、取り消しがないという意味ではありません。

itemsobject[]
—
capabilitiesobject

供給元の種類から推測せず、プランが実際に宣言した購入後の機能です。宣言がない場合は全項目falseとし、必ず422 capability.not_supportedになる操作を約束しません。

cancelobject
—
restrictionstring
null可

code_not_disclosedは誰もコードを見ていない場合のみ取消可能という意味です(顧客送信、画面表示、?include=lpaも含む)。実際の取消条件であり、システムが把握できないインストール有無を示しません。旧unused_onlyは不正確な表現でした。

code_not_disclosednull
supportedboolean
—
plan_changeobject
—
policyobject
null可

この供給元で新しいプランを追加チャージする際の動作です。nullはチャージ不可、または供給元の方針を未確認であることを示します。推測してはいけません。すべてfalseのオブジェクトは何もキャンセルしない保証となり、nullとは意味が異なります。

……

さらに深い項目はJSONの例を参照してください。

supportedboolean
—
usage_checkobject
—
supportedboolean
—
codestring

組織向けカタログのプランコード、すなわちpublic_skuです。供給元を切り替えてもプランごとに不変なので、照合キーに使えます。例は形式のみ正しく実際には使えません。GET /v1/catalog/packagesから実コードを取得してください。

coverageobject

プランの利用可能地域。

countriesstring[]

ISO-3166 alpha-2コードです。グローバルプラン(200か国を列挙しません)および対象国の宣言がないプランでは空になります。

country_countinteger

全件取得して配列を数えることなく、複数国対応プランを並べ替え・絞り込みできる対象国数です。

groupstring

対象範囲:国(country)、地域(region)、世界(global)。オープン列挙型のため不明な値は無視してください。

regionstring
null可

常にnullです。地域はプランではなく国に関連付けられます。?region=での絞り込みは利用できます。

dataobject

プランのデータ容量です。二重丸めを避けるため、すべてMB・GBではなくバイト単位です。

daily_bytesinteger · int64
null可

1日あたりのデータ容量(バイト)です。fixed・unlimitedプランではnullです。

labelstring

全画面と同じ関数で生成される、人が読める表示名です。

modelstring

容量計測方式:daily(1日単位)、fixed(全期間の総量)、unlimited。拡張可能な列挙型のため、クライアントは不明な値を無視してください。

dailyfixedunlimited
resetobject
null可

日次容量のリセット時点。夜遅く購入した場合の初日分に影響する販売情報です。nullは未宣言。

atstring
null可

timezoneの現地時刻でのリセット時刻です(00:00、00:00:01)。

notestring
null可
—
timezonestring
null可

リセット時刻のタイムゾーン(UTC+8、UTC+7)。

total_bytesinteger · int64
null可

全期間の総容量(バイト)。daily/unlimitedではnullです。日次容量と日数を掛けても供給元が保証する総量にはなりません。

descriptionstring
null可

プランの販売用説明。未作成の場合はnull。

description_enstring
null可

英語の説明。未提供の場合はnull。

featuresobject

機能をコード配列ではなく型付きオブジェクトで表します。[]ではテザリング非対応と不明を区別できませんが、falseとnullなら区別できます。

appsobject[]

OS別のアプリ対応状況です。

配列に存在しないアプリは情報不明であり、対応を意味しません。 一覧にあるものだけが供給元の宣言で、現在はTikTokのみです。

統合フィールドを設けないのは意図的です。実際のカタログでは2,465プランがiPhoneでTikTokに対応しますが、Androidでは非対応です。単一のフラグで「非対応」にまとめると、カタログの約3分の1を誤って扱うことになります。

androidstring

supported(対応宣言)、blocked(非対応宣言)、unknown(このOSの宣言なし)。オープン列挙型。

supportedblockedunknown
appstring

小文字のアプリコード(例:tiktok)。

iosstring

supported(対応宣言)、blocked(非対応宣言)、unknown(このOSの宣言なし)。オープン列挙型。

supportedblockedunknown
notestring
null可
—
hotspotboolean
null可

他の機器へのWi-Fi共有。nullは未宣言で、falseとは異なります。

kyc_requiredboolean
null可

利用前に本人確認(KYC)が必要です。nullは未宣言です。

smsboolean
null可

SMS。falseはSMSを受信できず、銀行のワンタイムパスワードも受信できません。nullは未宣言です。

voiceboolean
null可

音声通話。falseは供給元が音声非対応を宣言しており、データ専用回線は着信できません。nullは未宣言。

fupobject
null可

高速容量を使い切った後の動作。nullは速度制限の方針が未宣言です。

behaviorstring
null可

throttle(減速)、cutoff(切断)、null(未宣言)。オープン列挙型。

throttlecutoffnull
high_speed_bytesinteger · int64
null可

速度制限が始まるまでの高速通信量(バイト)。

notestring
null可
—
speed_kbpsinteger
null可

高速容量消費後の速度(kbps)です。回線停止または未宣言ならnullです。プラン全体の速度上限network.speed_cap_kbpsとは異なります。

marketstring

プランの供給システムです。拡張可能な列挙型のため不明値は無視してください。在庫の有無と販売後操作を決定します。domesticはキットを販売し、追加・取消・使用量照会に対応します。internationalは要求時に供給元へ注文するため在庫がありません。

domesticinternational
namestring
—
name_enstring
null可

英語名。未提供の場合はnull。

networkobject

プランが利用する通信網。

apnstring
null可

自動設定できない一部のAndroid端末で手動入力するAPNです。インストール手順に必要で、情報がなければ個別のサポート対応が必要になります。nullは未宣言です。

carriersobject[]

このプランが使用する通信事業者です。供給元ではなく、利用する無線ネットワークというeSIMの仕様です。

namestring
—
generationsstring[]
null可

利用可能な通信世代(["4g", "5g"])です。nullは未宣言であり、2G専用という意味ではありません。

speed_cap_kbpsinteger
null可

プラン全体の速度上限(kbps)です。高速容量消費後に適用するfup.speed_kbpsとは異なります。

priceobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
tagsstring[]

小文字・ハイフンで正規化した商品タグです。キーのカタログ制限にも使用します。現在タグ付きプランはなく、販売者が付与するまで?tag=は空一覧を返します。

validityobject

プランの有効期間と計測開始時点です。

daysinteger
—
install_by_daysinteger
null可

購入後にQRコードを読み取り、eSIMをインストールできる日数です。nullは未宣言であり、いつでもインストール可能という意味ではありません。

labelstring
—
reclaim_on_expiryboolean
null可

期限切れ時に供給元が契約を回収するため、追加チャージや変更ができなくなります。更新を販売する場合に重要です。nullは未宣言。

starts_whenstring
null可

計測開始:on_install(インストール時)、on_purchase(購入時)、またはnull。有効期限の算出に重要です。nullなら具体的な期限を約束しないでください。

on_installon_purchasenull
unused_valid_daysinteger
null可

未使用で保管できる期限までの日数です。nullは未宣言であり、無期限ではありません。保管期限とインストール期限は異なるため、install_by_daysとは別です。

modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
next_cursorstring
null可

次のページを取得する際は値をそのまま返してください。終了の唯一の合図はnullです。page_sizeより少ない件数でも続きがある場合があります。

page_sizeinteger

サーバーがページに使用した、上限適用後の最大件数です。itemsの実際の要素数ではありません。

policyobject
null可

この供給元で新しいプランを追加チャージする際の動作です。nullはチャージ不可、または供給元の方針を未確認であることを示します。推測してはいけません。すべてfalseのオブジェクトは何もキャンセルしない保証となり、nullとは意味が異なります。

notestring
null可
—
requires_cancel_firstboolean

この供給元はプランを積み重ねないため、新規注文前に利用中のプランがキャンセルされます。追加チャージボタンを押す前に顧客へ説明してください。

stackingboolean

新プランの期間と容量を現行プランに加算するかどうか。

totalinteger · int64
null可

条件に一致する総プラン数。国際向けやmarket未指定など集計が高コストな場合はnull。キー制限と組織価格の判定前に集計するため、購入可能数ではなくカタログの一致数です。

warningsobject[]

一覧の理由。特記事項がなければ空です。固定コード:filtered_by_key_package_filters、filtered_by_provider_scope、no_price_for_org、price_filter_removed_rows、provider_disabled、capability_missing。それぞれキー制限、組織の供給元範囲、価格未設定、価格条件、供給元無効、機能未宣言を示します。countは対象行数、数値化できない場合はnullです。

codestring
—
filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing
countinteger · int64
null可
—
messagestring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
internal.not_found
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="GET"
REQ_PATH="/v1/esims/$ID/plan-options"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "items": [
      {
        "capabilities": {
          "cancel": {
            "restriction": "code_not_disclosed",
            "supported": true
          },
          "plan_change": {
            "policy": {
              "note": "<note>",
              "requires_cancel_first": true,
              "stacking": true
            },
            "supported": true
          },
          "usage_check": {
            "supported": true
          }
        },
        "code": "TKE-VN-30D-X3K9F",
        "coverage": {
          "countries": [
            "CN"
          ],
          "country_count": 1,
          "group": "country",
          "region": "<region>"
        },
        "data": {
          "daily_bytes": 1073741824,
          "label": "1GB/ngày",
          "model": "daily",
          "reset": {
            "at": "00:00",
            "note": "<note>",
            "timezone": "UTC+8"
          },
          "total_bytes": null
        },
        "description": "<description>",
        "description_en": "<description_en>",
        "features": {
          "apps": [
            {
              "android": "blocked",
              "app": "tiktok",
              "ios": "supported",
              "note": "<note>"
            }
          ],
          "hotspot": true,
          "kyc_required": false,
          "sms": false,
          "voice": false
        },
        "fup": {
          "behavior": "throttle",
          "high_speed_bytes": 1048576,
          "note": "<note>",
          "speed_kbps": 128
        },
        "market": "international",
        "name": "eSIM Trung Quốc Mainland Multi - 1GB/ngày - 24 ngày",
        "name_en": "<name_en>",
        "network": {
          "apn": "e-ideas",
          "carriers": [
            {
              "name": "China Unicom"
            }
          ],
          "generations": [
            "4g",
            "5g"
          ],
          "speed_cap_kbps": 1
        },
        "price": {
          "amount": 273000,
          "currency": "VND"
        },
        "tags": [],
        "validity": {
          "days": 24,
          "install_by_days": 365,
          "label": "24 ngày",
          "reclaim_on_expiry": true,
          "starts_when": "on_install",
          "unused_valid_days": 1
        }
      }
    ],
    "mode": "live",
    "next_cursor": "eyJ1cGRhdGVkX2F0IjoiMjAyNi0wNy0xMVQwODoxMjozMFoifQ",
    "page_size": 50,
    "policy": {
      "note": "<note>",
      "requires_cancel_first": true,
      "stacking": true
    },
    "total": 128,
    "warnings": []
  },
  "ok": true
}
GET/v1/esims/{id}/refund-requests

eSIM返金申請履歴(会員専用)

scope esims:readget_esims__id__refund-requests

必要な権限スコープ: esims:read.

承認済みの本番メンバーキー専用です。所有eSIMの直近50件までの返金申請を新しい順に返し、next_cursorとtotalはnullです。has_open_requestは審査待ちを示します。組織・テストキーはcapability.not_supportedです。

パスパラメーター (1)

idstring必須

販売済みeSIMの固定ID。再利用され得るICCIDとは異なります。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
has_open_requestboolean
—
itemsobject[]
—
decided_atstring · date-time
null可
—
decision_notestring
null可
—
idstring · uuid
—
order_idstring · uuid
—
order_item_idstring · uuid
—
reasonstring
—
refundedobject
null可
—
requested_atstring · date-time
—
statusstring
—
pendingapprovedrejected
suggestedobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
next_cursorstring
null可

次のページを取得する際は値をそのまま返してください。終了の唯一の合図はnullです。page_sizeより少ない件数でも続きがある場合があります。

page_sizeinteger
null可

サーバーがページに使用した、上限適用後の最大件数です。itemsの実際の要素数ではありません。

totalinteger · int64
null可

条件に一致する件数です。集計コストが高い場合はnullになります。終端の判定には使用せず、next_cursorを確認してください。

warningsobject[]

一覧の理由。特記事項がなければ空です。固定コード:filtered_by_key_package_filters、filtered_by_provider_scope、no_price_for_org、price_filter_removed_rows、provider_disabled、capability_missing。それぞれキー制限、組織の供給元範囲、価格未設定、価格条件、供給元無効、機能未宣言を示します。countは対象行数、数値化できない場合はnullです。

codestring
—
filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing
countinteger · int64
null可
—
messagestring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
internal.not_found
422
capability.not_supported
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_member_live_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="GET"
REQ_PATH="/v1/esims/$ID/refund-requests"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "has_open_request": true,
    "items": [
      {
        "decided_at": "2026-07-11T08:12:30Z",
        "decision_note": "<decision_note>",
        "id": "018f2b00-0000-7000-8000-00000000009a",
        "order_id": "018f2b00-0000-7000-8000-00000000009a",
        "order_item_id": "018f2b00-0000-7000-8000-000000000000",
        "reason": "<reason>",
        "refunded": null,
        "requested_at": "2026-07-11T08:12:30Z",
        "status": "pending",
        "suggested": {
          "amount": 273000,
          "currency": "VND"
        }
      }
    ],
    "mode": "live",
    "next_cursor": "eyJ1cGRhdGVkX2F0IjoiMjAyNi0wNy0xMVQwODoxMjozMFoifQ",
    "page_size": 50,
    "total": 128,
    "warnings": []
  },
  "ok": true
}
POST/v1/esims/{id}/refund-requests

eSIM返金申請を作成(会員専用)

scope esims:writeIdempotency-Key必須post_esims__id__refund-requests

必要な権限スコープ: esims:write.

承認済みの本番メンバーキー専用です。Idempotency-Keyを付けて所有eSIMの返金を申請し、管理者承認前に残高は移動しません。組織・テストキーはcapability.not_supportedです。テストモードではeSIMキャンセルで仮想残高への返金を確認します。

パスパラメーター (1)

idstring必須

販売済みeSIMの固定ID。再利用され得るICCIDとは異なります。

ヘッダー (1)

Idempotency-Keystring必須

クライアントが生成する文字列。同じキーと本文は1回だけ実行され、再試行は元の結果を返します。api_key_id単位(§11)なので、異なるキーは別の命令です。

リクエスト本文必須application/json

フィールド型制約説明
reasonstring
必須

前後の空白を除去した後、5〜1000文字の返金理由。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
decided_atstring · date-time
null可
—
decision_notestring
null可
—
idstring · uuid
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
order_idstring · uuid
—
order_item_idstring · uuid
—
reasonstring
—
refundedobject
null可
—
requested_atstring · date-time
—
statusstring
—
pendingapprovedrejected
suggestedobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
internal.not_found
409
esim.refund_not_eligibleesim.refund_request_pendingidempotency.conflict
422
capability.not_supported
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_member_live_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="POST"
REQ_PATH="/v1/esims/$ID/refund-requests"   # them query thi noi thang vao day TRUOC khi ky
BODY='{"reason":"<reason>"}'

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  --data-raw "$BODY"

レスポンス例

json
{
  "data": {
    "decided_at": "2026-07-11T08:12:30Z",
    "decision_note": "<decision_note>",
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "mode": "live",
    "order_id": "018f2b00-0000-7000-8000-00000000009a",
    "order_item_id": "018f2b00-0000-7000-8000-000000000000",
    "reason": "<reason>",
    "refunded": null,
    "requested_at": "2026-07-11T08:12:30Z",
    "status": "pending",
    "suggested": {
      "amount": 273000,
      "currency": "VND"
    }
  },
  "ok": true
}

リクエスト本文の例

json
{
  "reason": "<reason>"
}
GET/v1/esims/{id}/usage

使用済みデータ

scope esims:readget_esims__id__usage

必要な権限スコープ: esims:read.

eSIM の使用済み・残りデータ量を、値の基準時刻 updated_at(実際の鮮度)とともに返します。リクエスト時のみ照会する提供元(現在は SkyFi)の eSIM では、この呼び出しがスキャンをキューに入れ、結果を最大約 15 秒待つため、応答に最大 ~15 秒かかることがあり、返す値は完了したばかりのスキャンのものです。スキャンの失敗、同一 eSIM の 15 秒間隔制限内、または待機タイムアウトの場合はエラーを返さず、最後に保存された値を返すので updated_at を確認してください。他の提供元は定期的に更新される保存値を返します。

パスパラメーター (1)

idstring必須

販売済みeSIMの固定ID。再利用され得るICCIDとは異なります。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
esim_idstring · uuid
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
usageobject
null可

eSIMのデータ利用統計。未取得の場合はupdated_at = null。

expires_atstring · date-time
null可
—
remaining_bytesinteger · int64
null可
—
sourcestring
null可
—
pollwebhook
total_bytesinteger · int64
null可
—
updated_atstring · date-time
null可
—
used_bytesinteger · int64
null可
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
422
capability.not_supported
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="GET"
REQ_PATH="/v1/esims/$ID/usage"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "esim_id": "018f2b00-0000-7000-8000-000000000000",
    "mode": "live",
    "usage": {
      "expires_at": "2026-08-10T00:00:00Z",
      "remaining_bytes": 5368709120,
      "source": "poll",
      "total_bytes": 5368709120,
      "updated_at": "2026-07-11T09:03:11Z",
      "used_bytes": 5368709120
    }
  },
  "ok": true
}

ウォレット

ウォレット残高

GET/v1/wallet/balance

ウォレット残高

scope wallet:readget_wallet_balance

必要な権限スコープ: wallet:read.

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
availableobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
balanceobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
credit_limitobject

金額。/v1全体で同じ形式を使用し、オブジェクトと数値を切り替えません。

amountinteger · int64

currencyの最小単位で表す整数です(VNDに補助単位はありません)。

currencystring
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="GET"
REQ_PATH="/v1/wallet/balance"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "available": {
      "amount": 273000,
      "currency": "VND"
    },
    "balance": {
      "amount": 273000,
      "currency": "VND"
    },
    "credit_limit": {
      "amount": 273000,
      "currency": "VND"
    },
    "mode": "live"
  },
  "ok": true
}

Webhook

Webhook設定、配信ログ、シミュレーター

POST/v1/testmode/webhooks/fail-next

次のWebhook失敗をシミュレーション(テストキー専用)

scope webhook:managepost_testmode_webhooks_fail-next

必要な権限スコープ: webhook:manage.

リクエスト本文必須application/json

フィールド型制約説明
countinteger
—

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
endpoint_idstring · uuid
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
testmode_fail_nextinteger
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbidden
404
internal.not_found
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="POST"
REQ_PATH="/v1/testmode/webhooks/fail-next"   # them query thi noi thang vao day TRUOC khi ky
BODY='{"count":1}'

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Content-Type: application/json" \
  --data-raw "$BODY"

レスポンス例

json
{
  "data": {
    "endpoint_id": "018f2b00-0000-7000-8000-000000000000",
    "mode": "live",
    "testmode_fail_next": 1
  },
  "ok": true
}

リクエスト本文の例

json
{
  "count": 1
}
POST/v1/testmode/webhooks/fire

テストWebhookイベントを送信(テストキー専用)

scope webhook:managepost_testmode_webhooks_fire

必要な権限スコープ: webhook:manage.

リクエスト本文必須application/json

フィールド型制約説明
dataobject

サンプルペイロードのdataフィールドを部分的に上書きします。

event_typestring
必須

テスト送信するWebhookイベントの種類。

order.completedorder.failedesim.deliveredesim.activatedesim.usage_thresholdesim.expiringwallet.low_balancecatalog.updated

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
delivery_idstring · uuid
—
event_idstring · uuid
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbidden
404
webhook.not_configuredinternal.not_found
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="POST"
REQ_PATH="/v1/testmode/webhooks/fire"   # them query thi noi thang vao day TRUOC khi ky
BODY='{"data":{},"event_type":"order.completed"}'

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Content-Type: application/json" \
  --data-raw "$BODY"

レスポンス例

json
{
  "data": {
    "delivery_id": "018f2b00-0000-7000-8000-000000000000",
    "event_id": "018f3c00-0000-7000-8000-0000000000b0",
    "mode": "live"
  },
  "ok": true
}

リクエスト本文の例

json
{
  "data": {},
  "event_type": "order.completed"
}
GET/v1/webhooks

Webhookエンドポイント一覧を取得

scope webhook:manageget_webhooks

必要な権限スコープ: webhook:manage.

呼出し元APIキーのエンドポイントのみです。同じ組織内の別キーでも相互に参照できません(§5.11:api_key_idに紐付き、本番とテストは共有しません)。

未設定なら404ではなく空配列の200です。コレクションは常に存在し、項目だけがない状態です。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
itemsobject[]
—
activeboolean

falseは新規イベント停止を表し、画面からの一時停止かAPIキー失効時に同じトランザクションで停止します。CHECK_HEALTHに合格したPUT /v1/webhooks/{id}で再開します。

created_atstring · date-time
—
eventsstring[]

空の場合はすべて受信します。

idstring · uuid

/v1/webhooks/{id}に指定するエンドポイントIDです。作成ごとに新規発行され、削除後の再作成は元の復活ではなく別エンドポイントになります。

last_delivery_atstring · date-time
null可

このエンドポイントで最後に送信した時刻です。nullは送信失敗ではなく未送信であり、パートナーがWebhook未受信を報告した際に最初に確認します。

secret_last4string

Webhookシークレットの末尾4文字です。秘密全体を再公開せず、手元の鍵が署名に使われるものか確認できます。全体は作成時に1回だけ表示します。

urlstring
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
next_cursorstring
null可

次のページを取得する際は値をそのまま返してください。終了の唯一の合図はnullです。page_sizeより少ない件数でも続きがある場合があります。

page_sizeinteger
null可

サーバーがページに使用した、上限適用後の最大件数です。itemsの実際の要素数ではありません。

totalinteger · int64
null可

条件に一致する件数です。集計コストが高い場合はnullになります。終端の判定には使用せず、next_cursorを確認してください。

warningsobject[]

一覧の理由。特記事項がなければ空です。固定コード:filtered_by_key_package_filters、filtered_by_provider_scope、no_price_for_org、price_filter_removed_rows、provider_disabled、capability_missing。それぞれキー制限、組織の供給元範囲、価格未設定、価格条件、供給元無効、機能未宣言を示します。countは対象行数、数値化できない場合はnullです。

codestring
—
filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing
countinteger · int64
null可
—
messagestring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="GET"
REQ_PATH="/v1/webhooks"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "items": [
      {
        "active": true,
        "created_at": "2026-07-11T08:12:30Z",
        "events": [
          "order.completed"
        ],
        "id": "018f2b00-0000-7000-8000-00000000009a",
        "last_delivery_at": "2026-07-11T08:12:30Z",
        "secret_last4": "a3f9",
        "url": "https://partner.example.com/hooks/tke"
      }
    ],
    "mode": "live",
    "next_cursor": "eyJ1cGRhdGVkX2F0IjoiMjAyNi0wNy0xMVQwODoxMjozMFoifQ",
    "page_size": 50,
    "total": 128,
    "warnings": []
  },
  "ok": true
}
POST/v1/webhooks

Webhookエンドポイントを作成する

scope webhook:managepost_webhooks

必要な権限スコープ: webhook:manage.

呼出し元キーのWebhookエンドポイントを作成します。保存前にURLへ署名済みpingをPOSTします(CHECK_HEALTH)。2xxでなければ保存せず422 webhook.health_check_failedです。公開httpsURLが必須で、内部・メタデータIPは422 webhook.url_not_allowedです。

webhook_secretは作成時に1回だけ表示し、再取得できません。紛失時はダッシュボードでローテーションしてください。旧シークレットも24時間有効です(§8.4)。

既存エンドポイントがあれば、一時停止(is_active: false)中でも409 webhook.already_configuredです。停止中もURL・秘密鍵・ログは保持されます。作り直す場合はDELETE /v1/webhooks/{id}の後に新規作成します。

リクエスト本文必須application/json

フィールド型制約説明
eventsstring[]

空の場合はすべて受信。不明な値は400 internal.validation_failed(項目events)。

urlstring · uri
必須
—

レスポンス

201成功

成功

フィールド型制約説明
dataobject
必須
—
activeboolean

falseは新規イベント停止を表し、画面からの一時停止かAPIキー失効時に同じトランザクションで停止します。CHECK_HEALTHに合格したPUT /v1/webhooks/{id}で再開します。

created_atstring · date-time
—
eventsstring[]

空の場合はすべて受信します。

health_checkstring
—
passed
idstring · uuid

/v1/webhooks/{id}に指定するエンドポイントIDです。作成ごとに新規発行され、削除後の再作成は元の復活ではなく別エンドポイントになります。

last_delivery_atstring · date-time
null可

このエンドポイントで最後に送信した時刻です。nullは送信失敗ではなく未送信であり、パートナーがWebhook未受信を報告した際に最初に確認します。

modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
secret_last4string

Webhookシークレットの末尾4文字です。秘密全体を再公開せず、手元の鍵が署名に使われるものか確認できます。全体は作成時に1回だけ表示します。

urlstring
—
webhook_secretstring

作成時に1回だけ表示します(接頭辞whsec_)。

okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
409
webhook.already_configured
422
webhook.health_check_failedwebhook.url_not_allowed
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="POST"
REQ_PATH="/v1/webhooks"   # them query thi noi thang vao day TRUOC khi ky
BODY='{"events":["order.completed"],"url":"https://partner.example.com/hooks/tke"}'

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Content-Type: application/json" \
  --data-raw "$BODY"

レスポンス例

json
{
  "data": {
    "active": true,
    "created_at": "2026-07-11T08:12:30Z",
    "events": [
      "order.completed"
    ],
    "health_check": "passed",
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "last_delivery_at": "2026-07-11T08:12:30Z",
    "mode": "live",
    "secret_last4": "a3f9",
    "url": "https://partner.example.com/hooks/tke",
    "webhook_secret": "<webhook secret — chỉ hiện đúng một lần>"
  },
  "ok": true
}

リクエスト本文の例

json
{
  "events": [
    "order.completed"
  ],
  "url": "https://partner.example.com/hooks/tke"
}
GET/v1/webhooks/{id}

Webhookエンドポイントを1件取得

scope webhook:manageget_webhooks__id_

必要な権限スコープ: webhook:manage.

パスパラメーター (1)

idstring必須

WebhookエンドポイントID(POST /v1/webhooksまたはGET /v1/webhooksのid)。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
activeboolean

falseは新規イベント停止を表し、画面からの一時停止かAPIキー失効時に同じトランザクションで停止します。CHECK_HEALTHに合格したPUT /v1/webhooks/{id}で再開します。

created_atstring · date-time
—
eventsstring[]

空の場合はすべて受信します。

idstring · uuid

/v1/webhooks/{id}に指定するエンドポイントIDです。作成ごとに新規発行され、削除後の再作成は元の復活ではなく別エンドポイントになります。

last_delivery_atstring · date-time
null可

このエンドポイントで最後に送信した時刻です。nullは送信失敗ではなく未送信であり、パートナーがWebhook未受信を報告した際に最初に確認します。

modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
secret_last4string

Webhookシークレットの末尾4文字です。秘密全体を再公開せず、手元の鍵が署名に使われるものか確認できます。全体は作成時に1回だけ表示します。

urlstring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
webhook.not_found
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="GET"
REQ_PATH="/v1/webhooks/$ID"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "active": true,
    "created_at": "2026-07-11T08:12:30Z",
    "events": [
      "order.completed"
    ],
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "last_delivery_at": "2026-07-11T08:12:30Z",
    "mode": "live",
    "secret_last4": "a3f9",
    "url": "https://partner.example.com/hooks/tke"
  },
  "ok": true
}
PUT/v1/webhooks/{id}

Webhookエンドポイントを更新する

scope webhook:manageput_webhooks__id_

必要な権限スコープ: webhook:manage.

パスパラメーター (1)

idstring必須

WebhookエンドポイントID(POST /v1/webhooksまたはGET /v1/webhooksのid)。

リクエスト本文必須application/json

フィールド型制約説明
eventsstring[]

空の場合はすべて受信。不明な値は400 internal.validation_failed(項目events)。

urlstring · uri
必須
—

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
activeboolean

falseは新規イベント停止を表し、画面からの一時停止かAPIキー失効時に同じトランザクションで停止します。CHECK_HEALTHに合格したPUT /v1/webhooks/{id}で再開します。

created_atstring · date-time
—
eventsstring[]

空の場合はすべて受信します。

idstring · uuid

/v1/webhooks/{id}に指定するエンドポイントIDです。作成ごとに新規発行され、削除後の再作成は元の復活ではなく別エンドポイントになります。

last_delivery_atstring · date-time
null可

このエンドポイントで最後に送信した時刻です。nullは送信失敗ではなく未送信であり、パートナーがWebhook未受信を報告した際に最初に確認します。

modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
secret_last4string

Webhookシークレットの末尾4文字です。秘密全体を再公開せず、手元の鍵が署名に使われるものか確認できます。全体は作成時に1回だけ表示します。

urlstring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
webhook.not_found
422
webhook.health_check_failedwebhook.url_not_allowed
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="PUT"
REQ_PATH="/v1/webhooks/$ID"   # them query thi noi thang vao day TRUOC khi ky
BODY='{"events":["order.completed"],"url":"https://partner.example.com/hooks/tke"}'

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Content-Type: application/json" \
  --data-raw "$BODY"

レスポンス例

json
{
  "data": {
    "active": true,
    "created_at": "2026-07-11T08:12:30Z",
    "events": [
      "order.completed"
    ],
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "last_delivery_at": "2026-07-11T08:12:30Z",
    "mode": "live",
    "secret_last4": "a3f9",
    "url": "https://partner.example.com/hooks/tke"
  },
  "ok": true
}

リクエスト本文の例

json
{
  "events": [
    "order.completed"
  ],
  "url": "https://partner.example.com/hooks/tke"
}
DELETE/v1/webhooks/{id}

Webhookエンドポイントを削除(新規イベントの受信停止)

scope webhook:managedelete_webhooks__id_

必要な権限スコープ: webhook:manage.

削除すると呼出し元キーの新規イベント受信が止まります。

webhook_secretも失われます。POST /v1/webhooksで再作成すると新しいidとシークレットになるため、検証関数を更新してください。秘密鍵を保ったまま一時停止する場合は、ダッシュボードの停止ボタンを使用します。

送信ログは照合用にすべて保持しますが、削除済みエンドポイントの送信は再実行できません。

再試行待ちのpending送信はendpoint_disabledで停止し、ログに残ります(§8.5)。

別キーのidや削除済みのidは、成功の200ではなく404 webhook.not_foundです。

パスパラメーター (1)

idstring必須

WebhookエンドポイントID(POST /v1/webhooksまたはGET /v1/webhooksのid)。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
deleted_atstring · date-time
—
idstring · uuid
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
webhook.not_found
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="DELETE"
REQ_PATH="/v1/webhooks/$ID"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "deleted_at": "2026-07-11T08:12:30Z",
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "mode": "live"
  },
  "ok": true
}
GET/v1/webhooks/deliveries

Webhook配信ログ

scope webhook:manageget_webhooks_deliveries

必要な権限スコープ: webhook:manage.

クエリパラメーター (5)

pageinteger任意既定値 1min 1

1始まりのページ番号。末尾を超えるとitems: []と実際のtotalを返します(200、404ではありません)。

page_sizeinteger任意既定値 50min 1max 200

1ページの件数です。既定50、上限200。上限を超えてもエラーにせず200に制限します。

event_typestring任意

イベント種別で絞り込みます(Webhookイベント一覧を参照)。

statusstring任意
許可される値:pendingdeliveredfailed

送信状態で絞り込みます。?status=failedは取得型のWebhook照合(§13)で使用します。不明な値はエラーにならず無視され、すべてのログが返されます。

event_idstring · uuid任意

1つのイベントの全配信試行(再配信を含む)。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
itemsobject[]
—
attemptsinteger
—
created_atstring · date-time
—
event_idstring · uuid

イベント識別子です。再送では同じevent_idを持つ新しい送信が作成されます。送信のidではなくevent_idで重複排除してください。

event_typestring
—
idstring · uuid
—
last_attempt_atstring · date-time
null可
—
next_retry_atstring · date-time
null可
—
response_codeinteger
null可
—
statusstring
—
pendingdeliveredfailed
webhook_idstring · uuid
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
next_cursorstring
null可

次のページを取得する際は値をそのまま返してください。終了の唯一の合図はnullです。page_sizeより少ない件数でも続きがある場合があります。

page_sizeinteger
null可

サーバーがページに使用した、上限適用後の最大件数です。itemsの実際の要素数ではありません。

totalinteger · int64
null可

条件に一致する件数です。集計コストが高い場合はnullになります。終端の判定には使用せず、next_cursorを確認してください。

warningsobject[]

一覧の理由。特記事項がなければ空です。固定コード:filtered_by_key_package_filters、filtered_by_provider_scope、no_price_for_org、price_filter_removed_rows、provider_disabled、capability_missing。それぞれキー制限、組織の供給元範囲、価格未設定、価格条件、供給元無効、機能未宣言を示します。countは対象行数、数値化できない場合はnullです。

codestring
—
filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing
countinteger · int64
null可
—
messagestring
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
webhook.not_configured
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="GET"
REQ_PATH="/v1/webhooks/deliveries"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "items": [
      {
        "attempts": 3,
        "created_at": "2026-07-11T08:12:30Z",
        "event_id": "018f3c00-0000-7000-8000-0000000000b0",
        "event_type": "order.completed",
        "id": "018f2b00-0000-7000-8000-00000000009a",
        "last_attempt_at": "2026-07-11T09:05:00Z",
        "next_retry_at": "2026-07-11T09:10:00Z",
        "response_code": 200,
        "status": "pending",
        "webhook_id": "018f2b00-0000-7000-8000-000000000000"
      }
    ],
    "mode": "live",
    "next_cursor": "eyJ1cGRhdGVkX2F0IjoiMjAyNi0wNy0xMVQwODoxMjozMFoifQ",
    "page_size": 50,
    "total": 128,
    "warnings": []
  },
  "ok": true
}
POST/v1/webhooks/deliveries/{id}/replay

Webhookを再送

scope webhook:managepost_webhooks_deliveries__id__replay

必要な権限スコープ: webhook:manage.

パスパラメーター (1)

idstring必須

Webhook送信1件のIDです(GET /v1/webhooks/deliveriesのitems[].id)。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
attemptsinteger
—
created_atstring · date-time
—
event_idstring · uuid

イベント識別子です。再送では同じevent_idを持つ新しい送信が作成されます。送信のidではなくevent_idで重複排除してください。

event_typestring
—
idstring · uuid
—
last_attempt_atstring · date-time
null可
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
next_retry_atstring · date-time
null可
—
response_codeinteger
null可
—
statusstring
—
pendingdeliveredfailed
webhook_idstring · uuid
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspended
404
webhook.delivery_not_foundwebhook.not_configured
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="POST"
REQ_PATH="/v1/webhooks/deliveries/$ID/replay"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "attempts": 3,
    "created_at": "2026-07-11T08:12:30Z",
    "event_id": "018f3c00-0000-7000-8000-0000000000b0",
    "event_type": "order.completed",
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "last_attempt_at": "2026-07-11T09:05:00Z",
    "mode": "live",
    "next_retry_at": "2026-07-11T09:10:00Z",
    "response_code": 200,
    "status": "pending",
    "webhook_id": "018f2b00-0000-7000-8000-000000000000"
  },
  "ok": true
}

テストモード

api-testingホストでtke_test_またはtke_member_test_のテストキーのみを使用します。本番残高や供給元を使わず、所有者のテストeSIMとデータを模擬します。メンバーのテストモードはWebhook、一括注文、審査用返金申請に対応していません。

POST/v1/testmode/esims/{id}/simulate

テストeSIMのライフサイクルをシミュレーション(テストキー専用)

scope esims:writepost_testmode_esims__id__simulate

必要な権限スコープ: esims:write.

tke_test_またはtke_member_test_テストキー専用です。所有者のテストeSIMに使用量、インストール状態、期限切れ、速度制限、次回操作の供給元拒否を設定します。本文には少なくとも1項目が必要で、空の場合は422 testmode.invalid_scenarioです。本番と同じGET /v1/esims/{id}と/usageで結果を確認できます。プラン変更とキャンセル規則は共通で、実際の供給元は呼び出しません。

パスパラメーター (1)

idstring必須

販売済みeSIMの固定ID。再利用され得るICCIDとは異なります。

リクエスト本文必須application/json

フィールド型制約説明
data_used_mbinteger · int64

使用済みデータ量(MB、1 MiBの2進単位)。容量を超える値は上限に丸められ、データ使い切りのシナリオとなります。エラーではありません。

expire_atstring · date-time

有効期限の日時を指定します(ISO-8601 UTC)。

expire_nowboolean

trueでプランを即時失効(esim_statusがexpiredになる)。

provider_rejectboolean

次の操作(追加/キャンセル)で供給元の拒否をシミュレーションします。

statusstring

供給元の用語によるeSIMプロファイルの技術的ライフサイクルです。eSIM取得APIの業務上のesim_statusとは異なります。

releasedinstalledenableddisabled
throttledboolean

trueは速度制限中(無制限プランの高速容量を超過)。

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
cancellableobject

eSIMの取消可否と不可の理由。POST /v1/esims/{order_item_id}/cancelの前に確認してください。回答のため常に存在し、nullにはなりません。

allowedboolean
—
disclosed_atstring · date-time
null可

コードがシステム外に出た時刻(ISO-8601 UTC)。誰も見ていない間はnullです。未受領を理由に取消不可を争う場合の確認記録です。

reasonstring
null可

取消不可の理由:code_disclosed(送信・表示済み)、wrong_status(状態不適合)、expired(期限切れ)、not_supported(取消機能未宣言)。allowed = trueならnull。esim.not_cancellableのmeta.reasonと同じ用語です。

code_disclosedwrong_statusexpirednot_supportednull
external_refstring
null可

注文時に送信したexternal_refで、eSIMと注文を照合します。未指定で注文した場合はnull。

iccidstring
null可
—
idstring · uuid

全/v1/esims/{id}/…パスで使うeSIM IDで、Webhookのorder_item_idでもあります。ICCIDのみ分かる場合はGET /v1/esims?iccid=…でidを取得します。

installobject
null可

このeSIMのインストールに必要なすべての情報です。nullは未要求(include=lpaなし)を意味します。まだコードがない場合とは異なり、その場合はブロックが存在してlpa: nullになります。

このブロックを含む応答には常にCache-Control: no-storeが付きます。

android_urlstring
null可
—
apnstring
null可

自動設定できないときに入力するアクセスポイント名(APN)です。現バージョンでは常にnullで、不明を意味し、不要という意味ではありません。

ios_urlstring
null可
—
lpastring
null可

eSIMのアクティベーションコードで、販売可能な秘密情報です。この文字列だけでQRコードを生成できます。

matching_idstring
null可
—
qr_code_base64string
null可

QRコードのPNGデータURIです。詳細エンドポイントでinclude=qrを指定した場合のみ存在し、一覧には含みません(1行約11KB、100行で約1.1MB)。lpaからQRコードを生成してください。

smdp_addressstring
null可
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
msisdnstring
null可
—
order_idstring · uuid
—
package_codestring
null可

カタログのプランコードで、eSIMをカタログに紐付けるキーです。元プランがカタログから削除された場合のみnullです。

package_namestring

表示用の名称で、変更される場合があります。照合キーには使用しないでください。

planobject
null可

このeSIMに現在適用されているプラン。

current_codestring
—
expires_atstring · date-time
null可
—
started_atstring · date-time
null可
—
simulatedobject

シナリオ適用後のシミュレーション状態。

esim_statestring

テストeSIMの技術的ライフサイクルです。本番ではsmdp_statusから取得しますが、テストeSIMにはSM-DP+プロファイルがないため、テスト専用項目とともにここに置きます。

releasedinstalledenableddisabled
last_viastring

このeSIMに最後に変更を加えた処理経路です。

open_apisimulateseed
viastring

このテストeSIMを作成した処理経路です。

open_apisimulateseed
smdp_statusstring
null可
—
statusstring
—
updated_atstring · date-time
—
usageobject
null可

eSIMのデータ利用統計。未取得の場合はupdated_at = null。

expires_atstring · date-time
null可
—
remaining_bytesinteger · int64
null可
—
sourcestring
null可
—
pollwebhook
total_bytesinteger · int64
null可
—
updated_atstring · date-time
null可
—
used_bytesinteger · int64
null可
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbidden
404
internal.not_found
422
testmode.invalid_scenario
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"
ID="THAY-BANG-ID"

METHOD="POST"
REQ_PATH="/v1/testmode/esims/$ID/simulate"   # them query thi noi thang vao day TRUOC khi ky
BODY='{"data_used_mb":4096,"expire_at":"2026-07-11T08:12:30Z","expire_now":true,"provider_reject":true,"status":"enabled","throttled":true}'

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Content-Type: application/json" \
  --data-raw "$BODY"

レスポンス例

json
{
  "data": {
    "cancellable": {
      "allowed": true,
      "disclosed_at": "2026-07-11T08:12:30Z",
      "reason": "code_disclosed"
    },
    "external_ref": "po-1001",
    "iccid": "8984012345678901234",
    "id": "018f2b00-0000-7000-8000-00000000009a",
    "install": {
      "android_url": "https://esimsetup.google.com/esim_qrcode_provisioning?data=LPA%3A1%24smdp.example.com%24MATCH-ABC123",
      "apn": "<apn>",
      "ios_url": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA%3A1%24smdp.example.com%24MATCH-ABC123",
      "lpa": "LPA:1$smdp.example.com$MATCH-ABC123",
      "matching_id": "MATCH-ABC123",
      "qr_code_base64": "<PNG base64 — đã rút gọn>",
      "smdp_address": "smdp.example.com"
    },
    "mode": "live",
    "msisdn": "+84900000000",
    "order_id": "018f2b00-0000-7000-8000-00000000009a",
    "package_code": "TKE-VN-30D-X3K9F",
    "package_name": "Tên gói hiển thị",
    "plan": {
      "current_code": "TKE-VN-30D-X3K9F",
      "expires_at": "2026-08-10T00:00:00Z",
      "started_at": "2026-07-11T08:12:30Z"
    },
    "simulated": {
      "esim_state": "released",
      "last_via": "open_api",
      "via": "open_api"
    },
    "smdp_status": "released",
    "status": "delivered",
    "updated_at": "2026-07-11T09:03:11Z",
    "usage": {
      "expires_at": "2026-08-10T00:00:00Z",
      "remaining_bytes": 5368709120,
      "source": "poll",
      "total_bytes": 5368709120,
      "updated_at": "2026-07-11T09:03:11Z",
      "used_bytes": 5368709120
    }
  },
  "ok": true
}

リクエスト本文の例

json
{
  "data_used_mb": 4096,
  "expire_at": "2026-07-11T08:12:30Z",
  "expire_now": true,
  "provider_reject": true,
  "status": "enabled",
  "throttled": true
}
POST/v1/testmode/reset

テストデータをリセット(テストキー専用)

scope orders:writepost_testmode_reset

必要な権限スコープ: orders:write.

ヘッダー (1)

Idempotency-Keystring任意

リクエスト本文任意application/json

フィールド型制約説明
reasonstring
—

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
esim_states_deletedinteger · int64
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
order_items_deletedinteger · int64
—
orders_deletedinteger · int64
—
wallet_balanceinteger · int64

リセット後のテストウォレット残高で、常に0です。元帳は削除せず、相殺仕訳で残高をゼロにします。

okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbidden
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="POST"
REQ_PATH="/v1/testmode/reset"   # them query thi noi thang vao day TRUOC khi ky
BODY='{"reason":"Reset test data"}'

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  --data-raw "$BODY"

レスポンス例

json
{
  "data": {
    "esim_states_deleted": 1,
    "mode": "live",
    "order_items_deleted": 1,
    "orders_deleted": 1,
    "wallet_balance": 1
  },
  "ok": true
}

リクエスト本文の例

json
{
  "reason": "Reset test data"
}
POST/v1/testmode/seed

テストモードのサンプルデータを作成(テストキー専用)

scope orders:writepost_testmode_seed

必要な権限スコープ: orders:write.

ヘッダー (1)

Idempotency-Keystring任意

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
already_seededboolean
—
esims_createdinteger
—
modestring

呼び出しキーの環境で、X-TKE-Modeヘッダーと一致します。組織はtke_live_/tke_test_、メンバーはtke_member_live_/tke_member_test_を使用します。本番とテストのホストはキーモードを検証します。

testlive
orders_createdinteger
—
seededboolean
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbidden
422
testmode.no_sellable_package
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="POST"
REQ_PATH="/v1/testmode/seed"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG" \
  -H "Idempotency-Key: $(uuidgen)"

レスポンス例

json
{
  "data": {
    "already_seeded": true,
    "esims_created": 1,
    "mode": "live",
    "orders_created": 1,
    "seeded": true
  },
  "ok": true
}
GET/v1/testmode/status

テストモード概要(テストキー専用)

scope esims:readget_testmode_status

必要な権限スコープ: esims:read.

レスポンス

200成功

成功

フィールド型制約説明
dataobject
必須
—
base_url_testingstring

テストモード用ホストです。tke_test_またはtke_member_test_キーのみ使用できます。本番ホストへの呼び出しは403 partner.wrong_hostになります。

capabilitiesobject
—
bulk_ordersboolean
—
cancel_refundboolean
—
refund_requestsboolean
—
webhooksboolean
—
checklistobject[]

同じ所有者のテストモードAPI実績から連携状況を判定します。Webhookの項目は組織のみに適用されます。

doneboolean
—
labelstring
—
last_atstring · date-time
null可
—
stepstring
—
driftobject

模擬使用量ループの有効状態、間隔、最終実行時刻です。しきい値Webhookは対応する組織のみに送信されます。

enabledboolean
—
interval_secsinteger · int64
—
last_run_atstring · date-time
null可
—
modestring
—
testlive
readyboolean

キー所有者が対応するチェック項目をすべて完了したかを示します。メンバーはWebhookテスト不要です。

sample_countsobject
—
test_esimsinteger · int64
—
test_ordersinteger · int64
—
seededboolean

キー所有者にサンプルのテスト注文とeSIMがあるかを示します。

test_key_countinteger · int64
—
wallet_balanceinteger · int64

キー所有者の仮想VNDテスト残高です。本番ウォレットとは分離されています。

webhookobject
—
endpoint_urlstring
null可
—
fail_nextinteger
—
statusstring
null可
—
okboolean
必須
—
true

エラーレスポンス

すべてのエラーは { ok: false, error } と適切なHTTPステータスを返し、200は使用しません。エラーコードのページをご覧ください。

400
internal.validation_failed
401
partner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reused
403
partner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbidden
429
partner.rate_limited
503
partner.endpoint_disabledinternal.service_unavailable

呼び出し例

すべての TKE-VN-30D-X3K9F は置換が必要です。実際のプランコードは次で取得します: GET /v1/catalog/packages.

bash
#!/usr/bin/env bash
# Can: bash + openssl + uuidgen.

KEY_ID="tke_test_THAY-BANG-KEY-ID-CUA-BAN"
SECRET="THAY-BANG-SECRET-CUA-BAN"

METHOD="GET"
REQ_PATH="/v1/testmode/status"   # them query thi noi thang vao day TRUOC khi ky
BODY=""

TS="$(date +%s000)"                 # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'\n'"$REQ_PATH"$'\n'"$TS"$'\n'"$NONCE"$'\n'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"

curl -sS -X "$METHOD" "https://api-testing.tongkhoesim.com$REQ_PATH" \
  -H "Accept-Language: ja" \
  -H "X-TKE-Key: $KEY_ID" \
  -H "X-TKE-Timestamp: $TS" \
  -H "X-TKE-Nonce: $NONCE" \
  -H "X-TKE-Signature: $SIG"

レスポンス例

json
{
  "data": {
    "base_url_testing": "<base_url_testing>",
    "capabilities": {
      "bulk_orders": true,
      "cancel_refund": true,
      "refund_requests": true,
      "webhooks": true
    },
    "checklist": [
      {
        "done": true,
        "label": "<label>",
        "last_at": "2026-07-11T08:12:30Z",
        "step": "<step>"
      }
    ],
    "drift": {
      "enabled": true,
      "interval_secs": 1,
      "last_run_at": "2026-07-11T08:12:30Z"
    },
    "mode": "test",
    "ready": true,
    "sample_counts": {
      "test_esims": 1,
      "test_orders": 1
    },
    "seeded": true,
    "test_key_count": 1,
    "wallet_balance": 1,
    "webhook": {
      "endpoint_url": "https://partner.example.com/hooks/tke",
      "fail_next": 1,
      "status": "completed"
    }
  },
  "ok": true
}