Self-Integration
There is no official package to install. The three things below do exactly what one used to do: sign requests correctly, give you a runnable example, and hand you a ready-to-click test collection — no need to write a line of code before you know what the API returns.
OpenAPI for members
Integrate directly with a member account, without creating an organization or a Vietnamese legal-entity profile.
An administrator grants OpenAPI per member. Open API Keys in the main sidebar, select Live or Test, then create a key; the secret appears once. Both modes share the key limit. Disabling access blocks both modes while still allowing revocation.
Live uses the member’s real VND wallet, without credit. Test uses a separate virtual wallet and simulated eSIMs; add test funds, seed or reset samples in Test Mode. Test orders do not appear in live purchase history.
A member’s private package price is final, with no additional tier discount. Without a private package price, the current list price and tier discount apply. The server fixes the price when placing the order.
Invoices follow the member flow: consumer sale by default. When creating an order, you may supply invoice_buyer with valid individual details under the current validation rules. A Vietnamese legal-entity profile is not required for OpenAPI access.
Live: https://api.tongkhoesim.com with tke_member_live_. Test: https://api-testing.tongkhoesim.com with tke_member_test_. Both use HMAC-SHA256 and X-TKE-Key, X-TKE-Timestamp, X-TKE-Nonce, X-TKE-Signature. Sign the exact method, path/query and raw-body hash; never put secrets in browser code.
POST requests to create orders, change plans, cancel or request refunds require Idempotency-Key. Keep the same key and body when retrying one intent; deduplication is scoped to the API key, so do not switch API keys to retry a pending transaction. Member test seed and reset also require Idempotency-Key; reset must include a {reason} body.
Include lpa in include to receive installation codes; the normal cancellation window closes when codes are actually returned. qr only adds a QR image alongside lpa and is ignored on list endpoints. Request codes only when ready to deliver; omit include to avoid disclosure. Refund requests still follow business eligibility and are not an unrestricted cancellation route after code disclosure.
Member API endpoints
- API route:
GET /v1/catalog/packages - Required scope:
catalog:read - API route:
GET /v1/catalog/packages/{code} - Required scope:
catalog:read - API route:
GET /v1/orders - Required scope:
orders:read - API route:
POST /v1/orders - Required scope:
orders:write - API route:
GET /v1/orders/{id} - Required scope:
orders:read - API route:
POST /v1/orders/{id}/resend - Required scope:
orders:write - API route:
GET /v1/esims - Required scope:
esims:read - API route:
GET /v1/esims/{id} - Required scope:
esims:read - API route:
GET /v1/esims/{id}/usage - Required scope:
esims:read - API route:
GET /v1/esims/{id}/plan-options - Required scope:
esims:read - API route:
POST /v1/esims/{id}/change-plan - Required scope:
esims:write - API route:
POST /v1/esims/{id}/cancel - Required scope:
esims:write - API route:
GET /v1/esims/{id}/refund-requests - Required scope:
esims:read - API route:
POST /v1/esims/{id}/refund-requests - Required scope:
esims:write - API route:
GET /v1/wallet/balance - Required scope:
wallet:read
Test Mode
GET /v1/testmode/statusesims:readPOST /v1/testmode/seedorders:writePOST /v1/testmode/resetorders:writePOST /v1/testmode/esims/{id}/simulateesims:write
The console accepts partner tke_test_ and member tke_member_test_ keys on the api-testing host only. All live keys are blocked. Secrets remain in page memory and are never saved to storage or logs.
Sign requests
The full HMAC-SHA256 formula, snippets in 5 languages (bash/Node/Python/PHP/Go), and real backend-generated test vectors live entirely on the HMAC Signing page — nothing is duplicated here.
#!/usr/bin/env bash
# Yeu cau: openssl. Ky POST /v1/orders.
KEY_ID="tke_test_ab12cd34..."
SECRET="tke_secret_test_0123456789abcdef"
METHOD="POST"
PATH_Q="/v1/orders"
BODY='{"items":[{"package_code":"THAY-BANG-MA-GOI-CUA-BAN","quantity":2}]}'
TS="$(date +%s000)" # epoch milliseconds
NONCE="$(uuidgen)"
BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')"
SIGNING="$METHOD"$'
'"$PATH_Q"$'
'"$TS"$'
'"$NONCE"$'
'"$BODY_HASH"
SIG="$(printf '%s' "$SIGNING" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')"
curl -sS "https://api.tongkhoesim.com$PATH_Q" -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"Runnable example files
Two files at the repository root (examples/sign.mjs, examples/sign.py) run immediately with the language's standard runtime, no package to install. Both read the /hmac-test-vectors.json test vectors, compute the signature for each one, compare it against the expected result, and print PASS/FAIL per line.
node examples/sign.mjs # plain Node (node:crypto), nothing to install
python examples/sign.py # plain Python (hmac/hashlib), nothing to installReady-to-run collections
Two collections generated DIRECTLY from openapi.json at build time, always matching the live spec: one for Postman, one for editors that support .http files (VS Code REST Client, JetBrains HTTP Client). One request per endpoint, with the 4 signing headers pre-filled — just add your key and compute the signature.
- Open tongkhoesim.http in VS Code (REST Client extension) or JetBrains HTTP Client.
- Fill in @key_id and @secret at the top with your tke_test_ key — @base_url already points at the api-testing.tongkhoesim.com host.
- Compute timestamp/nonce/signature using the snippets on the HMAC Signing page or by running examples/sign.*, then paste them into the matching variables.
- Send any request right inside your editor — no Postman, no code required.
Still want an SDK?
Generate one from openapi.json with openapi-generator — a machine-generated client never drifts from the spec, unlike a handwritten one:
npx @openapitools/openapi-generator-cli generate \
-i https://docs.tongkhoesim.com/openapi.json \
-g typescript-fetch \
-o ./tke-sdk