SentaduSentadu

eSIM buat yang suka jalan. Beli sebelum terbang, online begitu mendarat.

PT. Digital One Global

Tomorowland III Tegal, Jawa Tengah ID 52462

VisaMastercardJCBAmerican ExpressDiners Club
PayPalUnionPayQRISE-walletBank VARetail

Produk

  • Lokal
  • Bundle
  • Regional
  • Global
  • Destinasi
  • Unlimited
  • Umrah dan Haji

Bantuan

  • Cara Kerja
  • Jalur Internet eSIM
  • FAQ
  • Perangkat Didukung
  • Bagikan cerita
  • Bantuan

Kemitraan

  • Dashboard
  • Jadi Mitra
  • Solusi Bisnis
  • Reseller
  • Docs
  • Agent Skills

Perusahaan

  • Tentang
  • Investor (Private)Segera
  • Karier
  • Syarat & Ketentuan
  • Kebijakan Privasi
  • Kebijakan Pengembalian
VisaMastercardJCBAmerican ExpressDiners Club
PayPalUnionPayQRISE-walletBank VARetail

© 2026 PT. Digital One Global. Hak cipta dilindungi.

Tanya Many
Sentadu
Sentadu
LokalBundleRegionalGlobalDestinasiUnlimited

Dokumentasi API

Beli dan kelola eSIM secara programatik. Empat belas endpoint, satu bearer token, penyelesaian Rupiah.

Dokumentasi

  • Mulai cepat
  • Agent Skills
  • Autentikasi
  • Paket
  • Pesanan
  • eSIM
  • Dompet
  • Webhook
  • Sandbox
  • Batas laju
  • Error

Mulai cepat

Beli akses API dari dompet, buat key, lalu lakukan panggilan pertama. Seluruh alurnya sekitar satu menit.

  1. 1Buka konsol developer dan beli paket. Kedua paket langsung memotong dompet Sentadu kamu.
  2. 2Buat key. Pilih Live untuk pembelian nyata, atau Test untuk memakai sandbox. Key lengkap hanya tampil sekali.
  3. 3Panggil API dengan key sebagai bearer token. Setiap respons adalah JSON dengan field data, atau objek error.

URL dasar

https://api.sentadu.com/v1

Panggilan pertama

curl https://api.sentadu.com/v1/me \
  -H "Authorization: Bearer $SENTADU_API_KEY"
Agent SkillsSerahkan dokumentasi ini ke agen coding kamu. Satu bundel berisi SKILL.md, referensi endpoint, error, webhook, sandbox, dan dua skrip. Bisa diunduh sebagai .zip atau .tar.gz.

Autentikasi

Setiap permintaan membawa bearer token. Tidak ada kredensial lain dan tidak ada bentuk query string.

Authorization: Bearer sdk_live_ab12cd34.<secret>
Autentikasi
Key berbentuk sdk_live_ab12cd34.<rahasia>. Bagian sebelum titik mengidentifikasi key; semua setelahnya adalah rahasianya.
Kami hanya menyimpan hash key. Kalau hilang, cabut dan buat yang baru.
Key live memindahkan uang nyata. Key test memakai saldo sandbox dan tidak pernah menyentuh penyedia.
Key tidak punya masa berlaku sendiri. Key bekerja selama langganan akun aktif atau dalam masa tenggang.
Mencabut key bersifat langsung dan permanen.

Paket

Katalognya sama dengan yang dijual toko publik. Harga dikembalikan dalam satuan minor USD dan IDR; angka IDR adalah yang akan ditagih.

  • Harga per paket tergantung tier kamu. Key Reseller melihat harga toko publik. Key Enterprise melihat harga pokok penyedia, tanpa markup.
  • Paket DAILY adalah data tak terbatas per hari dengan throttle setelah kuota harian. duration_days-nya hanya placeholder 1; kirim validity_days saat memesan.
  • country_count dan countries menjelaskan cakupan. Paket SINGLE mencakup satu negara; REGIONAL dan MULTI mencakup beberapa.
GET/v1/packages

Every purchasable package, priced for your tier.

Parameter

  • country ISO-2 code · opsionalOnly packages covering this country.
  • coverage SINGLE,MULTI,REGIONAL · opsionalComma-separated coverage kinds.
  • type FIXED | DAILY · opsionalFixed-data or unlimited-per-day plans.
  • sort price_asc | price_desc | volume_desc · opsionalDefault is by name.
  • page integer · opsional1-based. Clamped to the last page.
  • limit integer 1-100 · opsionalDefault 24.

Respons

{
  "data": [{
    "package_code": string,
    "slug": string,
    "name": string,
    "coverage": "SINGLE" | "MULTI" | "REGIONAL",
    "plan_type": "FIXED" | "DAILY",
    "duration_days": number,
    "volume_bytes": number,
    "speed": string | null,
    "fup_policy": string | null,
    "support_top_up": boolean,
    "country_count": number,
    "countries": [{ "code": string, "name": string }],
    "price": { "usd_minor": number, "idr_minor": number, "currency": "USD" },
    "wholesale": boolean
  }],
  "meta": { "page": number, "perPage": number, "total": number, "totalPages": number }
}
GET/v1/packages/{package_code}

One package by its SKU.

Parameter

Tanpa parameter.

Respons

The same object as one element of `GET /v1/packages`.

Pesanan

Satu pesanan memotong dompet dan menyediakan eSIM dalam satu panggilan. Tidak ada langkah pembayaran yang perlu dipoll: responsnya sudah membawa status pesanan dan eSIM-nya begitu fulfillment cukup cepat.

  • Kirim header Idempotency-Key. Percobaan ulang dengan key yang sama mengembalikan pesanan yang sama, bukan membeli dua kali. Key unik per akun, jadi dua developer boleh sama-sama memakai 'order-1'.
  • quantity menyediakan sebanyak itu eSIM dalam satu pesanan, dengan satu pemotongan dompet. Maksimal 10.
  • Kalau saldo dompet tidak cukup, API menjawab 402 sebelum pesanan apa pun ada, jadi pembelian gagal tidak mengotori daftar pesanan kamu.
  • Pembatalan mengikuti aturan toko: eSIM yang belum pernah diaktivasi, di dalam jendela pembatalan. Dompet dikembalikan.
POST/v1/orders

Buy a package. Debits the wallet and provisions an eSIM.

Parameter

  • Idempotency-Key header · opsionalA retry with the same key returns the same order.

Body permintaan

{
  "package_code": "JP-5GB-30D",
  "validity_days": 30,
  "quantity": 1,
  "idempotency_key": "9f2c-order-1"
}

Respons

{
  "data": {
    "id": string,
    "order_number": "SUD-...",
    "status": "PAID" | "FULFILLMENT" | "ACTIVE",
    "package_code": string,
    "quantity": number,
    "validity_days": number | null,
    "amount_idr_minor": number,
    "pricing_mode": "STORE" | "WHOLESALE",
    "created_at": string,
    "paid_at": string | null,
    "esims": [{ "id": string, "iccid": string, "lpa": string, "status": string }]
  }
}
GET/v1/orders

Orders created by your integration, newest first.

Parameter

  • status order status · opsionalPENDING_PAYMENT, PAID, FULFILLMENT, ACTIVE, EXPIRED, CANCELLED, FAILED.
  • page integer · opsional1-based.
  • limit integer 1-100 · opsionalDefault 20.

Respons

A list of order objects, with `meta`.
GET/v1/orders/{id}

One order, by id or order_number.

Parameter

Tanpa parameter.

Respons

One order object.
POST/v1/orders/{id}/cancel

Cancel an order whose eSIM was never activated.

Parameter

Tanpa parameter.

Respons

The order, now `CANCELLED`.

eSIM

Satu eSIM milik satu paket dan satu pesanan. Membacanya memberi detail pemasangan; aksi siklus hidup mengubah apa yang penyedia lakukan dengannya.

  • lpa adalah string aktivasi yang dibaca ponsel dari kode QR, dan qr_code_url adalah gambar hosted dari hal yang sama. pin dan puk hanya dikembalikan saat kamu meminta ?include=secrets.
  • status diturunkan dari field penyedia ditambah tanggal kedaluwarsa, jadi bisa saja EXPIRED walau penyedia masih melaporkan eSIM itu terpakai.
  • Top up butuh paket yang penyedia tawarkan untuk eSIM ini. Picker di halaman akun dan endpoint ini memakai daftar yang sama, jadi kode dari sana selalu bisa dipakai di sini. Kirim Idempotency-Key dan panggilan ulang mengembalikan top-up yang sudah dibeli.
  • suspend dan unsuspend hanya bekerja pada eSIM yang sudah aktif. revoke permanen dan tidak mengembalikan apa pun; pakai cancel di pesanan kalau eSIM belum pernah dipakai.
GET/v1/esims

eSIMs owned by the account.

Parameter

  • status provider status · opsionalIN_USE, USED_UP, GOT_RESOURCE, CANCEL.
  • page integer · opsional1-based.
  • limit integer 1-100 · opsionalDefault 20.

Respons

{
  "data": [{
    "id": string,
    "iccid": string | null,
    "package_code": string,
    "status": "READY" | "ACTIVE" | "SUSPENDED" | "EXPIRED" | "USED_UP" | "CANCELLED",
    "total_bytes": number,
    "used_bytes": number,
    "remaining_bytes": number,
    "activated_at": string | null,
    "expires_at": string | null,
    "created_at": string
  }],
  "meta": { ... }
}
GET/v1/esims/{id}

One eSIM, with its install details.

Parameter

  • include secrets · opsionalAdds `pin` and `puk`.

Respons

The list shape plus `lpa`, `qr_code_url`, `smdp_status`, `esim_status`, `apn`.
GET/v1/esims/{id}/usage

Data used and remaining, as last measured.

Parameter

Tanpa parameter.

Respons

{
  "esim_id": string,
  "iccid": string | null,
  "total_bytes": number,
  "used_bytes": number,
  "remaining_bytes": number,
  "percent_used": number,
  "measured_at": string | null
}
POST/v1/esims/{id}/topups

Buy more data for an eSIM. Debits the wallet.

Parameter

Tanpa parameter.

Body permintaan

{ "package_code": "JP-1GB-7D" }

Respons

{
  "id": string,
  "esim_id": string,
  "package_code": string,
  "amount_idr_minor": number,
  "status": string,
  "created_at": string
}
POST/v1/esims/{id}/suspend

Temporarily suspend an activated eSIM.

Parameter

Tanpa parameter.

Respons

{ "esim_id": string, "status": "SUSPEND" }
POST/v1/esims/{id}/unsuspend

Re-enable a suspended eSIM.

Parameter

Tanpa parameter.

Respons

{ "esim_id": string, "status": "UNSUSPEND" }
POST/v1/esims/{id}/revoke

Permanently revoke an eSIM. No refund.

Parameter

Tanpa parameter.

Respons

{ "esim_id": string, "status": "REVOKE" }

Dompet

Pembelian dipotong dari dompet Sentadu dalam Rupiah. Top up dari halaman akun, lalu belanja lewat API.

  • Dompet hanya IDR. Tidak ada mata uang kedua dan tidak ada konversi di endpoint ini.
  • Pembelian lewat API tanpa biaya layanan. Biaya yang kamu bayar saat top up sudah menutup transaksi gateway.
  • Setiap kredit dan debit muncul di ledger, terbaru dulu, dengan referensi penyebabnya. Key sandbox mendapat daftar kosong, karena uang sandbox tidak masuk ledger.
GET/v1/wallet

Wallet balance in IDR, or the sandbox balance for a TEST key.

Parameter

Tanpa parameter.

Respons

{ "balance_idr_minor": number, "currency": "IDR", "sandbox": boolean }
GET/v1/wallet/transactions

Wallet ledger entries, newest first.

Parameter

  • limit integer 1-100 · opsionalDefault 50. Always empty for a TEST key.

Respons

{
  "data": [{
    "id": string,
    "amount_idr_minor": number,
    "balance_after_idr_minor": number,
    "type": "TOPUP" | "PURCHASE" | "REFUND" | "REFERRAL",
    "description": string | null,
    "reference_type": string | null,
    "reference_id": string | null,
    "created_at": string
  }]
}

Webhook

Kami mengirim POST untuk setiap event yang kamu langganan, dan mencoba ulang endpoint yang gagal selama sehari sebelum menyerah.

order.paidorder.activeorder.failedorder.cancelled

Setiap permintaan membawa X-Sentadu-Signature: t=<unix>,v1=<hex>. Isinya HMAC-SHA256 atas string '<t>.<raw body>', dengan rahasia endpoint kamu sebagai kunci.

X-Sentadu-Signature: t=1750000000,v1=6f1c...

Verifikasi tanda tangan terhadap body mentah, bukan objek yang diserialisasi ulang, dan tolak timestamp lebih tua dari lima menit.

import crypto from "node:crypto";

export function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(
    header.split(",").map((part) => part.split("=")),
  );
  const timestamp = Number(parts.t);
  if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${parts.t}.${rawBody}`)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(parts.v1),
  );
}

Respons non-2xx dicoba ulang setelah 1 menit, 5, 30, 2 jam, dan 12 jam. Setelah lima kegagalan, pengiriman ditandai FAILED dan tampil di dashboard kamu.

Endpoint harus https dan bisa dijangkau dari internet publik. Alamat privat, loopback, dan link-local ditolak.

Sandbox

Key Test menjalankan seluruh API terhadap akun palsu. Katalog dan harganya asli, jadi angka yang kamu lihat sama dengan produksi.

  • Pesanan bernomor TST-, eSIM punya ICCID sintetis dan LPA yang menunjuk test.sentadu.com, dan pemasangannya tidak ke mana-mana. Tidak ada panggilan ke penyedia.
  • Sandbox mulai dengan Rp 500.000 dan bisa direset dari konsol. Pembelian yang melebihi saldo mengembalikan insufficient_wallet yang sama dengan key live.
  • Key test butuh langganan aktif, sama seperti key live.

Batas laju

Batasnya per key, dihitung per menit. Key Reseller mendapat 60 permintaan/menit; Enterprise mulai dari 300 dan bisa menambah.

  • Setiap respons membawa X-RateLimit-Limit dan X-RateLimit-Remaining. Penolakan berupa 429 dengan Retry-After.
  • Add-on Enterprise bertumpuk dan berakhir bersama tahun langganan. Dibeli dari konsol developer.
  • Batasnya dihitung per key, bukan sebagai kumpulan bersama: setiap key dihitung sendiri.
TierRequests/minutePer year
Reseller60Rp 150.000 once
Enterprise300Rp 888.000
+300 add-on300Rp 450.000
+1200 add-on1200Rp 1.500.000
+2800 add-on2800Rp 3.000.000

Maximum self-serve: 4600 requests/minute.

Error

Setiap kegagalan berupa satu objek dengan kode stabil. Cabangkan pada kode, jangan pada pesan.

Bentuk

{
  "error": {
    "code": "insufficient_wallet",
    "message": "Wallet balance Rp 40.000 does not cover Rp 62.000.",
    "details": [{ "path": "package_code", "message": "..." }]
  }
}
KodeHTTP 
invalid_api_key401The Authorization bearer token is missing, malformed or revoked.
subscription_inactive403The account's API subscription has expired. Renew it to resume access.
rate_limited429Too many requests in the current window. Respect Retry-After.
invalid_request400The request body or query string failed validation.
not_found404The resource does not exist, or does not belong to this account.
insufficient_wallet402The Sentadu wallet balance does not cover this purchase.
package_unavailable409The package exists but is not available for purchase.
esim_not_toplup_able409This eSIM cannot be topped up (expired or unsupported).
esim_not_activatable409This eSIM is in a state that refuses the requested action.
idempotency_conflict409The same Idempotency-Key was used with a different request body.
internal_error500Something failed on our side. Retry with backoff.

Siap membangun?

Buat kunci API, pilih paket, dan kirim permintaan pertama dalam beberapa menit.

Buka Akun DevBandingkan paket
LokalBundleRegionalGlobalDestinasiUnlimited