Menu utama

Developer · API

Pesanan & SMS

Kontrak pembelian nomor, pembacaan SMS, pembatalan, dan penyelesaian order dengan perlindungan idempotensi.

Unduh OpenAPI 3.1

Sebelum mengirim request

Semua operasi hanya berlaku untuk order milik sesi. POST sukses memakai HTTP 200. Order yang masih disiapkan dapat berstatus waiting tanpa nomor atau kode. Gunakan flag tindakan server, bukan asumsi dari timer browser.

Kontrak nyata, nilai contoh

Endpoint, field, dan status HTTP mengikuti implementasi. Nilai ID, nomor, OTP, waktu, saldo, serta quote di contoh adalah ilustrasi, bukan data akun atau pilihan yang bisa langsung dibeli. Ganti dengan data dari instalasimu. Halaman ini tidak mengirim request atau menjalankan transaksi.

JavaScript dijalankan pada origin aplikasi setelah login. Contoh cURL memakai PING_ORIGIN dan cookie jar PING_COOKIE_JAR dari panduan autentikasi. Sukses memakai { ok: true, data }; create juga HTTP 200, bukan 201. Semua endpoint di halaman ini memerlukan sesi aktif dan dapat mengembalikan 401, 403, atau 500.

Aktivitas pendaftaran, pemesanan, SMS & top-up global

GET/api/activitySession cookie

Maksimal 10 event pendaftaran akun, pemesanan nomor, penerimaan kode SMS, dan top-up lintas pengguna dalam 24 jam terakhir, digabung dan diurutkan dari event terbaru. type=registration berasal dari waktu pembuatan akun yang tidak ditangguhkan; hanya id event anonim yang stabil, type, dan displayName yang dikirim, tanpa identitas akun atau provider. type=order berasal dari event ACTIVE untuk pesanan ACTIVE, CODE_RECEIVED, atau COMPLETED dengan nomor tidak kosong; pesanan masih disiapkan atau gagal tidak ditampilkan. type=sms berasal dari event CODE_RECEIVED untuk pesanan CODE_RECEIVED atau COMPLETED dengan kode tidak kosong, tanpa menunggu pesanan selesai. SMS tanpa kode, pesanan dibatalkan, dan pesanan kedaluwarsa dikecualikan. Event order dan sms memiliki ID terpisah, nama layanan, negara, alias server publik (v1–v4), dan nomor tersamar. type=topup hanya berasal dari pembayaran QRIS berstatus PAID yang terhubung ke ledger DEPOSIT akun dan pembayaran yang sama; hanya id event anonim, type, provider=qris, dan displayName yang dikirim. Pembayaran pending, gagal, kedaluwarsa, dan penyesuaian saldo admin bukan aktivitas top-up berhasil. Aktivitas anonim dibagikan secara default, termasuk jika belum ada preferensi tersimpan; akun dengan shareActivity=false yang tersimpan dikecualikan. Akun admin dan akun yang ditangguhkan tidak pernah ditampilkan. displayName selalu Pengguna ping. Nama, username, nomor lengkap, email, OTP, isi SMS, nominal, detail pembayaran, ID transaksi/pengguna, dan timestamp tidak dikirim. Wajib sesi aktif. Server membagikan satu snapshot ke semua pembaca hingga 8 detik; UI memeriksa setiap 10 detik saat tab terlihat dan saat kembali fokus, dengan retry terbatas untuk error sementara. Saat feed diaktifkan, aktivitas yang tersedia ditampilkan sekali; polling selanjutnya hanya menambah event yang belum tampil, tanpa memutar ulang riwayat. Error sementara menjeda antrean tanpa menghapus deduplikasi. Tidak memanggil provider atau mengubah saldo. Parameter query ditolak.

GET /api/activity · JavaScript
const response = await fetch("/api/activity", {
  credentials: "same-origin",
  cache: "no-store",
});
const body = await response.json();

if (!response.ok || !body.ok) {
  throw Object.assign(
    new Error(body.error?.message ?? "Request gagal"),
    { code: body.error?.code, status: response.status },
  );
}

const data = body.data;
Aktivitas pendaftaran, pemesanan, SMS & top-up global
Kode errorHTTPTindakan
VALIDATION_ERROR400Periksa tipe, field wajib, format UUID, dan field tambahan.

Statistik SMS akun

GET/api/statisticsSession cookie

Ringkasan pribadi riwayat pesanan milik pengguna bersesi dalam 7, 30, atau 90 hari kalender WIB, termasuk hari ini; periode mengikuti waktu pemesanan. Identitas akun selalu berasal dari sesi, bukan parameter permintaan. Seluruh hitungan, tren harian, layanan, negara, dan server dibatasi di database ke akun tersebut, termasuk untuk admin; tidak ada statistik seluruh pengguna. Rate menghitung satu SMS pertama per pesanan dibanding hasil akhir; pesanan menunggu dikecualikan. Hasil kosong bernilai null, bukan persentase buatan. Sampel kurang dari 10 hasil akhir perlu dibaca hati-hati. Waktu SMS dihitung sejak nomor aktif, termasuk jeda polling. Tidak memuat identitas pengguna, ID pesanan, nomor, OTP, isi SMS, harga, atau data wallet. ID agregasi layanan/negara bukan ID katalog untuk membeli nomor. Wajib sesi aktif; tanpa cache agregat bersama, respons HTTP private/no-store, tanpa panggilan provider. Parameter lain, termasuk userId dan scope, ditolak. Riwayat bukan jaminan stok atau keberhasilan verifikasi akun.

Statistik SMS akun
ParameterTipeWajibKeterangan
days (query)7 | 30 | 90Tidak
provider (query)all | v1 | v2 | v3 | v4Tidak
GET /api/statistics · JavaScript
const response = await fetch("/api/statistics?days=7&provider=all", {
  credentials: "same-origin",
  cache: "no-store",
});
const body = await response.json();

if (!response.ok || !body.ok) {
  throw Object.assign(
    new Error(body.error?.message ?? "Request gagal"),
    { code: body.error?.code, status: response.status },
  );
}

const data = body.data;
Statistik SMS akun
Kode errorHTTPTindakan
VALIDATION_ERROR400Periksa tipe, field wajib, format UUID, dan field tambahan.

Riwayat pesanan

GET/api/ordersSession cookie

Riwayat milik pengguna bersesi, diurutkan createdAt lalu id menurun. Respons data kini berupa OrderPage, bukan array: baca data.orders dan data.pagination. Default 20, maksimal 100 order per halaman. Pencarian tidak peka huruf besar/kecil pada ID, nomor, nama layanan, atau negara; %, _ dan backslash dicari sebagai karakter literal. counts mengikuti pencarian sebelum filter status; pagination.total mengikuti kedua filter. Parameter asing, duplikat, atau di luar batas ditolak. Tidak memanggil provider; pantau pesanan terbuka melalui daftar aktif dan endpoint detail.

Riwayat pesanan
ParameterTipeWajibKeterangan
limit (query)integerTidak
offset (query)integerTidak
status (query)all | waiting | completed | cancelled | failedTidakcancelled juga mencakup expired; waiting mencakup SMS yang belum diselesaikan.
search (query)stringTidakTeks literal, di-trim sebelum pencarian.
GET /api/orders · JavaScript
const response = await fetch("/api/orders?limit=20&offset=0&status=all&search=Telegram", {
  credentials: "same-origin",
  cache: "no-store",
});
const body = await response.json();

if (!response.ok || !body.ok) {
  throw Object.assign(
    new Error(body.error?.message ?? "Request gagal"),
    { code: body.error?.code, status: response.status },
  );
}

const data = body.data;
Riwayat pesanan
Kode errorHTTPTindakan
VALIDATION_ERROR400Periksa tipe, field wajib, format UUID, dan field tambahan.

Pesanan aktif

GET/api/orders/activeSession cookie

Seluruh pesanan terbuka milik pengguna bersesi, termasuk yang dibuat sebelum halaman riwayat pertama dan SMS yang belum diselesaikan. Semua DTO berstatus waiting. Dipakai dashboard dan polling akun tanpa memuat riwayat terminal. Terbaru lebih dahulu, tanpa pagination atau parameter query, tanpa panggilan provider. Panggil GET /api/orders/{id} untuk pemeriksaan status upstream.

GET /api/orders/active · JavaScript
const response = await fetch("/api/orders/active", {
  credentials: "same-origin",
  cache: "no-store",
});
const body = await response.json();

if (!response.ok || !body.ok) {
  throw Object.assign(
    new Error(body.error?.message ?? "Request gagal"),
    { code: body.error?.code, status: response.status },
  );
}

const data = body.data;
Pesanan aktif
Kode errorHTTPTindakan
VALIDATION_ERROR400Periksa tipe, field wajib, format UUID, dan field tambahan.

Buat pesanan

POST/api/ordersSession cookie

Menahan harga kandidat awal lalu meminta nomor ke provider. server v1 (v1) memakai ranking best_success untuk request provider yang dibekukan. Server aktif saling fallback setelah penolakan pasti sebelum aktivasi, memakai kandidat visible dan eligible untuk layanan dan negara yang sama. Jika server v2 ikut dalam routing, rute sehat didahulukan lalu server v2, server v1, dan sumber lainnya, tetap di dalam batas harga yang disetujui. Saat saldo upstream habis, semua tier provider tersebut dilewati dalam request yang sama dan pembelian baru dijeda 5 menit; polling pesanan lama tetap berjalan. Setiap percobaan adalah pesanan terpisah dengan kunci tetap; hold yang ditolak dilepas sebelum percobaan berikutnya. Tanpa maxPriceIdr eksplisit, harga tidak boleh melebihi expectedPriceIdr. Hasil ambigu menghentikan fallback dan memakai rekonsiliasi, bukan pembelian baru. Setelah berhasil, provider dan harga akhir tetap pinned. HTTP 200 berarti request ditangani, bukan jaminan nomor langsung terbit; periksa status, isPreparing, phone, dan message. Respons memakai Order, bukan activation atau token provider.

Perhatikan sebelum mengirim

Mutasi finansial. Simpan clientRequestId untuk satu niat pembelian sebelum mengirim request. Timeout bukan bukti pembelian gagal. Jangan membuat UUID baru atau melakukan retry otomatis saat hasil belum pasti.

Buat pesanan
Body JSONTipeWajibKeterangan
providerv1 | v2 | v3 | v4TidakIdentitas server publik v1–v4. Gunakan nilai dari katalog atau quote, bukan nama penyedia di belakang server. Setiap pesanan tetap terikat ke servernya. Fallback sebelum aktivasi memakai pesanan terpisah setelah penolakan terkonfirmasi, bukan memindahkan pesanan aktif.
serviceIdstringYaGunakan Service.id dari GET /api/catalog/services.
countryIdstringYaGunakan Country.id dari GET /api/catalog/countries.
clientRequestIdstring · uuidYaUUID per niat pembelian. Pertahankan UUID yang sama saat recovery request yang sama.
priceOptionIdstringYaWajib: Quote.options[].id yang dipilih pengguna. Jangan membuat ID sendiri.
expectedPriceIdrintegerYaWajib: Quote.options[].price_idr untuk kandidat awal. Harga awal berubah meminta konfirmasi baru.
maxPriceIdrintegerTidakOpsional: batas harga per nomor yang disetujui secara eksplisit, minimal expectedPriceIdr. Tanpa field ini, fallback tidak boleh lebih mahal dari harga awal. Simpan nilai yang sama pada intent dan setiap replay.
POST /api/orders · JavaScript
const response = await fetch("/api/orders", {
  method: "POST",
  credentials: "same-origin",
  cache: "no-store",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "provider": "v3",
    "serviceId": "service-example",
    "countryId": "country-example",
    "clientRequestId": "f41c29d8-967d-469d-ae4f-0114c38bf715",
    "priceOptionId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "expectedPriceIdr": 1500
  }),
});
const body = await response.json();

if (!response.ok || !body.ok) {
  throw Object.assign(
    new Error(body.error?.message ?? "Request gagal"),
    { code: body.error?.code, status: response.status },
  );
}

const data = body.data;
Buat pesanan
Kode errorHTTPTindakan
VALIDATION_ERROR400Periksa tipe, field wajib, format UUID, dan field tambahan.
ORDERING_PAUSED503Tawarkan server lain untuk dipilih pengguna. Pesanan lama dan replay UUID yang sama tetap diproses.
INSUFFICIENT_BALANCE422Tampilkan available dari server dan tawarkan top-up.
PRICE_CHANGED409Ambil quote baru dan minta konfirmasi harga lagi.
PRICE_OPTION_UNAVAILABLE409Ambil quote baru; jangan menebak atau membuat priceOptionId.
PRICE_UNAVAILABLE422Tawarkan pasangan lain atau coba baca quote lagi nanti.
SERVICE_UNAVAILABLE422Muat ulang katalog dan pilih layanan yang tersedia.
COUNTRY_UNAVAILABLE422Muat ulang katalog dan pilih negara yang tersedia.
ACTIVE_ORDER_LIMIT429Selesaikan order yang ada; limit mengikuti pengaturan operator.
ORDER_RATE_LIMIT429Jeda percobaan. Jangan membuat loop POST.
PURCHASE_UNRESOLVED409Pertahankan UUID awal dan tunggu rekonsiliasi; jangan membuat pembelian baru.
PROVIDER_ERROR502Baca ulang status. Jangan retry pembelian upstream secara otomatis.
RATE_LIMITED429Hormati Retry-After sebelum meminta ulang. Jangan retry pembelian otomatis atau membuat clientRequestId baru saat hasil awal belum pasti.

Baca pesanan & SMS

GET/api/orders/{id}Session cookie

Membaca order milik sesi. Untuk order terbuka atau yang memerlukan rekonsiliasi, server dapat memeriksa provider sebelum mengembalikan DTO. Polling UI berjalan setiap 5 detik selama status waiting; status waiting juga mencakup kode yang sudah diterima.

Baca pesanan & SMS
ParameterTipeWajibKeterangan
id (path)stringYaID order milik pengguna bersesi.
GET /api/orders/{id} · JavaScript
const response = await fetch("/api/orders/a4c4b37c-9b68-4b18-bd52-8e0ea3b08d19", {
  credentials: "same-origin",
  cache: "no-store",
});
const body = await response.json();

if (!response.ok || !body.ok) {
  throw Object.assign(
    new Error(body.error?.message ?? "Request gagal"),
    { code: body.error?.code, status: response.status },
  );
}

const data = body.data;
Baca pesanan & SMS
Kode errorHTTPTindakan
NOT_FOUND404Periksa ID dan akun; ID resource tidak memberi akses lintas pengguna.
PROVIDER_ERROR502Baca ulang status. Jangan retry pembelian upstream secara otomatis.
RECONCILIATION_REQUIRED409Pertahankan hold; baca ulang status. Callback SMS dapat memakai HTTP 503 untuk kode ini.
PROVIDER_UNAVAILABLE503Periksa konfigurasi server; lanjutkan pembacaan dengan backoff.
PROVIDER_TIMEOUT504Hasil bisa ambigu. Pertahankan UUID dan hold, tunggu rekonsiliasi.

Batalkan pesanan

POST/api/orders/{id}/cancelSession cookie

Pembatalan mengikuti canCancel, cooldown server, dan status provider. Kirim JSON {}. Dana dilepas setelah hasil pembatalan dikonfirmasi, bukan hanya karena tombol ditekan atau timer lokal selesai.

Batalkan pesanan
ParameterTipeWajibKeterangan
id (path)stringYaID order milik pengguna bersesi.

Body wajib: {} dengan Content-Type: application/json. Tidak menerima field tambahan.

POST /api/orders/{id}/cancel · JavaScript
const response = await fetch("/api/orders/a4c4b37c-9b68-4b18-bd52-8e0ea3b08d19/cancel", {
  method: "POST",
  credentials: "same-origin",
  cache: "no-store",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({}),
});
const body = await response.json();

if (!response.ok || !body.ok) {
  throw Object.assign(
    new Error(body.error?.message ?? "Request gagal"),
    { code: body.error?.code, status: response.status },
  );
}

const data = body.data;
Batalkan pesanan
Kode errorHTTPTindakan
NOT_FOUND404Periksa ID dan akun; ID resource tidak memberi akses lintas pengguna.
EARLY_CANCEL_DENIED409Baca ulang order dan ikuti canCancel serta cancelAvailableAt.
INVALID_STATE409GET detail order sebelum menawarkan aksi kembali.
ORDER_ALREADY_TERMINAL409Tampilkan hasil terkini dan perbarui saldo.
RECONCILIATION_REQUIRED409Pertahankan hold; baca ulang status. Callback SMS dapat memakai HTTP 503 untuk kode ini.
PROVIDER_TIMEOUT504Hasil bisa ambigu. Pertahankan UUID dan hold, tunggu rekonsiliasi.

Minta SMS ulang

POST/api/orders/{id}/resendSession cookie

Tersedia sesuai kemampuan provider setelah SMS pertama diterima; canResend, cooldown, dan batas aktivasi dicek lagi ke provider. Resend tidak menambah hold/capture atau biaya, tidak menghapus SMS sebelumnya, dan tidak menjamin pesan baru. SMS berikutnya dibaca melalui polling dengan revisi terbaru.

Perhatikan sebelum mengirim

requestId dicatat sebelum dispatch. Tidak ada retry otomatis ke provider, bahkan jika respons hilang. Retry dengan UUID sama hanya membaca hasil lokal; jangan membuat UUID baru ketika hasil belum pasti.

Minta SMS ulang
ParameterTipeWajibKeterangan
id (path)stringYaID order milik pengguna bersesi.
Minta SMS ulang
Body JSONTipeWajibKeterangan
requestIdstring · uuidYaUUID satu permintaan resend. Simpan untuk retry respons hilang; kunci sama tidak mengirim resend kedua, termasuk setelah restart.
POST /api/orders/{id}/resend · JavaScript
const response = await fetch("/api/orders/a4c4b37c-9b68-4b18-bd52-8e0ea3b08d19/resend", {
  method: "POST",
  credentials: "same-origin",
  cache: "no-store",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "requestId": "f41c29d8-967d-469d-ae4f-0114c38bf715"
  }),
});
const body = await response.json();

if (!response.ok || !body.ok) {
  throw Object.assign(
    new Error(body.error?.message ?? "Request gagal"),
    { code: body.error?.code, status: response.status },
  );
}

const data = body.data;
Minta SMS ulang
Kode errorHTTPTindakan
VALIDATION_ERROR400Periksa tipe, field wajib, format UUID, dan field tambahan.
NOT_FOUND404Periksa ID dan akun; ID resource tidak memberi akses lintas pengguna.
PROVIDER_MISMATCH422Pertahankan server asal. Resend tersedia pada semua server (v1–v4) saat provider mengizinkan; jangan memindahkan aktivasi ke provider lain.
INVALID_STATE409GET detail order sebelum menawarkan aksi kembali.
RECONCILIATION_REQUIRED409Pertahankan hold; baca ulang status. Callback SMS dapat memakai HTTP 503 untuk kode ini.
PROVIDER_TIMEOUT504Hasil bisa ambigu. Pertahankan UUID dan hold, tunggu rekonsiliasi.

Perpanjang nomor

POST/api/orders/{id}/prolongSession cookie

Mengaktifkan ulang nomor dari order yang sudah selesai untuk layanan dan negara yang sama, sebagai order baru. Tersedia saat canProlong true (saat ini hanya server v4, selama pemesanan server itu terbuka). Ini pembelian berbayar: harganya sama dengan order asal, saldo ditahan dulu, ditangkap saat SMS diterima, dan dilepas bila perpanjangan ditolak atau tidak terkonfirmasi sampai batas waktu. Respons adalah order baru dengan isProlongation true, bukan order asal; pantau order baru itu seperti pembelian biasa. Satu nomor hanya punya satu perpanjangan terbuka, dan nomor yang diperpanjang tidak bisa diganti.

Perhatikan sebelum mengirim

requestId dicatat sebelum dispatch dan provider dipanggil paling banyak sekali per requestId, tanpa retry otomatis, karena panggilan kedua berarti tagihan kedua. Jika respons hilang atau status order baru belum pasti, ulangi dengan UUID yang sama untuk membaca hasil lokal; jangan membuat UUID baru.

Perpanjang nomor
ParameterTipeWajibKeterangan
id (path)stringYaID order milik pengguna bersesi.
Perpanjang nomor
Body JSONTipeWajibKeterangan
requestIdstring · uuidYaUUID satu permintaan perpanjangan. Simpan untuk retry respons hilang; kunci sama tidak memperpanjang atau menagih dua kali, termasuk setelah restart.
POST /api/orders/{id}/prolong · JavaScript
const response = await fetch("/api/orders/a4c4b37c-9b68-4b18-bd52-8e0ea3b08d19/prolong", {
  method: "POST",
  credentials: "same-origin",
  cache: "no-store",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "requestId": "f41c29d8-967d-469d-ae4f-0114c38bf715"
  }),
});
const body = await response.json();

if (!response.ok || !body.ok) {
  throw Object.assign(
    new Error(body.error?.message ?? "Request gagal"),
    { code: body.error?.code, status: response.status },
  );
}

const data = body.data;
Perpanjang nomor
Kode errorHTTPTindakan
VALIDATION_ERROR400Periksa tipe, field wajib, format UUID, dan field tambahan.
NOT_FOUND404Periksa ID dan akun; ID resource tidak memberi akses lintas pengguna.
PROVIDER_MISMATCH422Pertahankan server asal. Resend tersedia pada semua server (v1–v4) saat provider mengizinkan; jangan memindahkan aktivasi ke provider lain.
INVALID_STATE409GET detail order sebelum menawarkan aksi kembali.
ORDERING_PAUSED503Tawarkan server lain untuk dipilih pengguna. Pesanan lama dan replay UUID yang sama tetap diproses.
INSUFFICIENT_BALANCE422Tampilkan available dari server dan tawarkan top-up.
ACTIVE_ORDER_LIMIT429Selesaikan order yang ada; limit mengikuti pengaturan operator.
ORDER_RATE_LIMIT429Jeda percobaan. Jangan membuat loop POST.
IDEMPOTENCY_CONFLICT409Pulihkan transaksi awal dengan payload yang sama. UUID baru hanya untuk niat transaksi baru setelah hasil awal terkonfirmasi.
PURCHASE_BUSY409Pantau order perpanjangan yang terbuka; minta lagi hanya setelah order itu selesai, gagal, atau dibatalkan.
RECONCILIATION_REQUIRED409Pertahankan hold; baca ulang status. Callback SMS dapat memakai HTTP 503 untuk kode ini.
PROVIDER_TIMEOUT504Hasil bisa ambigu. Pertahankan UUID dan hold, tunggu rekonsiliasi.

Selesaikan pesanan

POST/api/orders/{id}/completeSession cookie

Menyelesaikan order setelah kode diterima; ikuti canComplete dari server. Kirim JSON {}. Settlement menangkap alokasi saldo pesanan sekali saja. Sesudahnya, revalidasi order, akun, dan ledger.

Selesaikan pesanan
ParameterTipeWajibKeterangan
id (path)stringYaID order milik pengguna bersesi.

Body wajib: {} dengan Content-Type: application/json. Tidak menerima field tambahan.

POST /api/orders/{id}/complete · JavaScript
const response = await fetch("/api/orders/a4c4b37c-9b68-4b18-bd52-8e0ea3b08d19/complete", {
  method: "POST",
  credentials: "same-origin",
  cache: "no-store",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({}),
});
const body = await response.json();

if (!response.ok || !body.ok) {
  throw Object.assign(
    new Error(body.error?.message ?? "Request gagal"),
    { code: body.error?.code, status: response.status },
  );
}

const data = body.data;
Selesaikan pesanan
Kode errorHTTPTindakan
NOT_FOUND404Periksa ID dan akun; ID resource tidak memberi akses lintas pengguna.
INVALID_STATE409GET detail order sebelum menawarkan aksi kembali.
ORDER_ALREADY_TERMINAL409Tampilkan hasil terkini dan perbarui saldo.
RECONCILIATION_REQUIRED409Pertahankan hold; baca ulang status. Callback SMS dapat memakai HTTP 503 untuk kode ini.

Schema · Order

Schema · Order
FieldTipeWajibKeterangan
idstringYaSesuai tipe yang ditampilkan.
providerv1 | v2 | v3 | v4 | archivedYaServer asal pesanan. archived hanya untuk riwayat server yang sudah dinonaktifkan; bukan pilihan katalog atau pembelian. Aksi provider tidak tersedia untuk arsip.
countryIdstringYaSesuai tipe yang ditampilkan.
serviceIdstringYaSesuai tipe yang ditampilkan.
countryOrderCountryYaLihat schema OrderCountry pada OpenAPI.
serviceOrderServiceYaLihat schema OrderService pada OpenAPI.
phonestringYaNomor, atau teks status ketika nomor belum/tidak diterbitkan. Periksa isPreparing.
priceintegerYaHarga IDR yang dibekukan saat order dibuat.
statuswaiting | completed | cancelled | expired | failedYaStatus DTO client; tidak sama dengan enum database.
createdAtintegerYaUnix timestamp dalam milidetik, bukan detik.
expiresAtinteger | nullYaUnix timestamp dalam milidetik, bukan detik.
codestringTidakOpsional; field tidak dikirim bila belum ada kode terklasifikasi. SMS dapat diterima tanpa field ini. Jangan log OTP produksi.
smsTextstringTidakOpsional; isi SMS, termasuk teks/tautan tanpa kode. Berbeda dari message yang berisi status aplikasi. Jangan log SMS produksi.
canCancelbooleanYaIzin pembatalan pada saat respons dibuat. Server memeriksa ulang provider ketika aksi dikirim.
canCompletebooleanYaTrue pada CODE_RECEIVED, termasuk SMS tanpa kode. Jangan mensyaratkan code untuk menawarkan penyelesaian.
canResendbooleanTidakSesuai dukungan provider, setelah SMS diterima, sebelum kedaluwarsa, dan saat provider mengizinkan. Diperiksa ulang pada aksi; resend tidak mengubah harga atau saldo.
canReplacebooleanTidakSemua provider sebelum SMS, saat pembatalan diizinkan; provider berbasis capability juga memerlukan can_replace. UI mengonfirmasi harga terlebih dahulu, membatalkan lewat /cancel, lalu membeli pengganti lewat POST /api/orders hanya setelah pembatalan terkonfirmasi tanpa SMS. Bukan penggantian atomik; permintaan pembelian yang belum pasti diperiksa ulang dengan kunci idempotensi yang sama.
canProlongbooleanTidakTrue pada order selesai yang nomornya boleh diaktifkan ulang (saat ini server v4). Perpanjangan adalah pembelian berbayar dengan harga order ini; provider tetap dapat menolaknya, dan itu melepas saldo.
isProlongationbooleanTidakTrue pada order yang mengaktifkan ulang nomor lama, bukan membeli nomor baru. Order seperti ini tidak dapat diganti nomornya.
resendAvailableAtinteger | nullTidakCooldown provider untuk resend. Timer habis bukan izin; ikuti canResend terbaru.
smsRevisionintegerTidakRevisi pasangan agregat code/smsText dari provider berbasis revisi, atau revisi lokal kode baru dari polling handler API. SMS baru dapat mempertahankan kode sebelumnya; keduanya belum tentu berasal dari satu pesan.
messagestring | nullYaPesan status/kendala yang aman untuk ditampilkan, bukan isi SMS.
isPreparingbooleanYaTrue saat order masih CREATED atau PURCHASING.
cancelAvailableAtinteger | nullYaWaktu pembatalan paling cepat 3 menit setelah nomor aktif untuk semua server, atau lebih lama jika provider mensyaratkan. Null jika bukan ACTIVE atau izin eksplisit provider belum diketahui. Provider dapat menolak aksi; saldo hanya dilepas setelah pembatalan terkonfirmasi.

ping! · Panduan yang tumbuh bersama produknya.