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 签名。
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。
两种分页方式
两种方式的响应结构和结束条件不同,请分别处理。
仅用于 GET /v1/webhooks/deliveries,返回 page、page_size、total。
超出范围返回 HTTP 200、items: [] 和真实 total;列表为空或已处理 total 条时结束。
用于 /v1/catalog/packages、/v1/orders、/v1/esims、/v1/esims/{id}/plan-options,只有 orders 和 esims 支持 updated_since。
next_cursor 缺失或等于当前游标时结束,data 中可能完全不含此字段。
为兼容旧客户端,无效游标会静默回到起点。仅判断 next_cursor !== null 可能无限重复第一页。
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;
}目录
套餐目录为两个供应系统提供统一接口。供应系统通过字段(`market`: `domestic` | `international`)和筛选(`?market=`)区分,不再使用两个独立路径。 没有库存概念:不包含数量或 `available`/`low`/`out_of_stock` 等等级。套餐直接展示,若供应商无法交付,下单时由 `POST /v1/orders` 返回明确错误(如 `esim.out_of_stock`),而非目录提前告知。 统一使用游标分页。仅在统计成本低时(筛选国内系统)提供 `total`,否则为 `null`。
/v1/catalog/packages列出套餐
catalog:readget_catalog_packages所需权限范围: catalog:read.
您所属组织的套餐目录:两个供应系统共用一个接口,通过 ?market= 筛选。
仅返回实际可购买的套餐:已发布、供应商仍在分销、符合密钥目录限制,且已为组织定价。未定价套餐不显示是因为无法下单。
游标分页:首次不传 cursor,之后原样传回 next_cursor,直到为 null。当前页少于 page_size 条并不表示结束。
capabilities 来自套餐真实声明,绝不推测;未声明时全部标志为 false。宁可省略原本可用的按钮,也不承诺必然返回 422 的功能。
目录不包含库存概念,没有数量或有货/售罄等级。如果供应商无法交付,POST /v1/orders 会在下单时直接返回明确错误(如 esim.out_of_stock),无须从预先展示的字段推断。
查询参数 (18)
page_sizeinteger选填默认值 50min 1max 100每页记录数,默认 50,上限 100;超过上限时限制为 100,不报错。
marketstring选填供应系统:domestic | international。列表之外的值返回 internal.invalid_filter(400),而不是完整目录,避免将拼写错误误认为筛选没有排除任何记录。
countrystring选填ISO-3166 alpha-2 国家代码(如 VN),仅返回覆盖该国的套餐。
regionstring选填区域标识(如 chau-a),返回覆盖该区域至少一个国家的套餐及所有全球套餐。
qstring选填按公开代码和套餐名称进行自由文本搜索(部分匹配,不区分大小写)。
tagstring选填按一个商业标签筛选。与存储时使用相同的规范化方式:去除多余空格、转为小写并使用连字符,因此 Ban Le 与 ban-le 是同一标签。
data_modelstring选填流量模型:daily | fixed | unlimited,替代旧 supports_topup。未知值返回 internal.invalid_filter(400)。
data_min_bytesinteger · int64选填最低流量,单位为字节。按日套餐以每日额度比较;无限流量套餐始终满足下限条件。
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选填truefalsetrue 仅筛选明确支持热点的套餐,false 仅筛选明确不支持的套餐。未声明(features.hotspot = null)两边都不匹配。只接受字符串 true/false。
appstring选填仅返回声明在至少一个操作系统上支持此应用的套餐(app=tiktok)。未声明的套餐不匹配,沉默不代表承诺。目前仅接受 tiktok,其他代码返回 internal.invalid_filter(400)。
voicestring选填truefalsetrue 仅筛选明确支持语音的套餐,false 仅筛选明确不支持的套餐。未声明两边都不匹配。只接受字符串 true/false。
cursorstring选填原样传回 next_cursor。仅在其为 null 时停止,不要因页面条目少而停止。 密钥目录限制、组织定价、价格范围筛选均在分页之后执行。游标含筛选条件指纹,条件改变或游标损坏返回 catalog.cursor_mismatch(400),避免拼接不同查询的页面。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
items | object[] | — | |
capabilities | object | 套餐售后能力取自套餐实际声明,不根据供应商类型推断。未声明时所有标志为 | |
cancel | object | — | |
restriction | string | 可为 null |
code_not_disclosednull |
supported | boolean | — | |
plan_change | object | — | |
policy | object | 可为 null | 此供应商追加新套餐时的处理方式。 |
… | … | 还有更深层字段,请查看 JSON 示例。 | |
supported | boolean | — | |
usage_check | object | — | |
supported | boolean | — | |
code | string | 您目录中的套餐代码,即 | |
coverage | object | 套餐可用地区。 | |
countries | string[] | ISO-3166 alpha-2 国家代码。全球套餐不逐一列出 200 个国家;全球套餐及未声明覆盖范围的套餐返回空数组。 | |
country_count | integer | 套餐覆盖的国家数量,可据此排序或筛选多国套餐,无须获取全部数据后自行统计数组。 | |
group | string | 覆盖范围为国家列表( | |
region | string | 可为 null | 始终为 |
data | object | 套餐流量额度,所有数值均以字节表示,而非 MB/GB,以避免重复舍入。 | |
daily_bytes | integer · int64 | 可为 null | 每日流量额度,单位为字节。 |
label | string | 由所有界面共用的函数生成的可读标签。 | |
model | string | 流量计算方式: dailyfixedunlimited | |
reset | object | 可为 null | 每日额度重置时间。深夜购买时会影响首日可用时间,属于销售信息。 |
at | string | 可为 null | 按 |
note | string | 可为 null | — |
timezone | string | 可为 null | 重置时点的时区( |
total_bytes | integer · int64 | 可为 null | 整个周期总流量(字节)。 |
description | string | 可为 null | 套餐销售说明,尚未填写时为 |
description_en | string | 可为 null | 英文描述,尚未提供时为 |
features | object | 套餐能力采用带类型对象而非代码数组: | |
apps | object[] | 按操作系统区分的应用支持状态。 数组中不存在的应用表示信息未知,并非“支持”。 仅已列出的条目属于供应商承诺;目前只声明了 TikTok。 有意不提供合并字段:真实目录中有 2,465 个套餐支持 iPhone 上的 TikTok,但不支持 Android。一个合并标记会将其全部归为“不支持”,从而误判近三分之一的目录。 | |
android | string |
supportedblockedunknown | |
app | string | 小写应用代码(例如 | |
ios | string |
supportedblockedunknown | |
note | string | 可为 null | — |
hotspot | boolean | 可为 null | 向其他设备共享 Wi-Fi。 |
kyc_required | boolean | 可为 null | 使用前需要身份验证(KYC)。 |
sms | boolean | 可为 null | 短信功能。 |
voice | boolean | 可为 null | 语音通话。 |
fup | object | 可为 null | 高速流量耗尽后的处理方式。 |
behavior | string | 可为 null |
throttlecutoffnull |
high_speed_bytes | integer · int64 | 可为 null | 开始限速前可全速使用的字节数。 |
note | string | 可为 null | — |
speed_kbps | integer | 可为 null | 高速额度用尽后的速率(kbps)。断网或未声明时为 |
market | string | 套餐的供应系统,为可扩展枚举,客户端必须忽略未知值。它决定是否有库存及可用售后操作: domesticinternational | |
name | string | — | |
name_en | string | 可为 null | 英文名称,尚未提供时为 |
network | object | 套餐可用的网络。 | |
apn | string | 可为 null | 某些无法自动配置的 Android 设备需要手动输入的 APN。此信息用于编写安装指南,否则每次都会变成客服咨询。 |
carriers | object[] | 套餐实际使用的运营商网络。这是 eSIM 的无线网络规格,并非供应商。 | |
name | string | — | |
generations | string[] | 可为 null | 套餐可使用的网络代际( |
speed_cap_kbps | integer | 可为 null | 整个套餐的速率上限(kbps),不同于高速额度用尽后适用的 |
price | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
tags | string[] | 规范化的商业标签(小写、使用连字符),也用于匹配密钥的目录限制。目前没有套餐带标签,因此在卖方开始添加标签之前, | |
validity | object | 套餐有效期及开始计时的条件。 | |
days | integer | — | |
install_by_days | integer | 可为 null | 购买后可扫描二维码或安装 eSIM 的天数。 |
label | string | — | |
reclaim_on_expiry | boolean | 可为 null | 供应商在套餐到期时回收订阅,此后不能加购或换套餐。销售续费时需了解此窗口。 |
starts_when | string | 可为 null | 计时起点: on_installon_purchasenull |
unused_valid_days | integer | 可为 null | 套餐未使用时可存放至过期的天数。 |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
next_cursor | string | 可为 null | 获取下一页时请原样传回。 |
page_size | integer | 可为 null | 服务器用于本页的最大记录数,已应用上限,并非 |
total | integer · int64 | 可为 null | 匹配筛选条件的套餐总数。集合较大、计数成本高时(国际套餐或无 |
warnings | object[] | 列表呈现方式的原因;无异常时为空。封闭代码集: | |
code | string | —filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing | |
count | integer · int64 | 可为 null | — |
message | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedinternal.invalid_filtercatalog.cursor_mismatchpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}/v1/catalog/packages/{code}获取单个套餐
catalog:readget_catalog_packages__code_所需权限范围: catalog:read.
按公开代码获取一个套餐的详情。data 的字段与 GET /v1/catalog/packages 单项相同,仅增加 mode;没有详情专属字段,因此只需定义一个 Package 类型。
无权查看的代码统一返回 partner.package_not_visible(404),无论原因是代码不存在、超出密钥目录限制、组织未定价或套餐失去供应关联。区分这些原因会让外部人员枚举整个目录。
路径参数 (1)
codestring必填套餐代码,即目录中的 code(public_sku)。每个套餐不可变,更换底层供应商时不变,可保存为对账键。超出密钥目录限制或组织未定价的代码,与不存在的代码一样返回 404 partner.package_not_visible。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedpartner.package_not_visiblepartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"data": null,
"ok": true
}订单
下单及对账
/v1/orders列出订单(主动查询式对账)
orders:readget_orders所需权限范围: orders:read.
查询参数 (5)
page_sizeinteger选填默认值 50min 1max 200每页记录数,默认 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。畸形游标不会报错,而会从列表开头读取,以兼容游标编码变更。请确认新游标与刚发送的值不同,避免无限循环读取第一页。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
items | object[] | — | |
created_at | string · date-time | — | |
external_ref | string | 可为 null | — |
fulfillment_status | string | —fulfilledpartially_fulfilledunfulfilled | |
id | string · uuid | — | |
item_count | integer · int64 | — | |
net | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
public_ref | string | 可为 null | — |
refunded | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
status | string | — | |
total | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
updated_at | string · date-time | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
next_cursor | string | 可为 null | 获取下一页时请原样传回。 |
page_size | integer | 可为 null | 服务器用于本页的最大记录数,已应用上限,并非 |
total | integer · int64 | 可为 null | 符合筛选条件的记录数量。统计成本过高时为 |
warnings | object[] | 列表呈现方式的原因;无异常时为空。封闭代码集: | |
code | string | —filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing | |
count | integer · int64 | 可为 null | — |
message | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedinternal.invalid_filterpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}/v1/orders创建订单(直接购买)
orders:write必须提供 Idempotency-Keypost_orders所需权限范围: orders:write.
请求头 (1)
Idempotency-Keystring必填客户端生成的字符串:相同密钥和请求体只执行一次,重试返回原结果。范围为 api_key_id(§11),不同密钥属于不同命令。
请求体必填application/json
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
external_ref | string | 可为 null | 您的自定义引用代码,会原样回传至响应和 Webhook。 |
include | string[] | 可为 null | 请求额外区块: |
invoice_buyer | object | 可为 null | 仅适用于会员密钥。未填写时使用消费者流程,无需组织或越南法人。填写时按现有个人规则验证full_name、12位个人tax_code及结账address/email规则。企业发票在购买后申请。测试模式只验证快照,不签发MISA发票。 |
address | string | 可为 null | — |
email | string | 可为 null | — |
full_name | string | 可为 null | — |
legal_name | string | 可为 null | — |
tax_code | string | 可为 null | — |
items | object[] | 必填 | 待购买套餐及数量列表(最多 50 个 eSIM)。 |
package_code | string | 必填 | 您目录中的套餐代码,即 |
quantity | integer | 必填 | 此套餐要购买的 eSIM 数量(≥ 1)。 |
响应
24 小时内使用相同 Idempotency-Key 和请求体重放:响应体与首次完全相同,不重复扣款,并添加 Idempotent-Replayed: true。新建返回 201,请勿仅凭此状态码区分成功。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | 合作伙伴订单。 |
created_at | string · date-time | — | |
external_ref | string | 可为 null | — |
fulfillment_status | string | 实际交付情况,与 fulfilledpartially_fulfilledunfulfilled | |
id | string · uuid | 订单 ID(UUID)。 | |
idempotent_replay | boolean | 可为 null | 此请求为先前成功操作的幂等重放时为真。 |
invoice_no | string | 可为 null | 开具后的发票号码。 |
invoice_status | string | 订单的增值税发票状态。 nonependingissuingissuedfailedcancelled | |
items | object[] | — | |
cancellable | object | eSIM 是否仍可取消及原因,请在调用 | |
allowed | boolean | — | |
disclosed_at | string · date-time | 可为 null | 代码离开系统的时间(ISO-8601 UTC),无人查看时为 |
reason | string | 可为 null | 不可取消原因: code_disclosedwrong_statusexpirednot_supportednull |
external_ref | string | 可为 null | 您的订单引用(下单时发送的 |
iccid | string | 可为 null | — |
id | string · uuid | eSIM ID,用于所有 | |
install | object | 可为 null | 安装此 eSIM 所需的全部信息。 包含此对象的响应始终带有 |
android_url | string | 可为 null | — |
apn | string | 可为 null | 设备无法自动获取配置时需输入的接入点名称(APN)。当前版本始终为 |
ios_url | string | 可为 null | — |
lpa | string | 可为 null | eSIM 激活码,属于可销售的机密。仅凭此字符串即可在您的系统生成二维码。 |
matching_id | string | 可为 null | — |
qr_code_base64 | string | 可为 null | 二维码的 PNG data-URI。仅在详情端点请求 |
smdp_address | string | 可为 null | — |
msisdn | string | 可为 null | — |
order_id | string · uuid | — | |
package_code | string | 可为 null | 目录中的套餐代码,用于将此 eSIM 对应回您的目录。仅当源套餐已从目录移除时为 |
package_name | string | 供人阅读、可能变化的显示名称。请勿用作对账键。 | |
plan | object | 可为 null | 此 eSIM 当前使用的套餐。 |
current_code | string | — | |
expires_at | string · date-time | 可为 null | — |
started_at | string · date-time | 可为 null | — |
smdp_status | string | 可为 null | — |
status | string | — | |
updated_at | string · date-time | — | |
usage | object | 可为 null | eSIM 流量使用统计,从未查询过时 |
expires_at | string · date-time | 可为 null | — |
remaining_bytes | integer · int64 | 可为 null | — |
source | string | 可为 null | —pollwebhook |
total_bytes | integer · int64 | 可为 null | — |
updated_at | string · date-time | 可为 null | — |
used_bytes | integer · int64 | 可为 null | — |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
money_settled | boolean | 订单资金是否已结算(无处理中退款)。 | |
net | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
public_ref | string | 可为 null | 简短易读的订单编号,提交支持工单时使用。 |
refunded | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
status | string | —completedpending_providerprovider_failedcancelled | |
total | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
ok | boolean | 必填 | —true |
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | 合作伙伴订单。 |
created_at | string · date-time | — | |
external_ref | string | 可为 null | — |
fulfillment_status | string | 实际交付情况,与 fulfilledpartially_fulfilledunfulfilled | |
id | string · uuid | 订单 ID(UUID)。 | |
idempotent_replay | boolean | 可为 null | 此请求为先前成功操作的幂等重放时为真。 |
invoice_no | string | 可为 null | 开具后的发票号码。 |
invoice_status | string | 订单的增值税发票状态。 nonependingissuingissuedfailedcancelled | |
items | object[] | — | |
cancellable | object | eSIM 是否仍可取消及原因,请在调用 | |
allowed | boolean | — | |
disclosed_at | string · date-time | 可为 null | 代码离开系统的时间(ISO-8601 UTC),无人查看时为 |
reason | string | 可为 null | 不可取消原因: code_disclosedwrong_statusexpirednot_supportednull |
external_ref | string | 可为 null | 您的订单引用(下单时发送的 |
iccid | string | 可为 null | — |
id | string · uuid | eSIM ID,用于所有 | |
install | object | 可为 null | 安装此 eSIM 所需的全部信息。 包含此对象的响应始终带有 |
android_url | string | 可为 null | — |
apn | string | 可为 null | 设备无法自动获取配置时需输入的接入点名称(APN)。当前版本始终为 |
ios_url | string | 可为 null | — |
lpa | string | 可为 null | eSIM 激活码,属于可销售的机密。仅凭此字符串即可在您的系统生成二维码。 |
matching_id | string | 可为 null | — |
qr_code_base64 | string | 可为 null | 二维码的 PNG data-URI。仅在详情端点请求 |
smdp_address | string | 可为 null | — |
msisdn | string | 可为 null | — |
order_id | string · uuid | — | |
package_code | string | 可为 null | 目录中的套餐代码,用于将此 eSIM 对应回您的目录。仅当源套餐已从目录移除时为 |
package_name | string | 供人阅读、可能变化的显示名称。请勿用作对账键。 | |
plan | object | 可为 null | 此 eSIM 当前使用的套餐。 |
current_code | string | — | |
expires_at | string · date-time | 可为 null | — |
started_at | string · date-time | 可为 null | — |
smdp_status | string | 可为 null | — |
status | string | — | |
updated_at | string · date-time | — | |
usage | object | 可为 null | eSIM 流量使用统计,从未查询过时 |
expires_at | string · date-time | 可为 null | — |
remaining_bytes | integer · int64 | 可为 null | — |
source | string | 可为 null | —pollwebhook |
total_bytes | integer · int64 | 可为 null | — |
updated_at | string · date-time | 可为 null | — |
used_bytes | integer · int64 | 可为 null | — |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
money_settled | boolean | 订单资金是否已结算(无处理中退款)。 | |
net | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
public_ref | string | 可为 null | 简短易读的订单编号,提交支持工单时使用。 |
refunded | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
status | string | —completedpending_providerprovider_failedcancelled | |
total | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedinternal.invalid_filterpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedwallet.insufficient_balancepartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedpartner.package_not_visibleesim.out_of_stockidempotency.conflictinvoice.buyer_invalidpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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"响应示例
{
"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
}请求体示例
{
"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
}
]
}/v1/orders/{id}订单详情及 eSIM
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")。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | 合作伙伴订单。 |
created_at | string · date-time | — | |
external_ref | string | 可为 null | — |
fulfillment_status | string | 实际交付情况,与 fulfilledpartially_fulfilledunfulfilled | |
id | string · uuid | 订单 ID(UUID)。 | |
idempotent_replay | boolean | 可为 null | 此请求为先前成功操作的幂等重放时为真。 |
invoice_no | string | 可为 null | 开具后的发票号码。 |
invoice_status | string | 订单的增值税发票状态。 nonependingissuingissuedfailedcancelled | |
items | object[] | — | |
cancellable | object | eSIM 是否仍可取消及原因,请在调用 | |
allowed | boolean | — | |
disclosed_at | string · date-time | 可为 null | 代码离开系统的时间(ISO-8601 UTC),无人查看时为 |
reason | string | 可为 null | 不可取消原因: code_disclosedwrong_statusexpirednot_supportednull |
external_ref | string | 可为 null | 您的订单引用(下单时发送的 |
iccid | string | 可为 null | — |
id | string · uuid | eSIM ID,用于所有 | |
install | object | 可为 null | 安装此 eSIM 所需的全部信息。 包含此对象的响应始终带有 |
android_url | string | 可为 null | — |
apn | string | 可为 null | 设备无法自动获取配置时需输入的接入点名称(APN)。当前版本始终为 |
ios_url | string | 可为 null | — |
lpa | string | 可为 null | eSIM 激活码,属于可销售的机密。仅凭此字符串即可在您的系统生成二维码。 |
matching_id | string | 可为 null | — |
qr_code_base64 | string | 可为 null | 二维码的 PNG data-URI。仅在详情端点请求 |
smdp_address | string | 可为 null | — |
msisdn | string | 可为 null | — |
order_id | string · uuid | — | |
package_code | string | 可为 null | 目录中的套餐代码,用于将此 eSIM 对应回您的目录。仅当源套餐已从目录移除时为 |
package_name | string | 供人阅读、可能变化的显示名称。请勿用作对账键。 | |
plan | object | 可为 null | 此 eSIM 当前使用的套餐。 |
current_code | string | — | |
expires_at | string · date-time | 可为 null | — |
started_at | string · date-time | 可为 null | — |
smdp_status | string | 可为 null | — |
status | string | — | |
updated_at | string · date-time | — | |
usage | object | 可为 null | eSIM 流量使用统计,从未查询过时 |
expires_at | string · date-time | 可为 null | — |
remaining_bytes | integer · int64 | 可为 null | — |
source | string | 可为 null | —pollwebhook |
total_bytes | integer · int64 | 可为 null | — |
updated_at | string · date-time | 可为 null | — |
used_bytes | integer · int64 | 可为 null | — |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
money_settled | boolean | 订单资金是否已结算(无处理中退款)。 | |
net | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
public_ref | string | 可为 null | 简短易读的订单编号,提交支持工单时使用。 |
refunded | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
status | string | —completedpending_providerprovider_failedcancelled | |
total | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedinternal.invalid_filterpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedinternal.not_foundpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}/v1/orders/{id}/resend重新发送订单邮件/二维码
orders:writepost_orders__id__resend所需权限范围: orders:write.
路径参数 (1)
idstring必填订单 ID(UUID)。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
id | string · uuid | 刚刚重新发送的订单 ID。 | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
resent_at | string · date-time | — | |
resent_to | string | 部分隐藏的收件地址,合作伙伴接口不会重新返回客户的完整邮箱。 | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedorder.not_deliverablepartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"data": {
"id": "018f2b00-0000-7000-8000-00000000009a",
"mode": "live",
"resent_at": "2026-07-11T08:12:30Z",
"resent_to": "ab***@x.com"
},
"ok": true
}/v1/orders/bulk提交多行批量订单(每行一个订单)
orders:write必须提供 Idempotency-Keypost_orders_bulk所需权限范围: orders:write.
提交多行批次,每行独立生成一个订单,执行与 POST /v1/orders 相同的 quote→commit。
部分成功:失败行不阻止其他行,只扣成功行款项。缺货、余额不足、套餐不可售、触发防滥用限制等业务错误位于 lines[].error,不影响批次整体 HTTP 状态。中途余额不足仍尝试后续行,因为较便宜的套餐可能仍可购买。
状态始终为 200:结果是逐行混合结果而非单一新资源,故不是 201;批次在请求内处理完成,不使用 202 加轮询。
相同 Idempotency-Key 加相同请求体再次调用,将加载旧批次、原样返回已完成行,仅继续处理 pending 行,不重复扣款。未执行任何行时附带 Idempotent-Replayed: true。同密钥但请求体不同则为 idempotency.conflict。
同一组织在 10 分钟内提交内容相同的批次,即使幂等键不同,也视为误点重复提交:返回旧批次并带 Idempotent-Replayed: true,不再扣款。若确需为另一客户购买相同商品,请修改 external_ref;它属于签名内容,可区分批次并用于后续对账。全部失败、未产生任何订单的批次不会受此限制,超过 10 分钟也可正常重购。
行级 external_ref 原样返回于 lines[].external_ref,批次级参考编号返回于响应顶部。
响应不包含 LPA/QR,请按各 order_id 从 GET /v1/orders/{order_id} 获取。
请求头 (1)
Idempotency-Keystring必填客户端生成的字符串:相同密钥和请求体只执行一次,重试返回原结果。范围为 api_key_id(§11),不同密钥属于不同命令。
请求体必填application/json
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
external_ref | string | 可为 null | 整个批次的参考编号,会在批次响应中返回。 |
items | object[] | 必填 | 每个条目创建一个独立订单。行数上限可配置(默认 100),超出返回 |
external_ref | string | 可为 null | 仅此行的参考编号,会在该行结果中原样返回。 |
package_code | string | 必填 | 您目录中的套餐代码,即 |
quantity | integer | 必填 | — |
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | 批量订单结果。部分成功:失败行不阻止其他行,仅对 |
created_at | string · date-time | — | |
external_ref | string | 可为 null | — |
failed_lines | integer | — | |
id | string · uuid | — | |
items | object[] | — | |
charged | object | 可为 null | — |
error | object | 可为 null | 实际的 |
code | string | — | |
message | string | — | |
external_ref | string | 可为 null | — |
line_no | integer | 从 1 开始,与提交顺序完全一致。 | |
order_id | string · uuid | 可为 null | — |
package_code | string | — | |
quantity | integer | — | |
status | string | —pendingdonefailed | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
status | string |
pendingcompletedpartialfailed | |
succeeded_lines | integer | — | |
total_charged | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
total_lines | integer | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedpartner.package_not_visibleidempotency.conflictinternal.limit_exceededpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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"响应示例
{
"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
}请求体示例
{
"external_ref": "batch-2026-001",
"items": [
{
"external_ref": "po-1001",
"package_code": "TKE-VN-30D-X3K9F",
"quantity": 5
}
]
}/v1/orders/bulk/{id}批量订单结果
orders:readget_orders_bulk__id_所需权限范围: orders:read.
重新读取已提交批次的逐行结果,可在原始响应丢失时恢复,无须重发请求体。其他组织或其他环境(正式/测试)的批次返回 404。
路径参数 (1)
idstring必填POST /v1/orders/bulk 返回的批次 ID(UUID)。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | 批量订单结果。部分成功:失败行不阻止其他行,仅对 |
created_at | string · date-time | — | |
external_ref | string | 可为 null | — |
failed_lines | integer | — | |
id | string · uuid | — | |
items | object[] | — | |
charged | object | 可为 null | — |
error | object | 可为 null | 实际的 |
code | string | — | |
message | string | — | |
external_ref | string | 可为 null | — |
line_no | integer | 从 1 开始,与提交顺序完全一致。 | |
order_id | string · uuid | 可为 null | — |
package_code | string | — | |
quantity | integer | — | |
status | string | —pendingdonefailed | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
status | string |
pendingcompletedpartialfailed | |
succeeded_lines | integer | — | |
total_charged | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
total_lines | integer | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedinternal.not_foundpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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 记录、用量、加购及取消
/v1/esims列出 eSIM(主动查询式对账)
esims:readget_esims所需权限范围: esims:read.
查询参数 (8)
page_sizeinteger选填默认值 50min 1max 200每页记录数,默认 50,上限 200;超过上限时限制为 200,不报错。
statusstring选填pendingavailablereservedsolddeliveredin_useused_upexpiredsuspendedcancelledprovider_failed按 esim_status 筛选。列表之外的值返回 internal.invalid_filter(400),而非空列表,以免将拼写错误(如 cancelled 少写一个 l 的 canceled)误认为该客户没有此状态的 eSIM。
order_idstring · uuid选填仅查询同一订单的 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")。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
items | object[] | — | |
cancellable | object | eSIM 是否仍可取消及原因,请在调用 | |
allowed | boolean | — | |
disclosed_at | string · date-time | 可为 null | 代码离开系统的时间(ISO-8601 UTC),无人查看时为 |
reason | string | 可为 null | 不可取消原因: code_disclosedwrong_statusexpirednot_supportednull |
external_ref | string | 可为 null | 您的订单引用(下单时发送的 |
iccid | string | 可为 null | — |
id | string · uuid | eSIM ID,用于所有 | |
install | object | 可为 null | 安装此 eSIM 所需的全部信息。 包含此对象的响应始终带有 |
android_url | string | 可为 null | — |
apn | string | 可为 null | 设备无法自动获取配置时需输入的接入点名称(APN)。当前版本始终为 |
ios_url | string | 可为 null | — |
lpa | string | 可为 null | eSIM 激活码,属于可销售的机密。仅凭此字符串即可在您的系统生成二维码。 |
matching_id | string | 可为 null | — |
qr_code_base64 | string | 可为 null | 二维码的 PNG data-URI。仅在详情端点请求 |
smdp_address | string | 可为 null | — |
msisdn | string | 可为 null | — |
order_id | string · uuid | — | |
package_code | string | 可为 null | 目录中的套餐代码,用于将此 eSIM 对应回您的目录。仅当源套餐已从目录移除时为 |
package_name | string | 供人阅读、可能变化的显示名称。请勿用作对账键。 | |
plan | object | 可为 null | 此 eSIM 当前使用的套餐。 |
current_code | string | — | |
expires_at | string · date-time | 可为 null | — |
started_at | string · date-time | 可为 null | — |
smdp_status | string | 可为 null | — |
status | string | — | |
updated_at | string · date-time | — | |
usage | object | 可为 null | eSIM 流量使用统计,从未查询过时 |
expires_at | string · date-time | 可为 null | — |
remaining_bytes | integer · int64 | 可为 null | — |
source | string | 可为 null | —pollwebhook |
total_bytes | integer · int64 | 可为 null | — |
updated_at | string · date-time | 可为 null | — |
used_bytes | integer · int64 | 可为 null | — |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
next_cursor | string | 可为 null | 获取下一页时请原样传回。 |
page_size | integer | 可为 null | 服务器用于本页的最大记录数,已应用上限,并非 |
total | integer · int64 | 可为 null | 符合筛选条件的记录数量。统计成本过高时为 |
warnings | object[] | 列表呈现方式的原因;无异常时为空。封闭代码集: | |
code | string | —filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing | |
count | integer · int64 | 可为 null | — |
message | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedinternal.invalid_filterpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}/v1/esims/{id}获取单个 eSIM
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")。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
cancellable | object | eSIM 是否仍可取消及原因,请在调用 | |
allowed | boolean | — | |
disclosed_at | string · date-time | 可为 null | 代码离开系统的时间(ISO-8601 UTC),无人查看时为 |
reason | string | 可为 null | 不可取消原因: code_disclosedwrong_statusexpirednot_supportednull |
external_ref | string | 可为 null | 您的订单引用(下单时发送的 |
iccid | string | 可为 null | — |
id | string · uuid | eSIM ID,用于所有 | |
install | object | 可为 null | 安装此 eSIM 所需的全部信息。 包含此对象的响应始终带有 |
android_url | string | 可为 null | — |
apn | string | 可为 null | 设备无法自动获取配置时需输入的接入点名称(APN)。当前版本始终为 |
ios_url | string | 可为 null | — |
lpa | string | 可为 null | eSIM 激活码,属于可销售的机密。仅凭此字符串即可在您的系统生成二维码。 |
matching_id | string | 可为 null | — |
qr_code_base64 | string | 可为 null | 二维码的 PNG data-URI。仅在详情端点请求 |
smdp_address | string | 可为 null | — |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
msisdn | string | 可为 null | — |
order_id | string · uuid | — | |
package_code | string | 可为 null | 目录中的套餐代码,用于将此 eSIM 对应回您的目录。仅当源套餐已从目录移除时为 |
package_name | string | 供人阅读、可能变化的显示名称。请勿用作对账键。 | |
plan | object | 可为 null | 此 eSIM 当前使用的套餐。 |
current_code | string | — | |
expires_at | string · date-time | 可为 null | — |
started_at | string · date-time | 可为 null | — |
smdp_status | string | 可为 null | — |
status | string | — | |
updated_at | string · date-time | — | |
usage | object | 可为 null | eSIM 流量使用统计,从未查询过时 |
expires_at | string · date-time | 可为 null | — |
remaining_bytes | integer · int64 | 可为 null | — |
source | string | 可为 null | —pollwebhook |
total_bytes | integer · int64 | 可为 null | — |
updated_at | string · date-time | 可为 null | — |
used_bytes | integer · int64 | 可为 null | — |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedinternal.invalid_filterpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedinternal.not_foundpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}/v1/esims/{id}/cancel取消未使用的 eSIM
esims:write必须提供 Idempotency-Keypost_esims__id__cancel所需权限范围: esims:write.
路径参数 (1)
idstring必填已售 eSIM 的稳定 ID,不是可能复用的 ICCID。
请求头 (1)
Idempotency-Keystring必填客户端生成的字符串:相同密钥和请求体只执行一次,重试返回原结果。范围为 api_key_id(§11),不同密钥属于不同命令。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
cancelled_at | string · date-time | — | |
esim_id | string · uuid | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
refund_suggested | boolean |
| |
refunded | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
status | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedesim.not_cancellableidempotency.conflictcapability.not_supportedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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)"响应示例
{
"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
}/v1/esims/{id}/change-plan为 eSIM 加购
esims:write必须提供 Idempotency-Keypost_esims__id__change-plan所需权限范围: esims:write.
路径参数 (1)
idstring必填已售 eSIM 的稳定 ID,不是可能复用的 ICCID。
请求头 (1)
Idempotency-Keystring必填客户端生成的字符串:相同密钥和请求体只执行一次,重试返回原结果。范围为 api_key_id(§11),不同密钥属于不同命令。
请求体必填application/json
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
package_code | string | 必填 | 您目录中的套餐代码,即 |
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | eSIM 更换套餐的结果。 |
charged | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
current_plan | object | — | |
code | string | — | |
expires_at | string · date-time | 可为 null | — |
started_at | string · date-time | 可为 null | — |
esim_id | string · uuid | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
order_id | string · uuid | — | |
previous_plan | object | 可为 null | — |
cancelled_at | string · date-time | 可为 null | — |
code | string | — | |
remaining_bytes_forfeited | integer · int64 | 可为 null | — |
warning | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedwallet.insufficient_balancepartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedpartner.package_not_visibleesim.topup_not_supportedesim.topup_provider_mismatchesim.not_eligibleidempotency.conflictcapability.not_supportedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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"响应示例
{
"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
}请求体示例
{
"package_code": "TKE-VN-7D-P4M2Q"
}/v1/esims/{id}/plan-options此 eSIM 可用的加购套餐
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每页记录数,默认 50,上限 200;超过上限时限制为 200,不报错。
cursorstring选填下一页游标,请原样传回上一页的 next_cursor。畸形游标不会报错,而会从列表开头读取,以兼容游标编码变更。请确认新游标与刚发送的值不同,避免无限循环读取第一页。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | 可为此 eSIM 加购的套餐,已按当前供应商筛选。每项均为完整 |
items | object[] | — | |
capabilities | object | 套餐售后能力取自套餐实际声明,不根据供应商类型推断。未声明时所有标志为 | |
cancel | object | — | |
restriction | string | 可为 null |
code_not_disclosednull |
supported | boolean | — | |
plan_change | object | — | |
policy | object | 可为 null | 此供应商追加新套餐时的处理方式。 |
… | … | 还有更深层字段,请查看 JSON 示例。 | |
supported | boolean | — | |
usage_check | object | — | |
supported | boolean | — | |
code | string | 您目录中的套餐代码,即 | |
coverage | object | 套餐可用地区。 | |
countries | string[] | ISO-3166 alpha-2 国家代码。全球套餐不逐一列出 200 个国家;全球套餐及未声明覆盖范围的套餐返回空数组。 | |
country_count | integer | 套餐覆盖的国家数量,可据此排序或筛选多国套餐,无须获取全部数据后自行统计数组。 | |
group | string | 覆盖范围为国家列表( | |
region | string | 可为 null | 始终为 |
data | object | 套餐流量额度,所有数值均以字节表示,而非 MB/GB,以避免重复舍入。 | |
daily_bytes | integer · int64 | 可为 null | 每日流量额度,单位为字节。 |
label | string | 由所有界面共用的函数生成的可读标签。 | |
model | string | 流量计算方式: dailyfixedunlimited | |
reset | object | 可为 null | 每日额度重置时间。深夜购买时会影响首日可用时间,属于销售信息。 |
at | string | 可为 null | 按 |
note | string | 可为 null | — |
timezone | string | 可为 null | 重置时点的时区( |
total_bytes | integer · int64 | 可为 null | 整个周期总流量(字节)。 |
description | string | 可为 null | 套餐销售说明,尚未填写时为 |
description_en | string | 可为 null | 英文描述,尚未提供时为 |
features | object | 套餐能力采用带类型对象而非代码数组: | |
apps | object[] | 按操作系统区分的应用支持状态。 数组中不存在的应用表示信息未知,并非“支持”。 仅已列出的条目属于供应商承诺;目前只声明了 TikTok。 有意不提供合并字段:真实目录中有 2,465 个套餐支持 iPhone 上的 TikTok,但不支持 Android。一个合并标记会将其全部归为“不支持”,从而误判近三分之一的目录。 | |
android | string |
supportedblockedunknown | |
app | string | 小写应用代码(例如 | |
ios | string |
supportedblockedunknown | |
note | string | 可为 null | — |
hotspot | boolean | 可为 null | 向其他设备共享 Wi-Fi。 |
kyc_required | boolean | 可为 null | 使用前需要身份验证(KYC)。 |
sms | boolean | 可为 null | 短信功能。 |
voice | boolean | 可为 null | 语音通话。 |
fup | object | 可为 null | 高速流量耗尽后的处理方式。 |
behavior | string | 可为 null |
throttlecutoffnull |
high_speed_bytes | integer · int64 | 可为 null | 开始限速前可全速使用的字节数。 |
note | string | 可为 null | — |
speed_kbps | integer | 可为 null | 高速额度用尽后的速率(kbps)。断网或未声明时为 |
market | string | 套餐的供应系统,为可扩展枚举,客户端必须忽略未知值。它决定是否有库存及可用售后操作: domesticinternational | |
name | string | — | |
name_en | string | 可为 null | 英文名称,尚未提供时为 |
network | object | 套餐可用的网络。 | |
apn | string | 可为 null | 某些无法自动配置的 Android 设备需要手动输入的 APN。此信息用于编写安装指南,否则每次都会变成客服咨询。 |
carriers | object[] | 套餐实际使用的运营商网络。这是 eSIM 的无线网络规格,并非供应商。 | |
name | string | — | |
generations | string[] | 可为 null | 套餐可使用的网络代际( |
speed_cap_kbps | integer | 可为 null | 整个套餐的速率上限(kbps),不同于高速额度用尽后适用的 |
price | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
tags | string[] | 规范化的商业标签(小写、使用连字符),也用于匹配密钥的目录限制。目前没有套餐带标签,因此在卖方开始添加标签之前, | |
validity | object | 套餐有效期及开始计时的条件。 | |
days | integer | — | |
install_by_days | integer | 可为 null | 购买后可扫描二维码或安装 eSIM 的天数。 |
label | string | — | |
reclaim_on_expiry | boolean | 可为 null | 供应商在套餐到期时回收订阅,此后不能加购或换套餐。销售续费时需了解此窗口。 |
starts_when | string | 可为 null | 计时起点: on_installon_purchasenull |
unused_valid_days | integer | 可为 null | 套餐未使用时可存放至过期的天数。 |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
next_cursor | string | 可为 null | 获取下一页时请原样传回。 |
page_size | integer | 服务器用于本页的最大记录数,已应用上限,并非 | |
policy | object | 可为 null | 此供应商追加新套餐时的处理方式。 |
note | string | 可为 null | — |
requires_cancel_first | boolean | 新套餐下单前会取消正在使用的套餐,因为此供应商不叠加套餐。请在客户点击追加新套餐按钮之前告知。 | |
stacking | boolean | 新套餐的有效期和额度是否叠加到当前套餐。 | |
total | integer · int64 | 可为 null | 匹配筛选条件的套餐总数。集合较大、计数成本高时(国际套餐或无 |
warnings | object[] | 列表呈现方式的原因;无异常时为空。封闭代码集: | |
code | string | —filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing | |
count | integer · int64 | 可为 null | — |
message | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedinternal.not_foundpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}/v1/esims/{id}/refund-requestseSIM 退款申请记录(仅限会员)
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。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
has_open_request | boolean | — | |
items | object[] | — | |
decided_at | string · date-time | 可为 null | — |
decision_note | string | 可为 null | — |
id | string · uuid | — | |
order_id | string · uuid | — | |
order_item_id | string · uuid | — | |
reason | string | — | |
refunded | object | 可为 null | — |
requested_at | string · date-time | — | |
status | string | —pendingapprovedrejected | |
suggested | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
next_cursor | string | 可为 null | 获取下一页时请原样传回。 |
page_size | integer | 可为 null | 服务器用于本页的最大记录数,已应用上限,并非 |
total | integer · int64 | 可为 null | 符合筛选条件的记录数量。统计成本过高时为 |
warnings | object[] | 列表呈现方式的原因;无异常时为空。封闭代码集: | |
code | string | —filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing | |
count | integer · int64 | 可为 null | — |
message | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedinternal.not_foundcapability.not_supportedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}/v1/esims/{id}/refund-requests创建 eSIM 退款申请(仅限会员)
esims:write必须提供 Idempotency-Keypost_esims__id__refund-requests所需权限范围: esims:write.
仅限已授权的正式会员密钥。使用Idempotency-Key为会员自己的eSIM提交退款申请,管理员批准前不转移资金。组织及测试密钥返回capability.not_supported。测试模式请取消eSIM以验证虚拟钱包退款。
路径参数 (1)
idstring必填已售 eSIM 的稳定 ID,不是可能复用的 ICCID。
请求头 (1)
Idempotency-Keystring必填客户端生成的字符串:相同密钥和请求体只执行一次,重试返回原结果。范围为 api_key_id(§11),不同密钥属于不同命令。
请求体必填application/json
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
reason | string | 必填 | 退款理由,去除首尾空白后为 5 至 1000 个字符。 |
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
decided_at | string · date-time | 可为 null | — |
decision_note | string | 可为 null | — |
id | string · uuid | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
order_id | string · uuid | — | |
order_item_id | string · uuid | — | |
reason | string | — | |
refunded | object | 可为 null | — |
requested_at | string · date-time | — | |
status | string | —pendingapprovedrejected | |
suggested | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedinternal.not_foundesim.refund_not_eligibleesim.refund_request_pendingidempotency.conflictcapability.not_supportedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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"响应示例
{
"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
}请求体示例
{
"reason": "<reason>"
}/v1/esims/{id}/usage已使用流量
esims:readget_esims__id__usage所需权限范围: esims:read.
读取 eSIM 的已用与剩余流量,并附带数据时间戳 updated_at(真实新鲜度)。对于仅按需查询的供应商(目前为 SkyFi)的 eSIM,此调用会将一次扫描加入队列并最多等待约 15 秒获取结果,因此响应最长可能需要 ~15 秒,返回的数据来自刚完成的那次扫描。若扫描失败、同一 eSIM 距上次扫描不足 15 秒或等待超时,不会返回错误,而是返回最近保存的数据,请查看 updated_at。其他供应商返回定期更新的已保存数据。
路径参数 (1)
idstring必填已售 eSIM 的稳定 ID,不是可能复用的 ICCID。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
esim_id | string · uuid | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
usage | object | 可为 null | eSIM 流量使用统计,从未查询过时 |
expires_at | string · date-time | 可为 null | — |
remaining_bytes | integer · int64 | 可为 null | — |
source | string | 可为 null | —pollwebhook |
total_bytes | integer · int64 | 可为 null | — |
updated_at | string · date-time | 可为 null | — |
used_bytes | integer · int64 | 可为 null | — |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedcapability.not_supportedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}钱包
钱包余额
/v1/wallet/balance钱包余额
wallet:readget_wallet_balance所需权限范围: wallet:read.
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
available | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
balance | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
credit_limit | object | 金额。 | |
amount | integer · int64 | 以 | |
currency | string | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"data": {
"available": {
"amount": 273000,
"currency": "VND"
},
"balance": {
"amount": 273000,
"currency": "VND"
},
"credit_limit": {
"amount": 273000,
"currency": "VND"
},
"mode": "live"
},
"ok": true
}Webhook
Webhook 配置、投递日志及模拟器
/v1/testmode/webhooks/fail-next模拟下一次 webhook 失败(仅限测试密钥)
webhook:managepost_testmode_webhooks_fail-next所需权限范围: webhook:manage.
请求体必填application/json
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
count | integer | — |
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
endpoint_id | string · uuid | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
testmode_fail_next | integer | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbiddeninternal.not_foundpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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"响应示例
{
"data": {
"endpoint_id": "018f2b00-0000-7000-8000-000000000000",
"mode": "live",
"testmode_fail_next": 1
},
"ok": true
}请求体示例
{
"count": 1
}/v1/testmode/webhooks/fire发送测试 webhook 事件(仅限测试密钥)
webhook:managepost_testmode_webhooks_fire所需权限范围: webhook:manage.
请求体必填application/json
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 部分覆盖示例载荷中的 | |
event_type | string | 必填 | 要模拟触发的 Webhook 事件类型。 order.completedorder.failedesim.deliveredesim.activatedesim.usage_thresholdesim.expiringwallet.low_balancecatalog.updated |
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
delivery_id | string · uuid | — | |
event_id | string · uuid | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbiddenwebhook.not_configuredinternal.not_foundpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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"响应示例
{
"data": {
"delivery_id": "018f2b00-0000-7000-8000-000000000000",
"event_id": "018f3c00-0000-7000-8000-0000000000b0",
"mode": "live"
},
"ok": true
}请求体示例
{
"data": {},
"event_type": "order.completed"
}/v1/webhooks列出 webhook 端点
webhook:manageget_webhooks所需权限范围: webhook:manage.
仅返回调用 API 密钥的端点。密钥绝不查看其他密钥的端点,即使两个密钥属于同一组织(§5.11:绑定于 api_key_id,测试与正式环境不共享)。
尚未配置时返回 200 和空数组,而非 404;集合始终存在,只是当前没有元素。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
items | object[] | — | |
active | boolean |
| |
created_at | string · date-time | — | |
events | string[] | 为空表示接收全部。 | |
id | string · uuid | 端点 ID,用于 | |
last_delivery_at | string · date-time | 可为 null | 通过此端点最后投递的时间。 |
secret_last4 | string | Webhook 密钥的末四个字符,可用于核对手持密钥是否与系统签名密钥一致,而无需任何端点重新泄露密钥。完整密钥仅在创建时显示一次。 | |
url | string | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
next_cursor | string | 可为 null | 获取下一页时请原样传回。 |
page_size | integer | 可为 null | 服务器用于本页的最大记录数,已应用上限,并非 |
total | integer · int64 | 可为 null | 符合筛选条件的记录数量。统计成本过高时为 |
warnings | object[] | 列表呈现方式的原因;无异常时为空。封闭代码集: | |
code | string | —filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing | |
count | integer · int64 | 可为 null | — |
message | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}/v1/webhooks创建 Webhook 端点
webhook:managepost_webhooks所需权限范围: webhook:manage.
为调用密钥创建 webhook 端点。保存前,服务器会向 URL POST 一个已签名的 ping 事件(CHECK_HEALTH)。未获 2xx 则不保存并返回 422 webhook.health_check_failed。必须使用公开 https URL,内部或元数据 IP 返回 422 webhook.url_not_allowed。
webhook_secret 仅在创建时显示一次,无法再次读取。丢失后须在面板轮换,旧密钥还会并行有效 24 小时(§8.4)。
密钥已有端点时返回 409 webhook.already_configured,即使端点已暂停(is_active: false)。暂停仍保留 URL、密钥及日志。若需重建,先 DELETE /v1/webhooks/{id} 再创建。
请求体必填application/json
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
events | string[] | 为空表示接收全部。未知值返回 400 | |
url | string · uri | 必填 | — |
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
active | boolean |
| |
created_at | string · date-time | — | |
events | string[] | 为空表示接收全部。 | |
health_check | string | —passed | |
id | string · uuid | 端点 ID,用于 | |
last_delivery_at | string · date-time | 可为 null | 通过此端点最后投递的时间。 |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
secret_last4 | string | Webhook 密钥的末四个字符,可用于核对手持密钥是否与系统签名密钥一致,而无需任何端点重新泄露密钥。完整密钥仅在创建时显示一次。 | |
url | string | — | |
webhook_secret | string | 仅在创建时显示一次(前缀 | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedwebhook.already_configuredwebhook.health_check_failedwebhook.url_not_allowedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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"响应示例
{
"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
}请求体示例
{
"events": [
"order.completed"
],
"url": "https://partner.example.com/hooks/tke"
}/v1/webhooks/{id}获取单个 webhook 端点
webhook:manageget_webhooks__id_所需权限范围: webhook:manage.
路径参数 (1)
idstring必填Webhook 端点 ID(POST /v1/webhooks 或 GET /v1/webhooks 返回的 id)。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
active | boolean |
| |
created_at | string · date-time | — | |
events | string[] | 为空表示接收全部。 | |
id | string · uuid | 端点 ID,用于 | |
last_delivery_at | string · date-time | 可为 null | 通过此端点最后投递的时间。 |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
secret_last4 | string | Webhook 密钥的末四个字符,可用于核对手持密钥是否与系统签名密钥一致,而无需任何端点重新泄露密钥。完整密钥仅在创建时显示一次。 | |
url | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedwebhook.not_foundpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}/v1/webhooks/{id}更新 Webhook 端点
webhook:manageput_webhooks__id_所需权限范围: webhook:manage.
路径参数 (1)
idstring必填Webhook 端点 ID(POST /v1/webhooks 或 GET /v1/webhooks 返回的 id)。
请求体必填application/json
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
events | string[] | 为空表示接收全部。未知值返回 400 | |
url | string · uri | 必填 | — |
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
active | boolean |
| |
created_at | string · date-time | — | |
events | string[] | 为空表示接收全部。 | |
id | string · uuid | 端点 ID,用于 | |
last_delivery_at | string · date-time | 可为 null | 通过此端点最后投递的时间。 |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
secret_last4 | string | Webhook 密钥的末四个字符,可用于核对手持密钥是否与系统签名密钥一致,而无需任何端点重新泄露密钥。完整密钥仅在创建时显示一次。 | |
url | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedwebhook.not_foundwebhook.health_check_failedwebhook.url_not_allowedpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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"响应示例
{
"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
}请求体示例
{
"events": [
"order.completed"
],
"url": "https://partner.example.com/hooks/tke"
}/v1/webhooks/{id}删除 webhook 端点(停止接收新事件)
webhook:managedelete_webhooks__id_所需权限范围: webhook:manage.
删除端点后,调用密钥不再接收新事件。
webhook_secret 会随端点删除而失去。通过 POST /v1/webhooks 重建会生成新 id 和新密钥,必须更新签名验证函数。若只需暂停并保留密钥,请使用面板中的“暂停”。
完整投递日志保留用于对账,但被删端点的投递记录无法重放。
等待重试的 pending 投递会以 endpoint_disabled 原因停止,并保留日志(§8.5)。
不属于调用密钥或已删除的 id 返回 404 webhook.not_found,绝不会静默返回 200。
路径参数 (1)
idstring必填Webhook 端点 ID(POST /v1/webhooks 或 GET /v1/webhooks 返回的 id)。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
deleted_at | string · date-time | — | |
id | string · uuid | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedwebhook.not_foundpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"data": {
"deleted_at": "2026-07-11T08:12:30Z",
"id": "018f2b00-0000-7000-8000-00000000009a",
"mode": "live"
},
"ok": true
}/v1/webhooks/deliveriesWebhook 投递日志
webhook:manageget_webhooks_deliveries所需权限范围: webhook:manage.
查询参数 (5)
pageinteger选填默认值 1min 1页码从 1 开始。超出数据末尾时返回 items: [] 和真实 total(200,非 404)。
page_sizeinteger选填默认值 50min 1max 200每页记录数,默认 50,上限 200;超过上限时限制为 200,不报错。
event_typestring选填按事件类型筛选(参见 webhook 事件目录)。
statusstring选填pendingdeliveredfailed按投递状态筛选。?status=failed 用于主动查询式 webhook 对账(§13)。未知值不会报错,筛选条件会被忽略并返回完整日志。
event_idstring · uuid选填同一事件的所有投递尝试(包括重放)。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
items | object[] | — | |
attempts | integer | — | |
created_at | string · date-time | — | |
event_id | string · uuid | 事件标识。重放会创建一个新投递记录,但保留同一 | |
event_type | string | — | |
id | string · uuid | — | |
last_attempt_at | string · date-time | 可为 null | — |
next_retry_at | string · date-time | 可为 null | — |
response_code | integer | 可为 null | — |
status | string | —pendingdeliveredfailed | |
webhook_id | string · uuid | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
next_cursor | string | 可为 null | 获取下一页时请原样传回。 |
page_size | integer | 可为 null | 服务器用于本页的最大记录数,已应用上限,并非 |
total | integer · int64 | 可为 null | 符合筛选条件的记录数量。统计成本过高时为 |
warnings | object[] | 列表呈现方式的原因;无异常时为空。封闭代码集: | |
code | string | —filtered_by_key_package_filtersfiltered_by_provider_scopeno_price_for_orgprice_filter_removed_rowsprovider_disabledcapability_missing | |
count | integer · int64 | 可为 null | — |
message | string | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedwebhook.not_configuredpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}/v1/webhooks/deliveries/{id}/replay重新投递 webhook
webhook:managepost_webhooks_deliveries__id__replay所需权限范围: webhook:manage.
路径参数 (1)
idstring必填单次 webhook 投递 ID(来自 GET /v1/webhooks/deliveries 的 items[].id)。
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
attempts | integer | — | |
created_at | string · date-time | — | |
event_id | string · uuid | 事件标识。重放会创建一个新投递记录,但保留同一 | |
event_type | string | — | |
id | string · uuid | — | |
last_attempt_at | string · date-time | 可为 null | — |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
next_retry_at | string · date-time | 可为 null | — |
response_code | integer | 可为 null | — |
status | string | —pendingdeliveredfailed | |
webhook_id | string · uuid | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedwebhook.delivery_not_foundwebhook.not_configuredpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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、批量订单或人工审核退款申请。
/v1/testmode/esims/{id}/simulate模拟测试 eSIM 生命周期(仅限测试密钥)
esims:writepost_testmode_esims__id__simulate所需权限范围: esims:write.
仅限tke_test_或tke_member_test_测试密钥。对所有者的测试eSIM设置用量、安装状态、到期、限速或下一操作的模拟供应商拒绝。正文至少包含一个字段;空正文返回422 testmode.invalid_scenario。与正式模式相同,通过GET /v1/esims/{id}和/usage读取结果。套餐变更及取消规则共用,不调用真实供应商。
路径参数 (1)
idstring必填已售 eSIM 的稳定 ID,不是可能复用的 ICCID。
请求体必填application/json
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data_used_mb | integer · int64 | 已使用流量(MB,以二进制 1 MiB 为单位)。超出套餐额度时截至额度上限,表示流量耗尽场景,而非错误。 | |
expire_at | string · date-time | 设置明确的到期时间(ISO-8601 UTC)。 | |
expire_now | boolean |
| |
provider_reject | boolean | 模拟供应商拒绝下一次操作(追加/取消)。 | |
status | string | eSIM 配置的技术生命周期,采用供应商术语,不同于 eSIM 端点返回的业务状态 releasedinstalledenableddisabled | |
throttled | boolean |
|
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
cancellable | object | eSIM 是否仍可取消及原因,请在调用 | |
allowed | boolean | — | |
disclosed_at | string · date-time | 可为 null | 代码离开系统的时间(ISO-8601 UTC),无人查看时为 |
reason | string | 可为 null | 不可取消原因: code_disclosedwrong_statusexpirednot_supportednull |
external_ref | string | 可为 null | 您的订单引用(下单时发送的 |
iccid | string | 可为 null | — |
id | string · uuid | eSIM ID,用于所有 | |
install | object | 可为 null | 安装此 eSIM 所需的全部信息。 包含此对象的响应始终带有 |
android_url | string | 可为 null | — |
apn | string | 可为 null | 设备无法自动获取配置时需输入的接入点名称(APN)。当前版本始终为 |
ios_url | string | 可为 null | — |
lpa | string | 可为 null | eSIM 激活码,属于可销售的机密。仅凭此字符串即可在您的系统生成二维码。 |
matching_id | string | 可为 null | — |
qr_code_base64 | string | 可为 null | 二维码的 PNG data-URI。仅在详情端点请求 |
smdp_address | string | 可为 null | — |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
msisdn | string | 可为 null | — |
order_id | string · uuid | — | |
package_code | string | 可为 null | 目录中的套餐代码,用于将此 eSIM 对应回您的目录。仅当源套餐已从目录移除时为 |
package_name | string | 供人阅读、可能变化的显示名称。请勿用作对账键。 | |
plan | object | 可为 null | 此 eSIM 当前使用的套餐。 |
current_code | string | — | |
expires_at | string · date-time | 可为 null | — |
started_at | string · date-time | 可为 null | — |
simulated | object | 应用场景后的模拟状态。 | |
esim_state | string | 测试 eSIM 的技术生命周期。正式环境来自 releasedinstalledenableddisabled | |
last_via | string | 最近修改此 eSIM 的流程。 open_apisimulateseed | |
via | string | 创建此测试 eSIM 的流程。 open_apisimulateseed | |
smdp_status | string | 可为 null | — |
status | string | — | |
updated_at | string · date-time | — | |
usage | object | 可为 null | eSIM 流量使用统计,从未查询过时 |
expires_at | string · date-time | 可为 null | — |
remaining_bytes | integer · int64 | 可为 null | — |
source | string | 可为 null | —pollwebhook |
total_bytes | integer · int64 | 可为 null | — |
updated_at | string · date-time | 可为 null | — |
used_bytes | integer · int64 | 可为 null | — |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbiddeninternal.not_foundtestmode.invalid_scenariopartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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"响应示例
{
"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
}请求体示例
{
"data_used_mb": 4096,
"expire_at": "2026-07-11T08:12:30Z",
"expire_now": true,
"provider_reject": true,
"status": "enabled",
"throttled": true
}/v1/testmode/reset重置测试数据(仅限测试密钥)
orders:writepost_testmode_reset所需权限范围: orders:write.
请求头 (1)
Idempotency-Keystring选填请求体选填application/json
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
reason | string | — |
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
esim_states_deleted | integer · int64 | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
order_items_deleted | integer · int64 | — | |
orders_deleted | integer · int64 | — | |
wallet_balance | integer · int64 | 重置后的测试钱包余额,始终为 0。不会删除账本,而是通过抵销分录将余额归零。 | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbiddenpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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"响应示例
{
"data": {
"esim_states_deleted": 1,
"mode": "live",
"order_items_deleted": 1,
"orders_deleted": 1,
"wallet_balance": 1
},
"ok": true
}请求体示例
{
"reason": "Reset test data"
}/v1/testmode/seed生成测试示例数据(仅限测试密钥)
orders:writepost_testmode_seed所需权限范围: orders:write.
请求头 (1)
Idempotency-Keystring选填响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
already_seeded | boolean | — | |
esims_created | integer | — | |
mode | string | 调用密钥的环境,与X-TKE-Mode标头一致。组织密钥使用tke_live_/tke_test_,会员密钥使用tke_member_live_/tke_member_test_。正式和测试主机校验密钥模式。 testlive | |
orders_created | integer | — | |
seeded | boolean | — | |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbiddentestmode.no_sellable_packagepartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-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)"响应示例
{
"data": {
"already_seeded": true,
"esims_created": 1,
"mode": "live",
"orders_created": 1,
"seeded": true
},
"ok": true
}/v1/testmode/status测试模式概览(仅限测试密钥)
esims:readget_testmode_status所需权限范围: esims:read.
响应
成功
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
data | object | 必填 | — |
base_url_testing | string | 测试模式主机。仅使用tke_test_或tke_member_test_密钥;调用正式主机返回403 partner.wrong_host。 | |
capabilities | object | — | |
bulk_orders | boolean | — | |
cancel_refund | boolean | — | |
refund_requests | boolean | — | |
webhooks | boolean | — | |
checklist | object[] | 根据同一所有者在测试模式下的实际API记录计算集成进度。Webhook步骤仅适用于组织。 | |
done | boolean | — | |
label | string | — | |
last_at | string · date-time | 可为 null | — |
step | string | — | |
drift | object | 模拟用量循环的启用状态、间隔及最后运行时间。阈值Webhook仅发送给支持Webhook的组织。 | |
enabled | boolean | — | |
interval_secs | integer · int64 | — | |
last_run_at | string · date-time | 可为 null | — |
mode | string | —testlive | |
ready | boolean | 密钥所有者是否已完成所有受支持的检查步骤。会员无需测试Webhook。 | |
sample_counts | object | — | |
test_esims | integer · int64 | — | |
test_orders | integer · int64 | — | |
seeded | boolean | 密钥所有者是否已有测试订单和eSIM样本数据。 | |
test_key_count | integer · int64 | — | |
wallet_balance | integer · int64 | 密钥所有者的虚拟VND测试钱包余额,与正式钱包隔离。 | |
webhook | object | — | |
endpoint_url | string | 可为 null | — |
fail_next | integer | — | |
status | string | 可为 null | — |
ok | boolean | 必填 | —true |
错误响应
所有错误均返回 { ok: false, error } 及正确 HTTP 状态,错误不返回 200,详细含义参见错误码页面。
internal.validation_failedpartner.invalid_keypartner.invalid_signaturepartner.timestamp_expiredpartner.nonce_reusedpartner.ip_not_allowedpartner.scope_deniedpartner.key_suspendedpartner.key_revokedorg.suspendedtestmode.live_key_forbiddenpartner.rate_limitedpartner.endpoint_disabledinternal.service_unavailable调用示例
所有 TKE-VN-30D-X3K9F 值均需自行替换,真实套餐代码请查询 GET /v1/catalog/packages.
#!/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: zh-CN" \
-H "X-TKE-Key: $KEY_ID" \
-H "X-TKE-Timestamp: $TS" \
-H "X-TKE-Nonce: $NONCE" \
-H "X-TKE-Signature: $SIG"响应示例
{
"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
}