Dokumentasi API
Akses programatik ke nomor virtual, pesanan, dan saldo akun.
⟩ Autentikasi
Semua permintaan API memerlukan Bearer token. Buat token dari Pengaturan Akun di dashboard, lalu sertakan di setiap permintaan:
Permintaan tanpa token yang valid akan menerima respons 401 UNAUTHORIZED.
⟩ Base URL
Semua path endpoint di bawah ini relatif terhadap:
⟩ Format Respons
Setiap respons mengembalikan JSON dengan envelope yang konsisten. Semua respons menyertakan header x-request-id untuk debugging.
{
"success": true,
"data": { ... }
} {
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable message"
}
} /catalog/countries Mengembalikan daftar semua negara yang tersedia.
Parameter
Tidak ada
Contoh Request
curl -s https://api.smscode.gg/v1/catalog/countries \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/catalog/countries", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/catalog/countries",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": [
{
"id": 6,
"code": "ID",
"name": "Indonesia",
"dial_code": "+62",
"emoji": "🇮🇩",
"active": true
}
]
} /catalog/services Mengembalikan daftar layanan (platform) yang tersedia. Opsional filter berdasarkan negara.
Query Parameter
| Nama | Tipe | Wajib | Deskripsi |
|---|---|---|---|
country_id | integer | Tidak | Filter layanan yang tersedia untuk negara ini |
Contoh Request
curl -s "https://api.smscode.gg/v1/catalog/services?country_id=6" \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/catalog/services?country_id=6", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/catalog/services",
params={"country_id": 6},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": [
{
"id": 3,
"code": "wa",
"name": "WhatsApp",
"active": true
}
]
} /catalog/products Mengembalikan daftar produk yang tersedia secara berpaginasi. Filter berdasarkan negara dan/atau platform.
Query Parameter
| Nama | Tipe | Wajib | Deskripsi |
|---|---|---|---|
country_id | integer | Tidak | Filter berdasarkan ID negara |
platform_id | integer | Tidak | Filter berdasarkan ID platform/layanan |
sort | string | Tidak | Urutan: price_asc (default), price_desc, available_asc, available_desc, name_asc, name_desc |
limit | integer | Tidak | Hasil per halaman (1-10.000, default 1.000) |
page | integer | Tidak | Nomor halaman (min 1, default 1) |
Contoh Request
curl -s "https://api.smscode.gg/v1/catalog/products?country_id=6&platform_id=3&limit=10&page=1" \
-H "Authorization: Bearer YOUR_API_TOKEN" const params = new URLSearchParams({
country_id: "6", platform_id: "3", limit: "10", page: "1",
});
const res = await fetch(`https://api.smscode.gg/v1/catalog/products?${params}`, {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/catalog/products",
params={"country_id": 6, "platform_id": 3, "limit": 10, "page": 1},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": [
{
"id": 142,
"name": "WhatsApp Indonesia",
"country_id": 6,
"platform_id": 3,
"available": 42,
"price": 15000,
"active": true
}
],
"meta": { "page": 1, "limit": 10, "count": 1 }
} /catalog/exchange-rate Mengembalikan kurs tukar terkini untuk pasangan mata uang. Berguna untuk konversi harga.
Query Parameter
| Nama | Tipe | Wajib | Deskripsi |
|---|---|---|---|
pair | string | Tidak | Pasangan mata uang (default: USD/IDR) |
Contoh Request
curl -s "https://api.smscode.gg/v1/catalog/exchange-rate?pair=USD/IDR" \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/catalog/exchange-rate?pair=USD/IDR", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/catalog/exchange-rate",
params={"pair": "USD/IDR"},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": {
"pair": "USD/IDR",
"base_currency": "USD",
"quote_currency": "IDR",
"rate": 16250
}
} /balance Mengembalikan saldo akun pengguna yang terautentikasi dalam IDR.
Parameter
Tidak ada
Contoh Request
curl -s https://api.smscode.gg/v1/balance \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/balance", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/balance",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": {
"currency": "IDR",
"balance": 500000
}
} /orders Mengembalikan daftar pesanan pengguna yang terautentikasi, diurutkan dari yang terbaru. Mendukung filter berdasarkan status dan paginasi via offset.
Query Parameter
| Nama | Tipe | Wajib | Deskripsi |
|---|---|---|---|
limit | integer | Tidak | Maksimal hasil (1-100, default 20) |
offset | integer | Tidak | Jumlah hasil yang dilewati (default 0) |
status | string | Tidak | Filter berdasarkan status: ACTIVE, OTP_RECEIVED, COMPLETED, CANCELED, EXPIRED (tidak peka huruf besar/kecil) |
Contoh Request
curl -s "https://api.smscode.gg/v1/orders?limit=5&status=ACTIVE" \
-H "Authorization: Bearer YOUR_API_TOKEN" const params = new URLSearchParams({
limit: "5", status: "ACTIVE", offset: "0",
});
const res = await fetch(`https://api.smscode.gg/v1/orders?${params}`, {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/orders",
params={"limit": 5, "status": "ACTIVE", "offset": 0},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": [
{
"id": 1001,
"status": "ACTIVE",
"created_at": "2026-02-25T10:00:00Z",
"product_id": 142,
"phone_number": "+6281234567890",
"amount": 15000,
"otp_code": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:20:00Z",
"canceled_at": null,
"failed_reason": null
}
]
} /orders/{id} Mengembalikan satu pesanan berdasarkan ID. Hanya mengembalikan pesanan milik pengguna yang terautentikasi.
Path Parameter
| Nama | Tipe | Wajib | Deskripsi |
|---|---|---|---|
id | integer | Ya | ID Pesanan (path parameter) |
Contoh Request
curl -s https://api.smscode.gg/v1/orders/1001 \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/orders/1001", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/orders/1001",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": {
"id": 1001,
"status": "OTP_RECEIVED",
"created_at": "2026-02-25T10:00:00Z",
"product_id": 142,
"phone_number": "+6281234567890",
"amount": 15000,
"otp_code": "123456",
"otp_received_at": "2026-02-25T10:05:00Z",
"expires_at": "2026-02-25T10:20:00Z",
"canceled_at": null,
"failed_reason": null
}
} /orders/active Daftar semua pesanan yang sedang aktif (ACTIVE + OTP_RECEIVED). Gunakan ini untuk polling pembaruan status OTP.
Parameter
Tidak ada
Contoh Request
curl -s https://api.smscode.gg/v1/orders/active \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/orders/active", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/orders/active",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": [
{
"id": 1001,
"status": "OTP_RECEIVED",
"otp_code": "123456",
"otp_message": "Your verification code is 123456",
"otp_received_at": "2026-02-25T10:05:00Z",
"expires_at": "2026-02-25T10:20:00Z",
"failed_reason": null
},
{
"id": 1002,
"status": "ACTIVE",
"otp_code": null,
"otp_message": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:50:00Z",
"failed_reason": null
}
]
} /orders/create Membuat pesanan nomor virtual baru. Memotong saldo secara otomatis. Mendukung header Idempotency-Key opsional untuk mencegah pesanan duplikat saat retry jaringan.
Request Body
| Nama | Tipe | Wajib | Deskripsi |
|---|---|---|---|
product_id | integer | Ya | ID produk yang akan dipesan |
quantity | integer | Tidak | Jumlah item (1-100, default 1) |
Kirim header Idempotency-Key (string unik apa pun) untuk melakukan retry dengan aman tanpa membuat pesanan duplikat.
Contoh Request
curl -s -X POST https://api.smscode.gg/v1/orders/create \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-request-id-123" \
-d '{"product_id":142,"quantity":1}' const res = await fetch("https://api.smscode.gg/v1/orders/create", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
"Idempotency-Key": "unique-request-id-123",
},
body: JSON.stringify({ product_id: 142, quantity: 1 }),
});
const data = await res.json(); import requests
res = requests.post("https://api.smscode.gg/v1/orders/create",
json={"product_id": 142, "quantity": 1},
headers={
"Authorization": "Bearer YOUR_API_TOKEN",
"Idempotency-Key": "unique-request-id-123",
})
data = res.json() Contoh Response
{
"success": true,
"data": {
"orders": [
{
"id": 1002,
"status": "ACTIVE",
"phone_number": "+6281234567891",
"otp_code": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:50:00Z",
"failed_reason": null
}
],
"failed_count": 0
}
} /orders/cancel Membatalkan pesanan yang aktif. Biaya sewa dikembalikan ke saldo akun kamu.
Request Body
| Nama | Tipe | Wajib | Deskripsi |
|---|---|---|---|
id | integer | Ya | ID Pesanan yang akan dibatalkan |
Contoh Request
curl -s -X POST https://api.smscode.gg/v1/orders/cancel \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id":1001}' const res = await fetch("https://api.smscode.gg/v1/orders/cancel", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ id: 1001 }),
});
const data = await res.json(); import requests
res = requests.post("https://api.smscode.gg/v1/orders/cancel",
json={"id": 1001},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": {
"order_id": 1001,
"status": "CANCELED",
"refund_amount": 15000,
"new_balance": 515000
}
} /orders/finish Tandai pesanan sebagai selesai setelah menerima OTP. Ini melepaskan nomor segera alih-alih menunggu kedaluwarsa.
Request Body
| Nama | Tipe | Wajib | Deskripsi |
|---|---|---|---|
id | integer | Ya | ID Pesanan yang akan diselesaikan |
Contoh Request
curl -s -X POST https://api.smscode.gg/v1/orders/finish \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id":1001}' const res = await fetch("https://api.smscode.gg/v1/orders/finish", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ id: 1001 }),
});
const data = await res.json(); import requests
res = requests.post("https://api.smscode.gg/v1/orders/finish",
json={"id": 1001},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": {
"order_id": 1001,
"status": "COMPLETED"
}
} /orders/resend Minta platform untuk mengirim ulang SMS ke nomor yang disewa. Tidak semua platform mendukung pengiriman ulang — periksa field resent di respons.
Request Body
| Nama | Tipe | Wajib | Deskripsi |
|---|---|---|---|
id | integer | Ya | ID Pesanan untuk pengiriman ulang SMS |
Contoh Request
curl -s -X POST https://api.smscode.gg/v1/orders/resend \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id":1001}' const res = await fetch("https://api.smscode.gg/v1/orders/resend", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ id: 1001 }),
});
const data = await res.json(); import requests
res = requests.post("https://api.smscode.gg/v1/orders/resend",
json={"id": 1001},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": {
"order_id": 1001,
"status": "ACTIVE",
"resent": true
}
} /webhook Mengembalikan konfigurasi notifikasi webhook kamu saat ini.
Parameter
Tidak ada
Contoh Request
curl -s https://api.smscode.gg/v1/webhook \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/webhook", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/webhook",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} /webhook Perbarui URL dan/atau secret webhook kamu. Secret dibuat otomatis saat kamu menetapkan URL untuk pertama kali. Kirim string kosong untuk menghapus. URL harus menggunakan HTTPS.
Request Body
| Nama | Tipe | Wajib | Deskripsi |
|---|---|---|---|
webhook_url | string | Tidak | URL HTTPS untuk menerima event webhook (string kosong untuk menghapus) |
webhook_secret | string | Tidak | Shared secret untuk tanda tangan HMAC-SHA256 (dibuat otomatis jika tidak disertakan saat pertama kali) |
Minimal satu field wajib diisi.
Contoh Request
curl -s -X PATCH https://api.smscode.gg/v1/webhook \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"webhook_url":"https://example.com/webhook"}' const res = await fetch("https://api.smscode.gg/v1/webhook", {
method: "PATCH",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ webhook_url: "https://example.com/webhook" }),
});
const data = await res.json(); import requests
res = requests.patch("https://api.smscode.gg/v1/webhook",
json={"webhook_url": "https://example.com/webhook"},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} /webhook/test Kirim event tes ke URL webhook yang sudah dikonfigurasi. Mengembalikan kode status HTTP dari server kamu. Berguna untuk memverifikasi endpoint berfungsi sebelum go live.
Parameter
Tidak ada
Contoh Request
curl -s -X POST https://api.smscode.gg/v1/webhook/test \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/webhook/test", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.post("https://api.smscode.gg/v1/webhook/test",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Contoh Response
{
"success": true,
"data": {
"status_code": 200
}
} ⟩ Notifikasi Webhook
Konfigurasi URL webhook untuk menerima notifikasi push real-time untuk event pesanan alih-alih polling. Ini adalah pendekatan yang direkomendasikan untuk bot script.
Event
| Event | Pemicu |
|---|---|
order.otp_received | Kode OTP terkirim ke nomor yang disewa |
order.completed | Pesanan ditandai selesai (manual atau kedaluwarsa) |
order.expired | Pesanan kedaluwarsa tanpa OTP (saldo dikembalikan) |
order.canceled | Pesanan dibatalkan oleh pengguna (saldo dikembalikan) |
Payload
{
"event": "order.otp_received",
"timestamp": "2026-02-25T12:00:00Z",
"data": {
"order_id": 1001,
"phone_number": "+628123456789",
"otp_code": "1234",
"otp_message": "Your verification code is 1234",
"product_id": 42,
"country": "Indonesia",
"platform": "WhatsApp"
}
} Verifikasi Tanda Tangan
Setiap permintaan webhook menyertakan header X-Webhook-Signature dengan tanda tangan HMAC-SHA256 dari body permintaan, menggunakan webhook_secret kamu sebagai kunci:
Verifikasi tanda tangan ini di server kamu untuk memastikan permintaan autentik. Pengiriman bersifat fire-and-forget dengan timeout 3 detik dan tanpa retry.
⟩ Rate Limit
Permintaan API dibatasi per grup endpoint. Melebihi batas mengembalikan 429 Too Many Requests dengan header Retry-After yang menunjukkan berapa detik harus menunggu.
| Grup Endpoint | Batas | Jendela Waktu |
|---|---|---|
| Katalog (countries, services, products, exchange-rate) | 1.200 permintaan | 60 detik |
| Saldo | 600 permintaan | 60 detik |
| Baca pesanan (list, get, active) | 1.200 permintaan | 60 detik |
| Buat pesanan | 1.200 permintaan | 60 detik |
| Batalkan pesanan | 600 permintaan | 60 detik |
| Aksi pesanan (finish, resend) | 600 permintaan | 60 detik |
| Konfigurasi webhook (get, update, test) | 120 permintaan | 60 detik |
⟩ Kode Error
Respons error menyertakan salah satu kode berikut di error.code:
| Kode | HTTP | Deskripsi |
|---|---|---|
UNAUTHORIZED | 401 | Token API tidak ada atau tidak valid |
FORBIDDEN | 403 | Akses ditolak |
NOT_FOUND | 404 | Sumber daya tidak ditemukan (pesanan, kurs tukar, dll.) |
CONFLICT | 409 | Permintaan duplikat atau konflik sumber daya |
INSUFFICIENT_BALANCE | 409 | Saldo tidak cukup untuk membuat pesanan |
VALIDATION_ERROR | 422 | Parameter permintaan gagal validasi |
RATE_LIMIT_EXCEEDED | 429 | Terlalu banyak permintaan (cek header Retry-After) |
INTERNAL_ERROR | 500 | Kesalahan server internal |
PROVIDER_ERROR | 422 | Penyedia SMS upstream menolak permintaan |
CANCEL_TOO_EARLY | 409 | Pesanan terlalu baru untuk dibatalkan — tunggu 2 menit |
SERVICE_UNAVAILABLE | 503 | Layanan sementara tidak tersedia (pemeliharaan) |