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을 포함한 모든 요청에 HMAC-SHA256 및 헤더 4개(X-TKE-Key · X-TKE-Timestamp · X-TKE-Nonce · X-TKE-Signature)가 필요합니다.
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에서 사용합니다. updated_since는 orders와 esims만 지원합니다.
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는 X-TKE-* 헤더 4개를 추가하는 함수입니다(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는 Wi-Fi 공유 지원 명시, 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에서는 지원하지 않습니다. 하나의 통합 플래그로 모두 미지원 처리하면 카탈로그의 약 3분의 1을 잘못 안내하게 됩니다. | |
android | string |
supportedblockedunknown | |
app | string | 소문자 앱 코드입니다(예: | |
ios | string |
supportedblockedunknown | |
note | string | null 허용 | — |
hotspot | boolean | null 허용 | 다른 기기와 Wi-Fi 공유 기능입니다. |
kyc_required | boolean | null 허용 | 사용 전에 신원 확인(KYC)이 필요합니다. |
sms | boolean | null 허용 | SMS입니다. |
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 허용 | 구매 후 QR 스캔 또는 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: ko" \
-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: ko" \
-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)입니다. 웹훅을 놓쳐도 상태를 복원할 수 있습니다. 형식이 틀리면 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: ko" \
-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:writeIdempotency-Key 필수post_orders필요한 권한 범위: orders:write.
헤더 (1)
Idempotency-Keystring필수클라이언트 생성 문자열입니다. 같은 키와 본문은 한 번만 실행되며 재시도는 원래 결과를 반환합니다. api_key_id 단위(§11)이므로 다른 키는 별개 명령입니다.
요청 본문필수application/json
| 필드 | 유형 | 제약 조건 | 설명 |
|---|---|---|---|
external_ref | string | null 허용 | 응답 및 웹훅에 그대로 반환되는 자체 참조 코드입니다. |
include | string[] | null 허용 | 추가 블록 요청: |
invoice_buyer | object | null 허용 | 회원 키 전용입니다. 생략하면 조직이나 베트남 법인 없이 소비자 흐름을 사용합니다. 입력 시 기존 개인 검증인 full_name, 12자리 개인 tax_code 및 checkout의 address/email 규칙을 적용합니다. 기업 청구서는 구매 후 요청합니다. 테스트 모드는 스냅샷만 검증하며 MISA 청구서를 발행하지 않습니다. |
address | string | null 허용 | — |
email | string | null 허용 | — |
full_name | string | null 허용 | — |
legal_name | string | null 허용 | — |
tax_code | string | null 허용 | — |
items | object[] | 필수 | 구매할 요금제 및 수량 목록입니다(eSIM 최대 50개). |
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 | 주문의 VAT 청구서 상태입니다. 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 | 모든 | |
install | object | null 허용 | 이 eSIM 설치에 필요한 모든 정보입니다. 이 블록이 포함된 응답에는 항상 |
android_url | string | null 허용 | — |
apn | string | null 허용 | 기기가 자동 구성하지 못할 때 입력할 APN입니다. 현재 버전에서는 항상 |
ios_url | string | null 허용 | — |
lpa | string | null 허용 | eSIM 활성화 코드이며 판매 가능한 비밀 정보입니다. 이 문자열만으로 QR 코드를 생성할 수 있습니다. |
matching_id | string | null 허용 | — |
qr_code_base64 | string | null 허용 | QR 코드의 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 | 주문의 VAT 청구서 상태입니다. 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 | 모든 | |
install | object | null 허용 | 이 eSIM 설치에 필요한 모든 정보입니다. 이 블록이 포함된 응답에는 항상 |
android_url | string | null 허용 | — |
apn | string | null 허용 | 기기가 자동 구성하지 못할 때 입력할 APN입니다. 현재 버전에서는 항상 |
ios_url | string | null 허용 | — |
lpa | string | null 허용 | eSIM 활성화 코드이며 판매 가능한 비밀 정보입니다. 이 문자열만으로 QR 코드를 생성할 수 있습니다. |
matching_id | string | null 허용 | — |
qr_code_base64 | string | null 허용 | QR 코드의 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: ko" \
-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 | 주문의 VAT 청구서 상태입니다. 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 | 모든 | |
install | object | null 허용 | 이 eSIM 설치에 필요한 모든 정보입니다. 이 블록이 포함된 응답에는 항상 |
android_url | string | null 허용 | — |
apn | string | null 허용 | 기기가 자동 구성하지 못할 때 입력할 APN입니다. 현재 버전에서는 항상 |
ios_url | string | null 허용 | — |
lpa | string | null 허용 | eSIM 활성화 코드이며 판매 가능한 비밀 정보입니다. 이 문자열만으로 QR 코드를 생성할 수 있습니다. |
matching_id | string | null 허용 | — |
qr_code_base64 | string | null 허용 | QR 코드의 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: ko" \
-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주문의 이메일/QR 재전송
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 | 일부 가린 수신 주소입니다. 파트너 API는 고객의 전체 이메일을 다시 노출하지 않습니다. | |
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: ko" \
-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:writeIdempotency-Key 필수post_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분이 지나면 다시 정상 주문할 수 있습니다.
줄별 참조는 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: ko" \
-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: ko" \
-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/esimseSIM 목록 조회(조회 기반 대사)
esims:readget_esims필요한 권한 범위: esims:read.
쿼리 매개변수 (8)
page_sizeinteger선택기본값 50min 1max 200페이지당 레코드 수입니다. 기본 50, 최대 200이며 더 큰 값을 보내면 오류 없이 200으로 제한됩니다.
statusstring선택pendingavailablereservedsolddeliveredin_useused_upexpiredsuspendedcancelledprovider_failedesim_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)입니다. 웹훅을 놓쳐도 상태를 복원할 수 있습니다. 형식이 틀리면 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 | 모든 | |
install | object | null 허용 | 이 eSIM 설치에 필요한 모든 정보입니다. 이 블록이 포함된 응답에는 항상 |
android_url | string | null 허용 | — |
apn | string | null 허용 | 기기가 자동 구성하지 못할 때 입력할 APN입니다. 현재 버전에서는 항상 |
ios_url | string | null 허용 | — |
lpa | string | null 허용 | eSIM 활성화 코드이며 판매 가능한 비밀 정보입니다. 이 문자열만으로 QR 코드를 생성할 수 있습니다. |
matching_id | string | null 허용 | — |
qr_code_base64 | string | null 허용 | QR 코드의 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: ko" \
-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 | 모든 | |
install | object | null 허용 | 이 eSIM 설치에 필요한 모든 정보입니다. 이 블록이 포함된 응답에는 항상 |
android_url | string | null 허용 | — |
apn | string | null 허용 | 기기가 자동 구성하지 못할 때 입력할 APN입니다. 현재 버전에서는 항상 |
ios_url | string | null 허용 | — |
lpa | string | null 허용 | eSIM 활성화 코드이며 판매 가능한 비밀 정보입니다. 이 문자열만으로 QR 코드를 생성할 수 있습니다. |
matching_id | string | null 허용 | — |
qr_code_base64 | string | null 허용 | QR 코드의 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: ko" \
-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:writeIdempotency-Key 필수post_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: ko" \
-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-planeSIM 충전
esims:writeIdempotency-Key 필수post_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: ko" \
-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에서는 지원하지 않습니다. 하나의 통합 플래그로 모두 미지원 처리하면 카탈로그의 약 3분의 1을 잘못 안내하게 됩니다. | |
android | string |
supportedblockedunknown | |
app | string | 소문자 앱 코드입니다(예: | |
ios | string |
supportedblockedunknown | |
note | string | null 허용 | — |
hotspot | boolean | null 허용 | 다른 기기와 Wi-Fi 공유 기능입니다. |
kyc_required | boolean | null 허용 | 사용 전에 신원 확인(KYC)이 필요합니다. |
sms | boolean | null 허용 | SMS입니다. |
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 허용 | 구매 후 QR 스캔 또는 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: ko" \
-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: ko" \
-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-requestseSIM 환불 요청 생성(회원 전용)
esims:writeIdempotency-Key 필수post_esims__id__refund-requests필요한 권한 범위: esims:write.
승인된 실제 회원 키만 가능합니다. Idempotency-Key로 회원 eSIM의 환불을 신청하며 관리자 승인 전에는 자금이 이동하지 않습니다. 조직 및 테스트 키는 capability.not_supported입니다. 테스트 모드에서는 eSIM 취소로 가상 지갑 환불을 시험하세요.
경로 매개변수 (1)
idstring필수판매된 eSIM의 고정 ID입니다. 재사용될 수 있는 ICCID가 아닙니다.
헤더 (1)
Idempotency-Keystring필수클라이언트 생성 문자열입니다. 같은 키와 본문은 한 번만 실행되며 재시도는 원래 결과를 반환합니다. 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: ko" \
-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: ko" \
-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: ko" \
-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
}웹훅
웹훅 설정, 전송 기록 및 시뮬레이터
/v1/testmode/webhooks/fail-next다음 웹훅 실패 시뮬레이션(테스트 키 전용)
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: ko" \
-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:managepost_testmode_webhooks_fire필요한 권한 범위: webhook:manage.
요청 본문필수application/json
| 필드 | 유형 | 제약 조건 | 설명 |
|---|---|---|---|
data | object | 샘플 페이로드의 | |
event_type | string | 필수 | 발생시킬 웹훅 이벤트 유형입니다. 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: ko" \
-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:manageget_webhooks필요한 권한 범위: webhook:manage.
호출한 API 키의 웹훅 엔드포인트만 반환합니다. 같은 조직의 두 키라도 다른 키의 엔드포인트를 볼 수 없습니다(§5.11: api_key_id에 연결되며 테스트와 실운영은 공유하지 않음).
아직 설정하지 않았으면 404가 아닌 빈 배열과 200을 반환합니다. 컬렉션은 항상 존재하며 항목만 없을 수 있습니다.
응답
성공
| 필드 | 유형 | 제약 조건 | 설명 |
|---|---|---|---|
data | object | 필수 | — |
items | object[] | — | |
active | boolean |
| |
created_at | string · date-time | — | |
events | string[] | 비어 있으면 모두 수신합니다. | |
id | string · uuid |
| |
last_delivery_at | string · date-time | null 허용 | 이 엔드포인트로 마지막 전송한 시각입니다. |
secret_last4 | string | 웹훅 비밀키의 마지막 네 글자입니다. 비밀키 전체를 다시 노출하지 않고 보유한 키가 서명에 쓰이는 키인지 확인합니다. 전체 비밀키는 생성 시 한 번만 표시됩니다. | |
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: ko" \
-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:managepost_webhooks필요한 권한 범위: webhook:manage.
호출한 키의 웹훅 엔드포인트를 생성합니다. 저장 전에 서버가 URL로 서명한 ping POST를 보냅니다(CHECK_HEALTH). 2xx가 아니면 저장하지 않고 422 webhook.health_check_failed입니다. 공개 https URL만 허용하며 내부/메타데이터 IP는 422 webhook.url_not_allowed입니다.
webhook_secret는 생성 시 한 번만 표시하며 다시 읽을 수 없습니다. 분실하면 대시보드에서 교체해야 하며 이전 비밀키도 24시간 함께 유효합니다(§8.4).
이미 엔드포인트가 있으면 일시 중지(is_active: false) 상태여도 409 webhook.already_configured입니다. 중지는 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 |
| |
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 | 웹훅 비밀키의 마지막 네 글자입니다. 비밀키 전체를 다시 노출하지 않고 보유한 키가 서명에 쓰이는 키인지 확인합니다. 전체 비밀키는 생성 시 한 번만 표시됩니다. | |
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: ko" \
-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:manageget_webhooks__id_필요한 권한 범위: webhook:manage.
경로 매개변수 (1)
idstring필수웹훅 엔드포인트 ID입니다(POST /v1/webhooks 또는 GET /v1/webhooks의 id).
응답
성공
| 필드 | 유형 | 제약 조건 | 설명 |
|---|---|---|---|
data | object | 필수 | — |
active | boolean |
| |
created_at | string · date-time | — | |
events | string[] | 비어 있으면 모두 수신합니다. | |
id | string · uuid |
| |
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 | 웹훅 비밀키의 마지막 네 글자입니다. 비밀키 전체를 다시 노출하지 않고 보유한 키가 서명에 쓰이는 키인지 확인합니다. 전체 비밀키는 생성 시 한 번만 표시됩니다. | |
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: ko" \
-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:manageput_webhooks__id_필요한 권한 범위: webhook:manage.
경로 매개변수 (1)
idstring필수웹훅 엔드포인트 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 |
| |
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 | 웹훅 비밀키의 마지막 네 글자입니다. 비밀키 전체를 다시 노출하지 않고 보유한 키가 서명에 쓰이는 키인지 확인합니다. 전체 비밀키는 생성 시 한 번만 표시됩니다. | |
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: ko" \
-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:managedelete_webhooks__id_필요한 권한 범위: webhook:manage.
엔드포인트를 제거하면 호출 키의 새 이벤트 수신이 중지됩니다.
webhook_secret도 함께 사라집니다. POST /v1/webhooks로 재생성하면 새 id와 새 비밀키가 발급되므로 검증 함수를 수정해야 합니다. 비밀키를 유지하는 일시 중지는 대시보드의 중지 버튼을 사용하세요.
전체 전송 로그는 대사용으로 유지되지만 삭제한 엔드포인트의 전송은 재시도할 수 없습니다.
재시도 대기 중인 pending 전송은 endpoint_disabled로 중지되고 로그에는 남습니다(§8.5).
다른 키의 id 또는 이미 삭제한 id는 조용히 200을 반환하지 않고 404 webhook.not_found입니다.
경로 매개변수 (1)
idstring필수웹훅 엔드포인트 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: ko" \
-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/deliveries웹훅 전송 기록
webhook:manageget_webhooks_deliveries필요한 권한 범위: webhook:manage.
쿼리 매개변수 (5)
pageinteger선택기본값 1min 11부터 시작하는 페이지 번호입니다. 마지막 페이지를 넘으면 items: []와 실제 total을 반환합니다(200, 404 아님).
page_sizeinteger선택기본값 50min 1max 200페이지당 레코드 수입니다. 기본 50, 최대 200이며 더 큰 값을 보내면 오류 없이 200으로 제한됩니다.
event_typestring선택이벤트 유형으로 필터링합니다(웹훅 이벤트 목록 참조).
statusstring선택pendingdeliveredfailed전송 상태로 필터링합니다. ?status=failed는 조회 기반 웹훅 대사(§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: ko" \
-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:managepost_webhooks_deliveries__id__replay필요한 권한 범위: webhook:manage.
경로 매개변수 (1)
idstring필수웹훅 전송 한 건의 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: ko" \
-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과 데이터를 모의합니다. 회원 테스트 모드는 웹훅, 대량 주문, 검토용 환불 요청을 지원하지 않습니다.
/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 | 모든 | |
install | object | null 허용 | 이 eSIM 설치에 필요한 모든 정보입니다. 이 블록이 포함된 응답에는 항상 |
android_url | string | null 허용 | — |
apn | string | null 허용 | 기기가 자동 구성하지 못할 때 입력할 APN입니다. 현재 버전에서는 항상 |
ios_url | string | null 허용 | — |
lpa | string | null 허용 | eSIM 활성화 코드이며 판매 가능한 비밀 정보입니다. 이 문자열만으로 QR 코드를 생성할 수 있습니다. |
matching_id | string | null 허용 | — |
qr_code_base64 | string | null 허용 | QR 코드의 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: ko" \
-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입니다. 원장은 삭제하지 않고 상계 분개로 잔액을 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: ko" \
-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: ko" \
-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 기록으로 통합 단계를 계산합니다. 웹훅 단계는 조직에만 적용됩니다. | |
done | boolean | — | |
label | string | — | |
last_at | string · date-time | null 허용 | — |
step | string | — | |
drift | object | 모의 사용량 증가 주기의 활성 상태, 간격, 최근 실행 시각입니다. 임계값 웹훅은 웹훅을 지원하는 조직에만 전송됩니다. | |
enabled | boolean | — | |
interval_secs | integer · int64 | — | |
last_run_at | string · date-time | null 허용 | — |
mode | string | —testlive | |
ready | boolean | 키 소유자가 지원되는 체크리스트 단계를 모두 완료했는지 나타냅니다. 회원은 웹훅 테스트가 필요하지 않습니다. | |
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: ko" \
-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
}