Pesanan & SMS
Kontrak pembelian nomor, pembacaan SMS, pembatalan, dan penyelesaian order dengan perlindungan idempotensi.
Unduh OpenAPI 3.1Di halaman ini
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.
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.
Daftar pesanan
/api/ordersSession cookieSource : app/api/orders/route.ts
Semua order milik pengguna, terbaru lebih dahulu. Tidak ada parameter status, limit, offset, atau cursor. Endpoint daftar tidak melakukan polling provider; gunakan GET detail untuk order terbuka.
const response = await fetch("/api/orders", {
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;Buat pesanan
/api/ordersSession cookieSource : app/api/orders/route.ts
Menahan saldo lalu meminta nomor ke provider. HTTP 200 berarti request ditangani, bukan jaminan nomor langsung terbit; periksa status, isPreparing, phone, dan message. Respons memakai Order, bukan activation atau token provider.
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.
| Body JSON | Tipe | Wajib | Keterangan |
|---|---|---|---|
| serviceId | string | Ya | Gunakan Service.id dari GET /api/catalog/services. |
| countryId | string | Ya | Gunakan Country.id dari GET /api/catalog/countries. |
| clientRequestId | string · uuid | Ya | UUID per niat pembelian. Pertahankan UUID yang sama saat recovery request yang sama. |
| priceOptionId | string | Tidak | Quote.options[].id. Harus bersama expectedPriceIdr; direkomendasikan agar harga dikonfirmasi. |
| expectedPriceIdr | integer | Tidak | Quote.options[].price_idr yang disetujui pengguna. Harus bersama priceOptionId. |
const response = await fetch("/api/orders", {
method: "POST",
credentials: "same-origin",
cache: "no-store",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"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;| Kode error | HTTP | Tindakan |
|---|---|---|
| VALIDATION_ERROR | 400 | Periksa tipe, field wajib, format UUID, dan field tambahan. |
| INSUFFICIENT_BALANCE | 422 | Tampilkan available dari server dan tawarkan top-up. |
| PRICE_CHANGED | 409 | Ambil quote baru dan minta konfirmasi harga lagi. |
| PRICE_OPTION_UNAVAILABLE | 409 | Ambil quote baru; jangan menebak atau membuat priceOptionId. |
| PRICE_UNAVAILABLE | 422 | Tawarkan pasangan lain atau coba baca quote lagi nanti. |
| SERVICE_UNAVAILABLE | 422 | Muat ulang katalog dan pilih layanan yang tersedia. |
| COUNTRY_UNAVAILABLE | 422 | Muat ulang katalog dan pilih negara yang tersedia. |
| ACTIVE_ORDER_LIMIT | 429 | Selesaikan order yang ada; limit mengikuti pengaturan operator. |
| ORDER_RATE_LIMIT | 429 | Jeda percobaan. Jangan membuat loop POST. |
| PURCHASE_UNRESOLVED | 409 | Jangan membuat pembelian baru. Tunggu rekonsiliasi. |
| PROVIDER_ERROR | 502 | Baca ulang status. Jangan retry pembelian upstream secara otomatis. |
Baca pesanan & SMS
/api/orders/{id}Session cookieSource : app/api/orders/[id]/route.ts
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.
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
| id (path) | string | Ya | ID order milik pengguna bersesi. |
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;| Kode error | HTTP | Tindakan |
|---|---|---|
| NOT_FOUND | 404 | Periksa ID dan akun; ID resource tidak memberi akses lintas pengguna. |
| PROVIDER_ERROR | 502 | Baca ulang status. Jangan retry pembelian upstream secara otomatis. |
| RECONCILIATION_REQUIRED | 409 | Pertahankan hold; baca ulang status. Webhook Tiger dapat memakai HTTP 503 untuk kode ini. |
| PROVIDER_UNAVAILABLE | 503 | Periksa konfigurasi server; lanjutkan pembacaan dengan backoff. |
| PROVIDER_TIMEOUT | 504 | Hasil bisa ambigu. Pertahankan UUID dan hold, tunggu rekonsiliasi. |
Batalkan pesanan
/api/orders/{id}/cancelSession cookieSource : app/api/orders/[id]/cancel/route.ts
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.
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
| id (path) | string | Ya | ID order milik pengguna bersesi. |
Body wajib: {} dengan Content-Type: application/json. Tidak menerima field tambahan.
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;| Kode error | HTTP | Tindakan |
|---|---|---|
| NOT_FOUND | 404 | Periksa ID dan akun; ID resource tidak memberi akses lintas pengguna. |
| EARLY_CANCEL_DENIED | 409 | Baca ulang order dan ikuti canCancel serta cancelAvailableAt. |
| INVALID_STATE | 409 | GET detail order sebelum menawarkan aksi kembali. |
| ORDER_ALREADY_TERMINAL | 409 | Tampilkan hasil terkini dan perbarui saldo. |
| RECONCILIATION_REQUIRED | 409 | Pertahankan hold; baca ulang status. Webhook Tiger dapat memakai HTTP 503 untuk kode ini. |
| PROVIDER_TIMEOUT | 504 | Hasil bisa ambigu. Pertahankan UUID dan hold, tunggu rekonsiliasi. |
Selesaikan pesanan
/api/orders/{id}/completeSession cookieSource : app/api/orders/[id]/complete/route.ts
Menyelesaikan order setelah kode diterima; ikuti canComplete dari server. Kirim JSON {}. Settlement menangkap dana yang ditahan sekali saja. Sesudahnya, revalidasi order, akun, dan ledger.
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
| id (path) | string | Ya | ID order milik pengguna bersesi. |
Body wajib: {} dengan Content-Type: application/json. Tidak menerima field tambahan.
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;| Kode error | HTTP | Tindakan |
|---|---|---|
| NOT_FOUND | 404 | Periksa ID dan akun; ID resource tidak memberi akses lintas pengguna. |
| INVALID_STATE | 409 | GET detail order sebelum menawarkan aksi kembali. |
| ORDER_ALREADY_TERMINAL | 409 | Tampilkan hasil terkini dan perbarui saldo. |
| RECONCILIATION_REQUIRED | 409 | Pertahankan hold; baca ulang status. Webhook Tiger dapat memakai HTTP 503 untuk kode ini. |
Schema · Order
| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
| id | string | Ya | Sesuai tipe yang ditampilkan. |
| provider | tiger | smscode | Ya | tiger = Server 1 (Tiger SMS); smscode = Server 2 (smscode.gg). Katalog, harga, dan pesanan terikat ke server ini; tidak ada perpindahan otomatis. |
| countryId | string | Ya | Sesuai tipe yang ditampilkan. |
| serviceId | string | Ya | Sesuai tipe yang ditampilkan. |
| country | Country | Ya | Lihat schema Country pada OpenAPI. |
| service | Service | Ya | Lihat schema Service pada OpenAPI. |
| phone | string | Ya | Nomor, atau teks status ketika nomor belum/tidak diterbitkan. Periksa isPreparing. |
| price | integer | Ya | Harga IDR yang dibekukan saat order dibuat. |
| status | waiting | completed | cancelled | expired | failed | Ya | Status DTO client; tidak sama dengan enum database. |
| createdAt | integer | Ya | Unix timestamp dalam milidetik, bukan detik. |
| expiresAt | integer | null | Ya | Unix timestamp dalam milidetik, bukan detik. |
| code | string | Tidak | Opsional; field tidak dikirim bila belum ada kode terklasifikasi. SMS dapat diterima tanpa field ini. Jangan log OTP produksi. |
| smsText | string | Tidak | Opsional; isi SMS, termasuk teks/tautan tanpa kode. Berbeda dari message yang berisi status aplikasi. Jangan log SMS produksi. |
| canCancel | boolean | Ya | Izin pembatalan pada saat respons dibuat. Server memeriksa ulang provider ketika aksi dikirim. |
| canComplete | boolean | Ya | True pada CODE_RECEIVED, termasuk SMS tanpa kode. Jangan mensyaratkan code untuk menawarkan penyelesaian. |
| message | string | null | Ya | Pesan status/kendala yang aman untuk ditampilkan, bukan isi SMS. |
| isPreparing | boolean | Ya | True saat order masih CREATED atau PURCHASING. |
| cancelAvailableAt | integer | null | Ya | Batas pembatalan menurut server. Server 1 memakai cooldown lokal; Server 2 mengikuti kemampuan provider (0 bila sudah diizinkan). Null jika bukan ACTIVE atau waktu izin belum diketahui. |