Dokumentasi API

REST API untuk akses batch / otomatis ke jiema.my. Gunakan ini untuk mengintegrasikan verifikasi SMS ke layanan Anda sendiri. Semua endpoint mengembalikan JSON.

Masuk untuk membuat API key pertama Anda.

Autentikasi

Setiap permintaan harus menyertakan API key Anda:

Authorization: Bearer jm_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Bentuk header alternatif: X-API-Key: jm_xxx…

Buat dan cabut key di /account/api-keys. Setiap pengguna dapat memiliki hingga 10 key aktif. Token lengkap hanya ditampilkan sekali saat pembuatan — simpan dengan aman.

Error & batas rate

Semua error mengembalikan JSON:

{ "ok": false, "code": "RATE_LIMITED", "message": "..." }
HTTPcodearti
401AUTH_MISSING / AUTH_INVALIDTidak ada key atau dicabut
403FORBIDDENDiblokir atau tidak ada akses
400BAD_REQUEST / INSUFFICIENT / NO_NUMBERS / …Validasi atau error bisnis
404NOT_FOUNDOrder tidak ada (atau bukan milik Anda)
429RATE_LIMITEDBatas rate tercapai — coba lagi setelah jendela direset. Batas per user, dibagi di antara semua key.
500INTERNALError server (dilaporkan otomatis)

Batas rate: Per user (kuota dibagi di antara semua API key kamu), jendela geser 60s. Endpoint tulis (orders, cancel, next-sms) 10 req/min; endpoint baca (account, services, prices, list) 60 req/min. Membuat key tambahan tidak menambah kuotamu.

GET /v1/account

Dapatkan saldo saat ini dan profil dasar Anda.

curl https://jiema.my/api/v1/account \
  -H "Authorization: Bearer jm_xxx"

# 200 OK
{ "ok": true, "data": {
  "id": "clxxxxxxxxxxx",
  "balanceCents": "1200",       // string to preserve precision; $12.00
  "referralCode": "abc123",
  "displayName": "Alice",
  "lang": "en"
}}

GET /v1/services

Daftar service dengan stok. Di-cache di server sekitar 5 menit.

curl https://jiema.my/api/v1/services -H "Authorization: Bearer jm_xxx"

{ "ok": true, "data": { "items": [
  { "code": "tg", "slug": "telegram", "name": "Telegram",
    "minCostUsd": 0.18, "totalCount": 1234, "countryCount": 24 },
  ...
] }}

Gunakan code (atau slug yang ramah) sebagai field service saat membuat order.

GET /v1/countries

curl https://jiema.my/api/v1/countries -H "Authorization: Bearer jm_xxx"

{ "ok": true, "data": { "items": [
  { "id": 7, "slug": "my", "name": "Malaysia" },
  ...
] }}

id adalah country id numerik upstream; slug adalah kode pendek SEO (mis. "my" / "us"). Kedua bentuk berfungsi sebagai field country.

GET /v1/prices?service=tg

Harga per negara dan stok untuk service tertentu. Harga sudah termasuk markup/diskon yang dikonfigurasi oleh ops.

curl "https://jiema.my/api/v1/prices?service=tg" -H "Authorization: Bearer jm_xxx"

{ "ok": true, "data": {
  "service": "tg",
  "items": [
    { "countryId": 7, "countrySlug": "my", "priceCents": "32", "count": 540 },
    ...
  ]
}}

POST /v1/orders

Buat order verifikasi SMS. Sistem akan memesan nomor telepon dari upstream dan memotong jumlah yang ditagih dari saldo Anda.

curl -X POST https://jiema.my/api/v1/orders \
  -H "Authorization: Bearer jm_xxx" \
  -H "content-type: application/json" \
  -d '{ "service": "tg", "country": 7 }'

{ "ok": true, "data": {
  "id": "ckxxxxx",
  "status": "WAITING",
  "service": "tg",
  "country": "7",
  "phone": "+60123456789",
  "expiresAt": "2026-05-22T08:30:00.000Z",
  "chargedCents": "32"
}}

Tidak ada field opsional selain service / country.

Kode error umum: INSUFFICIENT (perlu top up), NO_NUMBERS, BAD_SERVICE, BAD_COUNTRY.

GET /v1/orders/:id

Polling hingga status menjadi RECEIVED dan smsBody tidak null.

curl https://jiema.my/api/v1/orders/ckxxxxx -H "Authorization: Bearer jm_xxx"

{ "ok": true, "data": {
  "id": "ckxxxxx",
  "status": "RECEIVED",
  "phone": "+60123456789",
  "smsBody": "Your verification code is 123456",
  "smsHistory": [
    { "body": "Your verification code is 123456", "receivedAt": "..." }
  ],
  "smsReceivedAt": "2026-05-22T08:12:34.000Z",
  ...
}}

Status: WAITING (nomor aktif, menunggu SMS) · RECEIVED (kode tiba) · COMPLETED / FAILED / CANCELLED adalah status akhir.

Polling yang disarankan: setiap 3–5 detik. Sinkronisasi upstream berjalan di dalam endpoint ini sehingga polling akan menggerakkan state walaupun worker latar sedang sibuk.

POST /v1/orders/:id/cancel

Batalkan order yang belum menerima kode. Refund penuh ke saldo Anda.

curl -X POST https://jiema.my/api/v1/orders/ckxxxxx/cancel \
  -H "Authorization: Bearer jm_xxx"

{ "ok": true, "data": { "id": "ckxxxxx", "status": "CANCELLED" }}

Ditolak dengan CODE_RECEIVED jika nomor sudah menerima SMS apa pun, atau ALREADY_CHANGED jika status berubah secara konkuren.

POST /v1/orders/:id/next-sms

Setelah RECEIVED, minta upstream untuk mempertahankan nomor tetap aktif dan menunggu SMS lain (tanpa biaya tambahan dalam jendela aktif).

curl -X POST https://jiema.my/api/v1/orders/ckxxxxx/next-sms \
  -H "Authorization: Bearer jm_xxx"

{ "ok": true, "data": { "id": "ckxxxxx", "status": "WAITING" }}

GET /v1/orders

Daftar order Anda terbaru dengan paginasi berbasis cursor.

curl "https://jiema.my/api/v1/orders?limit=20" -H "Authorization: Bearer jm_xxx"

{ "ok": true, "data": {
  "items": [ { "id": "ck...", "status": "RECEIVED", "service": "tg", ... }, ... ],
  "nextCursor": "ck..." | null
}}

Query opsional: status · limit 1–100 (default 20) · cursor = nextCursor dari halaman sebelumnya.

Alur kerja umum

  1. Top up via UI web → GET /v1/account untuk konfirmasi saldo.
  2. Pilih service: GET /v1/services dan GET /v1/prices?service=tg.
  3. Buat order: POST /v1/orders dengan service + country.
  4. Baca data.phone dan picu SMS upstream dari client Anda (mis. tempel ke registrasi Telegram).
  5. Polling GET /v1/orders/:id setiap 3–5 detik. Ketika status === "RECEIVED", baca smsBody.
  6. Jika SMS salah atau ingin kode kedua: POST /v1/orders/:id/next-sms → kembali ke WAITING.
  7. Selesai. Jika Anda membatalkan sebelum SMS tiba: POST /v1/orders/:id/cancel untuk refund penuh.