Tổng Kho eSIM
Tổng Kho eSIM — Open API đối tác · v2.4.0

Open API Documentation

Open API serves partners and members whose access has been enabled by an administrator. Your system calls /v1 to browse catalogs, create and read orders, retrieve eSIM profiles (ICCID + LPA installation codes), track usage and reconcile through REST polling. Payments debit the key owner’s wallet: organization or member. Webhooks are for organizations; member prices and invoices follow the member flow described in the member OpenAPI section of the integration guide.

API Surface at a Glance

30 operations
Organized across 6 groups: Catalog · Orders · eSIMs · Wallet · Webhooks · Test Mode.
Unified Authentication
HMAC-SHA256 with 4 X-TKE-* headers, applied even to GET requests. No skip-signing mode, no raw API keys in headers.
Single Consistent Envelope
{ ok, data } or { ok, error } paired with semantic HTTP status codes. Never HTTP 200 for errors.
91 published error codes
Every error code carries an HTTP status code and a clear retryability flag, sourced directly from the backend registry.
8 webhook events
Configurable via POST /v1/webhooks, signed with dedicated secrets, at-least-once delivery, and full delivery logs for replay.
Test Mode on Its Own Host
Host api-testing.tongkhoesim.com only accepts tke_test_ keys: virtual wallet, virtual stock, deterministic mock provisioning, self-running usage. Switch to the live host + tke_live_ key when ready, no code changes.
text
https://api.tongkhoesim.com/v1    # Live
https://api-testing.tongkhoesim.com/v1    # Test mode

Live: api.tongkhoesim.com / tke_live_ (partners) or tke_member_live_ (approved members). Test: api-testing.tongkhoesim.com / tke_test_ / tke_member_test_ (partners / members).

4-Step Onboarding

1. Create a test key
From the partner dashboard, Test Mode section: create a key with prefix tke_test_. The secret is shown only once, store it securely immediately. Your organization's first test key auto-generates sample data (3 orders, 3 states). Test wallets can be topped up indefinitely.
2. Place orders on the test host
Sign requests with HMAC, invoke POST https://api-testing.tongkhoesim.com/v1/orders. The test host issues deterministic mock eSIMs (ICCID prefix 8999) immediately without touching real inventory or funds. Try directly in the browser or download our Postman collection.
3. Register webhook & trigger test events
Call POST /v1/webhooks to register your URL (your endpoint must return 2xx for CHECK_HEALTH upon creation). Then invoke POST /v1/testmode/webhooks/fire to dispatch mock events, or POST /v1/testmode/webhooks/fail-next to exercise retries.
4. Switch to a live key
Create a key with prefix tke_live_, keep the exact same codebase, and switch host (api-testing → api) plus key_id + secret. Remember to register webhooks separately for your live key, as endpoints are isolated per api_key_id.

3 Critical Integration Pitfalls

Read these three caveats before writing your first line of code. All three are silent traps: code runs, unit tests pass, and bugs only surface when real money is spent or reconciliation data is corrupted.

Idempotency-Key is scoped per API key
Deduplication is scoped strictly to a single api_key_id. The same Idempotency-Key sent across two distinct keys (even within the same organization) constitutes two separate commands: two orders, two wallet debits. Use a stable key per ordering flow or embed your key_id.
REST calls it id; webhooks call the same value order_item_id
On REST (/v1/esims, an order's items[]), an eSIM's own primary key is id; order_id is only the foreign key back to its parent order. Webhook payloads (order.completed, esim.delivered) use the field name order_item_id for that exact same value — two surfaces, two names, one UUID. Cross-reference by value, never by assuming identical field names. Always store and look up eSIMs by id/order_item_id, NEVER by ICCID: upstream telco providers may recycle ICCIDs, whereas this identifier remains globally unique and permanent. If all you have is an ICCID, call GET /v1/esims?iccid=… to get the id. To match an eSIM back to your own order, send external_ref (your order reference) when ordering — it comes back on every REST eSIM block and on every per-eSIM webhook (together with order_id), and GET /v1/esims?external_ref=… returns every eSIM of that order.
Cursor pagination loops must terminate properly
GET /v1/orders and GET /v1/esims use cursor pagination. Malformed cursors do NOT throw errors; the server resets to the beginning. Loops checking only next_cursor !== null will loop infinitely: you must stop when next_cursor is absent or equal to the current cursor.

Next Steps

Runnable example files, a Postman collection, an .http bundle — and how to generate your own client from openapi.json if you still need one.
Exact signature canonical formula + live test vectors to validate your implementation.
Every endpoint: parameters, schemas, all response branches, and runnable snippets.
Event catalog, signature verification, retry backoff schedules, and pull reconciliation.