API Belgeleri
Sanal numaralara, siparişlere ve hesap bakiyesine programatik erişim.
Genel Bakis
/v1 API'sindeki tüm para alanları IDR cinsindendir (Endonezya Rupisi), tam sayı birimleri olarak — örneğin "price": 15000 ve "balance": 500000, Rp 15.000 ve Rp 500.000 anlamına gelir. Aynı defterin USD-native projeksiyonu için yukarıdaki sürüm anahtarıyla v2 API'sine geçin.
⟩Kimlik Doğrulama
Tüm API istekleri bir Bearer token gerektirir. Paneldeki Hesap Ayarları'ndan bir tane oluşturun ve her istekte ekleyin:
Geçerli bir token içermeyen istekler 401 UNAUTHORIZED yanıtı alır.
⟩Temel URL
Aşağıdaki tüm endpoint yolları şuna görelidir:
⟩Yanıt Formatı
Her yanıt tutarlı bir zarfla JSON döndürür. Tüm yanıtlar hata ayıklama için bir x-request-id başlığı içerir.
{
"success": true,
"data": { ... }
} {
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable message"
}
} /v1 API'sindeki tüm para alanları IDR cinsindendir (Endonezya Rupisi), tam sayı birimleri olarak — örneğin "price": 15000 ve "balance": 500000, Rp 15.000 ve Rp 500.000 anlamına gelir. Aynı defterin USD-native projeksiyonu için yukarıdaki sürüm anahtarıyla v2 API'sine geçin.
/catalog/countries Tüm mevcut ülkelerin listesini döndürür.
Parametreler
Yok
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": [
{
"id": 6,
"code": "ID",
"name": "Indonesia",
"dial_code": "+62",
"emoji": "🇮🇩",
"active": true
}
]
} /catalog/services Mevcut hizmetlerin (platformların) listesini döndürür. İsteğe bağlı olarak ülkeye göre filtreleyin.
Sorgu Parametreleri
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
country_id | integer | Hayır | Bu ülke için mevcut hizmetleri filtrele |
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": [
{
"id": 3,
"code": "wa",
"name": "WhatsApp",
"active": true
}
]
} /catalog/products Mevcut ürünlerin sayfalanmış listesini döndürür. Ülke ve/veya platforma göre filtreleyin.
Sorgu Parametreleri
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
country_id | integer | Hayır | Ülke kimliğine göre filtrele |
platform_id | integer | Hayır | Platform/hizmet kimliğine göre filtrele |
sort | string | Hayır | Sıralama: price_asc (varsayılan), price_desc, available_asc, available_desc, name_asc, name_desc |
limit | integer | Hayır | Sayfa başına sonuç (1-10.000, varsayılan 1.000) |
page | integer | Hayır | Sayfa numarası (min 1, varsayılan 1) |
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": [
{
"id": 142,
"name": "WhatsApp Indonesia",
"country_id": 6,
"platform_id": 3,
"catalog_product_id": 87,
"available": 42,
"price": 15000,
"active": true
}
],
"meta": { "page": 1, "limit": 10, "count": 1 }
} /catalog/exchange-rate Para birimi dönüşümü için kullanılan güncel USD/IDR döviz kurunu döndürür.
Sorgu Parametreleri
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
pair | string | Hayır | Döviz çifti (varsayılan: USD/IDR) |
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": {
"pair": "USD/IDR",
"base_currency": "USD",
"quote_currency": "IDR",
"rate": 16250
}
} /balance Kimliği doğrulanmış kullanıcının hesap bakiyesini döndürür.
Parametreler
Yok
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": {
"currency": "IDR",
"balance": 500000
}
} /orders Kimliği doğrulanmış kullanıcının siparişlerini en yeniden eskiye sıralı olarak döndürür. Duruma göre filtreleme ve offset ile sayfalamayı destekler.
Sorgu Parametreleri
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
limit | integer | Hayır | Maksimum sonuç (1-100, varsayılan 20) |
offset | integer | Hayır | Atlanacak sonuç sayısı (varsayılan 0) |
status | string | Hayır | Duruma göre filtrele: ACTIVE, OTP_RECEIVED, COMPLETED, CANCELED, EXPIRED (büyük/küçük harf duyarsız) |
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": [
{
"id": 1001,
"status": "ACTIVE",
"created_at": "2026-02-25T10:00:00+00:00",
"product_id": 142,
"phone_number": "+6281234567890",
"amount": 15000,
"otp_code": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:20:00+00:00",
"canceled_at": null,
"failed_reason": null
}
]
} /orders/{id} Kimliğe göre tek bir siparişi döndürür. Yalnızca kimliği doğrulanmış kullanıcıya ait siparişleri döndürür.
Yol Parametreleri
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
id | integer | Evet | Sipariş kimliği (yol parametresi) |
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": {
"id": 1001,
"status": "OTP_RECEIVED",
"created_at": "2026-02-25T10:00:00+00:00",
"product_id": 142,
"phone_number": "+6281234567890",
"amount": 15000,
"otp_code": "123456",
"otp_received_at": "2026-02-25T10:05:00+00:00",
"expires_at": "2026-02-25T10:20:00+00:00",
"canceled_at": null,
"failed_reason": null
}
} /orders/active Tüm aktif siparişleri (ACTIVE + OTP_RECEIVED) listeler. OTP durumu güncellemelerini sorgulamak için kullanın.
Parametreler
Yok
Örnek İstek
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()Örnek Yanıt
{
"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:00+00:00",
"expires_at": "2026-02-25T10:20:00+00:00",
"failed_reason": null
},
{
"id": 1002,
"status": "ACTIVE",
"otp_code": null,
"otp_message": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:50:00+00:00",
"failed_reason": null
}
]
} /orders/create Yeni bir sanal numara siparişi oluşturur. Bakiyeyi otomatik olarak düşer. Ağ yeniden denemelerinde yinelenen siparişleri önlemek için isteğe bağlı Idempotency-Key başlığını destekler.
İstek Gövdesi
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
product_id | integer | Hayır | Sipariş verilecek ürün kimliği. YALNIZCA BİRİNİ girin: product_id VEYA catalog_product_id, ikisini birden değil. |
catalog_product_id | integer | Hayır | Kararlı ürün kimliği — sunucu mevcut en iyi teklifi seçer (en ucuz, güvenilirliği gözeterek). Bunu veya product_id'yi girin. |
max_price | integer · string | Hayır | İsteğe bağlı fiyat üst sınırı. v1: IDR tam sayı. v2: USD ondalık dizesi (örn. "0.50"). |
prefer_provider | string | Hayır | Teklifler eşit olduğunda tercih edilecek isteğe bağlı sağlayıcı kodu. |
policy | string | Hayır | İsteğe bağlı yönlendirme politikası, yalnızca catalog_product_id ile geçerlidir. Değerler: cheapest (varsayılan) en düşük fiyatlı sağlıklı teklifi seçer; best_success teklifleri önce son teslim başarısına göre sıralar. best_success her sağlayıcıyı son 30 tamamlanmış gün içinde OTP alan siparişlerin oranına göre %10'luk dilimlerde puanlar ve bir sağlayıcıyı ancak o aralıkta en az 20 siparişi olduğunda sayar — bu eşiğin altındaki veya geçmişi olmayan sağlayıcılar nötr kabul edilir, böylece yeni teklifler asla geri planda kalmaz (tercihe bağlı; sinyal nötr başlar). prefer_provider de ayarlandıysa tercih edilen sağlayıcı yine ilk sırada kalır. |
quantity | integer | Hayır | Adet sayısı (1-100, varsayılan 1) |
Yinelenen siparişler oluşturmadan güvenle yeniden deneme yapmak için Idempotency-Key başlığı gönderin. Anahtar harf, rakam, tire ve alt çizgi (A-Z a-z 0-9 _ -) içerebilir, en fazla 128 karakter; geçersiz bir anahtar 422 VALIDATION_ERROR ile reddedilir. Aynı anahtar ve aynı gövde ile yeniden deneme, orijinal sonucu yeniden döndürür (kısmi başarıdaki failed_count dahil). Sağlayıcıya ulaşan ama başarısız olan bir yeniden deneme kaydedilir ve tekrar denendiğinde aynı hatayı döndürür — yeni bir deneme için YENİ bir anahtar kullanın. Yan etkisi olmayan hatalar (yetersiz bakiye, uygun teklif yok) anahtarı serbest bırakır, böylece bakiye yükleyip aynı anahtarla yeniden deneyebilirsiniz. Bir anahtarı farklı bir gövde ile yeniden kullanmak 422 IDEMPOTENCY_KEY_REUSED döndürür ve bu anahtarla hâlâ devam eden bir istek 409 REQUEST_IN_PROGRESS döndürür. create yanıtlarındaki failed_reason alanı her zaman null'dur — yalnızca sipariş sorgulama/listeleme sırasında doldurulur.
Örnek İstek
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}'
# Or order by stable catalog_product_id — the server picks the best current offer
# (cheapest, reliability-aware). Optional max_price caps the price; on v1 it is an
# IDR integer, on v2 it is a USD decimal string (e.g. "0.50"). prefer_provider
# (provider code) is a soft tie-breaker. Pass EITHER product_id OR catalog_product_id.
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-124" \
-d '{"catalog_product_id":87,"max_price":20000}'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()Örnek Yanıt
{
"success": true,
"data": {
"orders": [
{
"id": 1002,
"status": "ACTIVE",
"product_id": 142,
"catalog_product_id": 87,
"amount": 15000,
"phone_number": "+6281234567891",
"otp_code": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:50:00+00:00",
"failed_reason": null
}
],
"failed_count": 0
}
} /orders/cancel Aktif bir siparişi iptal eder. Kiralama bedeli hesap bakiyenize iade edilir.
İstek Gövdesi
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
id | integer | Evet | İptal edilecek sipariş kimliği |
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": {
"order_id": 1001,
"status": "CANCELED",
"refund_amount": 15000,
"new_balance": 515000
}
} /orders/finish OTP alındıktan sonra siparişi tamamlandı olarak işaretler. Süre dolmasını beklemek yerine numarayı hemen serbest bırakır.
İstek Gövdesi
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
id | integer | Evet | Tamamlanacak sipariş kimliği |
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": {
"order_id": 1001,
"status": "COMPLETED"
}
} /orders/resend Platformdan kiralanan numaraya SMS'i yeniden göndermesini ister. Tüm platformlar yeniden gönderimi desteklemez — yanıttaki resent alanını kontrol edin.
İstek Gövdesi
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
id | integer | Evet | SMS yeniden gönderilecek sipariş kimliği |
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": {
"order_id": 1001,
"status": "ACTIVE",
"resent": true
}
} /webhook Mevcut webhook bildirim yapılandırmanızı döndürür.
Parametreler
Yok
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} /webhook Webhook URL'nizi ve/veya gizli anahtarınızı güncelleyin. İlk kez URL belirlediğinizde gizli anahtar otomatik oluşturulur. Temizlemek için boş dize gönderin. URL HTTPS kullanmalıdır.
İstek Gövdesi
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
webhook_url | string | Hayır | Webhook olaylarını alacak HTTPS URL'si (temizlemek için boş dize) |
webhook_secret | string | Hayır | HMAC-SHA256 imzası için paylaşılan gizli anahtar (ilk ayarlamada belirtilmezse otomatik oluşturulur) |
En az bir alan gereklidir.
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} /webhook/test Yapılandırılmış webhook URL'nize bir test olayı gönderir. Sunucunuzdan dönen HTTP durum kodunu döndürür. Canlıya geçmeden önce endpoint'inizin çalıştığını doğrulamak için kullanışlıdır.
Parametreler
Yok
Örnek İstek
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()Örnek Yanıt
{
"success": true,
"data": {
"status_code": 200
}
} ⟩Webhook Bildirimleri
Polling yerine sipariş olayları için gerçek zamanlı push bildirimleri almak üzere bir webhook URL'si yapılandırın. Bu, bot betikleri için önerilen yaklaşımdır.
Olaylar
| Olay | Tetikleyici |
|---|---|
order.otp_received | Kiralanan numaraya OTP kodu teslim edildi |
order.completed | Sipariş tamamlandı olarak işaretlendi (manuel olarak veya süre dolmasıyla) |
order.expired | Sipariş OTP alınmadan süresi doldu (bakiye iade edildi) |
order.canceled | Sipariş kullanıcı tarafından iptal edildi (bakiye iade edildi) |
Veri Yükü
{
"event": "order.otp_received",
"timestamp": "2026-02-25T12:00:00+00:00",
"data": {
"order_id": 1001,
"phone_number": "+628123456789",
"otp_code": "1234",
"otp_message": "Your verification code is 1234",
"product_id": 42,
"catalog_product_id": 87,
"country": "Indonesia",
"platform": "WhatsApp"
}
} İmza Doğrulama
Her webhook isteği, webhook_secret'ınızı anahtar olarak kullanarak istek gövdesinin HMAC-SHA256 imzasını içeren bir X-Webhook-Signature başlığı içerir:
İsteğin gerçek olduğundan emin olmak için bu imzayı sunucunuzda doğrulayın. Teslim, 3 saniyelik zaman aşımıyla tek seferlik gönderimdir ve yeniden deneme yapılmaz.
⟩Rate Limit'ler
API isteklerine endpoint grubuna göre rate limit uygulanır. Limiti aşmak, kaç saniye bekleneceğini belirten bir Retry-After başlığıyla birlikte 429 Too Many Requests döndürür.
| Endpoint Grubu | Limit | Pencere |
|---|---|---|
| Katalog (ülkeler, hizmetler, ürünler, döviz kuru) | 5.000 istek | 60 saniye |
| Bakiye | 600 istek | 60 saniye |
| Sipariş okumaları (liste, tekil, aktif) | 5.000 istek | 60 saniye |
| Sipariş oluşturma | 3.000 istek | 60 saniye |
| Sipariş iptali | 1.000 istek | 60 saniye |
| Sipariş işlemleri (tamamla, yeniden gönder) | 1.000 istek | 60 saniye |
| Webhook yapılandırması (al, güncelle) | 600 istek | 60 saniye |
| Webhook testi | 10 istek | 60 saniye |
⟩Hata Kodları
error.code içinde aşağıdaki kodlardan biri yer alır:
| Kod | HTTP | Açıklama |
|---|---|---|
UNAUTHORIZED | 401 | Eksik veya geçersiz API token |
FORBIDDEN | 403 | Erişim reddedildi |
NOT_FOUND | 404 | Kaynak bulunamadı (sipariş, döviz kuru vb.) |
CONFLICT | 409 | Yinelenen istek veya kaynak çakışması |
INSUFFICIENT_BALANCE | 409 | Sipariş oluşturmak için yeterli bakiye yok |
VALIDATION_ERROR | 422 | İstek parametreleri doğrulamayı geçemedi |
RATE_LIMIT_EXCEEDED | 429 | Çok fazla istek (Retry-After başlığını kontrol edin) |
INTERNAL_ERROR | 500 | Sunucu iç hatası |
PROVIDER_ERROR | 422 | Üst düzey SMS sağlayıcısı isteği reddetti. Sipariş oluşturma başarısız olduğunda hata <code>details</code> taşıyabilir: <code>cause_counts</code> (eski <code>product_id</code> siparişleri — nedene göre gruplanmış bir sayım) veya <code>attempts</code> (<code>catalog_product_id</code> siparişleri — deneme başına sonuçlar), şu değerlerle: <code>ok</code>, <code>no_numbers</code>, <code>insufficient_balance</code>, <code>price_rejected</code>, <code>provider_unavailable</code>, <code>provider_account_balance</code>, <code>provider_error</code>. |
NO_OFFER_AVAILABLE | 422 | İstenen ürün ve politikaya (fiyat üst sınırı, stok durumu) uyan etkin bir teklif yok. |
CANCEL_TOO_EARLY | 409 | Sipariş iptal etmek için çok yeni — 2 dakika bekleyin |
REQUEST_IN_PROGRESS | 409 | Bu idempotency anahtarıyla bir oluşturma isteği hâlâ devam ediyor |
IDEMPOTENCY_KEY_REUSED | 422 | Bu idempotency anahtarı zaten farklı bir istek gövdesiyle kullanıldı |
SERVICE_UNAVAILABLE | 503 | Hizmet geçici olarak kullanılamıyor (bakım) |
Genel Bakis
/v2 API'sindeki tüm para alanları USD cinsindendir ve bir para nesnesi olarak döndürülür — { "amount": "0.92", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" }. amount ondalık bir dizedir; canonical_amount tam IDR defter değeridir (mutabakat için bunu kullanın). Uygulanan USD/IDR rate değeri yanıt başına bir kez meta.fx içinde açıklanır. v2, v1 ile aynı IDR defteri üzerinde render zamanlı bir USD projeksiyonudur — asla USD saklamaz veya işleme almaz.
⟩Kimlik Doğrulama
Tüm API istekleri bir Bearer token gerektirir. Paneldeki Hesap Ayarları'ndan bir tane oluşturun ve her istekte ekleyin:
Geçerli bir token içermeyen istekler 401 UNAUTHORIZED yanıtı alır.
⟩Temel URL
Aşağıdaki tüm endpoint yolları şuna görelidir:
⟩Yanıt Formatı
Her yanıt tutarlı bir zarfla JSON döndürür. Tüm yanıtlar hata ayıklama için bir x-request-id başlığı içerir.
{
"success": true,
"data": { ... }
} {
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable message"
}
} v2 hatası: kullanılabilir döviz kuru yok (503)
{
"success": false,
"error": { "code": "FX_RATE_UNAVAILABLE", "message": "USD/IDR exchange rate is unavailable" }
} /v2 API'sindeki tüm para alanları USD cinsindendir ve bir para nesnesi olarak döndürülür — { "amount": "0.92", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" }. amount ondalık bir dizedir; canonical_amount tam IDR defter değeridir (mutabakat için bunu kullanın). Uygulanan USD/IDR rate değeri yanıt başına bir kez meta.fx içinde açıklanır. v2, v1 ile aynı IDR defteri üzerinde render zamanlı bir USD projeksiyonudur — asla USD saklamaz veya işleme almaz.
/catalog/countries Tüm mevcut ülkelerin listesini döndürür.
Parametreler
Yok
Örnek İstek
curl -s https://api.smscode.gg/v2/catalog/countries \
-H "Authorization: Bearer YOUR_API_TOKEN"const res = await fetch("https://api.smscode.gg/v2/catalog/countries", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();import requests
res = requests.get("https://api.smscode.gg/v2/catalog/countries",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": [
{
"id": 6,
"code": "ID",
"name": "Indonesia",
"dial_code": "+62",
"emoji": "🇮🇩",
"active": true
}
]
} v1 ile aynı — yalnızca temel yol değişir (/v1 → /v2).
/catalog/services Mevcut hizmetlerin (platformların) listesini döndürür. İsteğe bağlı olarak ülkeye göre filtreleyin.
Sorgu Parametreleri
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
country_id | integer | Hayır | Bu ülke için mevcut hizmetleri filtrele |
Örnek İstek
curl -s "https://api.smscode.gg/v2/catalog/services?country_id=6" \
-H "Authorization: Bearer YOUR_API_TOKEN"const res = await fetch("https://api.smscode.gg/v2/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/v2/catalog/services",
params={"country_id": 6},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": [
{
"id": 3,
"code": "wa",
"name": "WhatsApp",
"active": true
}
]
} v1 ile aynı — yalnızca temel yol değişir (/v1 → /v2).
/catalog/products Mevcut ürünlerin sayfalanmış listesini döndürür. Ülke ve/veya platforma göre filtreleyin.
Sorgu Parametreleri
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
country_id | integer | Hayır | Ülke kimliğine göre filtrele |
platform_id | integer | Hayır | Platform/hizmet kimliğine göre filtrele |
sort | string | Hayır | Sıralama: price_asc (varsayılan), price_desc, available_asc, available_desc, name_asc, name_desc |
limit | integer | Hayır | Sayfa başına sonuç (1-10.000, varsayılan 1.000) |
page | integer | Hayır | Sayfa numarası (min 1, varsayılan 1) |
Örnek İstek
curl -s "https://api.smscode.gg/v2/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/v2/catalog/products?${params}`, {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();import requests
res = requests.get("https://api.smscode.gg/v2/catalog/products",
params={"country_id": 6, "platform_id": 3, "limit": 10, "page": 1},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": [
{
"id": 142,
"name": "WhatsApp Indonesia",
"country_id": 6,
"platform_id": 3,
"catalog_product_id": 87,
"available": 42,
"price": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
"active": true
}
],
"meta": { "page": 1, "limit": 10, "count": 1, "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
} v2: para alanları USD para nesneleridir ve yanıt tek bir meta.fx { pair, rate, rate_as_of } taşır. rate, 1 USD başına tam sayı IDR'dir, dolayısıyla USD = canonical_amount / rate. Toplamlar 2 ondalık; kalem başına fiyatlar/iadeler 4 ondalık kullanır. Kesinlikle pozitif bir tutar asla 0.00'a yuvarlanmaz. rate_as_of, kurun RFC3339 zaman damgasıdır (+00:00 biçimi) veya kaydedilmiş bir zaman damgası yoksa null'dur.
Yalnızca v2: kullanılabilir bir USD/IDR kuru yoksa, para endpoint'leri bir para gövdesi yerine Retry-After başlığıyla 503 FX_RATE_UNAVAILABLE döndürür. v1 bunu asla döndürmez.
/catalog/exchange-rate Para birimi dönüşümü için kullanılan güncel USD/IDR döviz kurunu döndürür.
Parametreler
Yok — v2 her zaman USD/IDR döndürür; v1'in ?pair parametresi yok sayılır.
Örnek İstek
curl -s "https://api.smscode.gg/v2/catalog/exchange-rate?pair=USD/IDR" \
-H "Authorization: Bearer YOUR_API_TOKEN"const res = await fetch("https://api.smscode.gg/v2/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/v2/catalog/exchange-rate",
params={"pair": "USD/IDR"},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" }
} v2: { pair, rate, rate_as_of } döndürür (base_currency/quote_currency yok, meta sarmalayıcısı yok — kurun kendisi veridir). ?pair yok sayılır — v2 her zaman USD/IDR döndürür (v1, ?pair'i dikkate alır). Kullanılabilir bir kur yoksa 503 FX_RATE_UNAVAILABLE döndürür.
/balance Kimliği doğrulanmış kullanıcının hesap bakiyesini döndürür.
Parametreler
Yok
Örnek İstek
curl -s https://api.smscode.gg/v2/balance \
-H "Authorization: Bearer YOUR_API_TOKEN"const res = await fetch("https://api.smscode.gg/v2/balance", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();import requests
res = requests.get("https://api.smscode.gg/v2/balance",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": {
"balance": { "amount": "30.77", "currency": "USD", "canonical_amount": 500000, "canonical_currency": "IDR" }
},
"meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
} v2: para alanları USD para nesneleridir ve yanıt tek bir meta.fx { pair, rate, rate_as_of } taşır. rate, 1 USD başına tam sayı IDR'dir, dolayısıyla USD = canonical_amount / rate. Toplamlar 2 ondalık; kalem başına fiyatlar/iadeler 4 ondalık kullanır. Kesinlikle pozitif bir tutar asla 0.00'a yuvarlanmaz. rate_as_of, kurun RFC3339 zaman damgasıdır (+00:00 biçimi) veya kaydedilmiş bir zaman damgası yoksa null'dur.
Yalnızca v2: kullanılabilir bir USD/IDR kuru yoksa, para endpoint'leri bir para gövdesi yerine Retry-After başlığıyla 503 FX_RATE_UNAVAILABLE döndürür. v1 bunu asla döndürmez.
/orders Kimliği doğrulanmış kullanıcının siparişlerini en yeniden eskiye sıralı olarak döndürür. Duruma göre filtreleme ve offset ile sayfalamayı destekler.
Sorgu Parametreleri
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
limit | integer | Hayır | Maksimum sonuç (1-100, varsayılan 20) |
offset | integer | Hayır | Atlanacak sonuç sayısı (varsayılan 0) |
status | string | Hayır | Duruma göre filtrele: ACTIVE, OTP_RECEIVED, COMPLETED, CANCELED, EXPIRED (büyük/küçük harf duyarsız) |
Örnek İstek
curl -s "https://api.smscode.gg/v2/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/v2/orders?${params}`, {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();import requests
res = requests.get("https://api.smscode.gg/v2/orders",
params={"limit": 5, "status": "ACTIVE", "offset": 0},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": [
{
"id": 1001,
"status": "ACTIVE",
"created_at": "2026-02-25T10:00:00+00:00",
"product_id": 142,
"phone_number": "+6281234567890",
"amount": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
"otp_code": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:20:00+00:00",
"canceled_at": null,
"failed_reason": null
}
],
"meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
} v2: para alanları USD para nesneleridir ve yanıt tek bir meta.fx { pair, rate, rate_as_of } taşır. rate, 1 USD başına tam sayı IDR'dir, dolayısıyla USD = canonical_amount / rate. Toplamlar 2 ondalık; kalem başına fiyatlar/iadeler 4 ondalık kullanır. Kesinlikle pozitif bir tutar asla 0.00'a yuvarlanmaz. rate_as_of, kurun RFC3339 zaman damgasıdır (+00:00 biçimi) veya kaydedilmiş bir zaman damgası yoksa null'dur.
Yalnızca v2: kullanılabilir bir USD/IDR kuru yoksa, para endpoint'leri bir para gövdesi yerine Retry-After başlığıyla 503 FX_RATE_UNAVAILABLE döndürür. v1 bunu asla döndürmez.
/orders/{id} Kimliğe göre tek bir siparişi döndürür. Yalnızca kimliği doğrulanmış kullanıcıya ait siparişleri döndürür.
Yol Parametreleri
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
id | integer | Evet | Sipariş kimliği (yol parametresi) |
Örnek İstek
curl -s https://api.smscode.gg/v2/orders/1001 \
-H "Authorization: Bearer YOUR_API_TOKEN"const res = await fetch("https://api.smscode.gg/v2/orders/1001", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();import requests
res = requests.get("https://api.smscode.gg/v2/orders/1001",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": {
"id": 1001,
"status": "OTP_RECEIVED",
"created_at": "2026-02-25T10:00:00+00:00",
"product_id": 142,
"phone_number": "+6281234567890",
"amount": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
"otp_code": "123456",
"otp_received_at": "2026-02-25T10:05:00+00:00",
"expires_at": "2026-02-25T10:20:00+00:00",
"canceled_at": null,
"failed_reason": null
},
"meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
} v2: para alanları USD para nesneleridir ve yanıt tek bir meta.fx { pair, rate, rate_as_of } taşır. rate, 1 USD başına tam sayı IDR'dir, dolayısıyla USD = canonical_amount / rate. Toplamlar 2 ondalık; kalem başına fiyatlar/iadeler 4 ondalık kullanır. Kesinlikle pozitif bir tutar asla 0.00'a yuvarlanmaz. rate_as_of, kurun RFC3339 zaman damgasıdır (+00:00 biçimi) veya kaydedilmiş bir zaman damgası yoksa null'dur.
Yalnızca v2: kullanılabilir bir USD/IDR kuru yoksa, para endpoint'leri bir para gövdesi yerine Retry-After başlığıyla 503 FX_RATE_UNAVAILABLE döndürür. v1 bunu asla döndürmez.
/orders/active Tüm aktif siparişleri (ACTIVE + OTP_RECEIVED) listeler. OTP durumu güncellemelerini sorgulamak için kullanın.
Parametreler
Yok
Örnek İstek
curl -s https://api.smscode.gg/v2/orders/active \
-H "Authorization: Bearer YOUR_API_TOKEN"const res = await fetch("https://api.smscode.gg/v2/orders/active", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();import requests
res = requests.get("https://api.smscode.gg/v2/orders/active",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"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:00+00:00",
"expires_at": "2026-02-25T10:20:00+00:00",
"failed_reason": null
},
{
"id": 1002,
"status": "ACTIVE",
"otp_code": null,
"otp_message": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:50:00+00:00",
"failed_reason": null
}
]
} v2: bu endpoint para taşıyan bir endpoint değildir — ne amount ne de meta.fx döndürür (v1 ile aynı yapı, /v2 altında).
/orders/create Yeni bir sanal numara siparişi oluşturur. Bakiyeyi otomatik olarak düşer. Ağ yeniden denemelerinde yinelenen siparişleri önlemek için isteğe bağlı Idempotency-Key başlığını destekler.
İstek Gövdesi
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
product_id | integer | Hayır | Sipariş verilecek ürün kimliği. YALNIZCA BİRİNİ girin: product_id VEYA catalog_product_id, ikisini birden değil. |
catalog_product_id | integer | Hayır | Kararlı ürün kimliği — sunucu mevcut en iyi teklifi seçer (en ucuz, güvenilirliği gözeterek). Bunu veya product_id'yi girin. |
max_price | integer · string | Hayır | İsteğe bağlı fiyat üst sınırı. v1: IDR tam sayı. v2: USD ondalık dizesi (örn. "0.50"). |
prefer_provider | string | Hayır | Teklifler eşit olduğunda tercih edilecek isteğe bağlı sağlayıcı kodu. |
policy | string | Hayır | İsteğe bağlı yönlendirme politikası, yalnızca catalog_product_id ile geçerlidir. Değerler: cheapest (varsayılan) en düşük fiyatlı sağlıklı teklifi seçer; best_success teklifleri önce son teslim başarısına göre sıralar. best_success her sağlayıcıyı son 30 tamamlanmış gün içinde OTP alan siparişlerin oranına göre %10'luk dilimlerde puanlar ve bir sağlayıcıyı ancak o aralıkta en az 20 siparişi olduğunda sayar — bu eşiğin altındaki veya geçmişi olmayan sağlayıcılar nötr kabul edilir, böylece yeni teklifler asla geri planda kalmaz (tercihe bağlı; sinyal nötr başlar). prefer_provider de ayarlandıysa tercih edilen sağlayıcı yine ilk sırada kalır. |
quantity | integer | Hayır | Adet sayısı (1-100, varsayılan 1) |
Yinelenen siparişler oluşturmadan güvenle yeniden deneme yapmak için Idempotency-Key başlığı gönderin. Anahtar harf, rakam, tire ve alt çizgi (A-Z a-z 0-9 _ -) içerebilir, en fazla 128 karakter; geçersiz bir anahtar 422 VALIDATION_ERROR ile reddedilir. Aynı anahtar ve aynı gövde ile yeniden deneme, orijinal sonucu yeniden döndürür (kısmi başarıdaki failed_count dahil). Sağlayıcıya ulaşan ama başarısız olan bir yeniden deneme kaydedilir ve tekrar denendiğinde aynı hatayı döndürür — yeni bir deneme için YENİ bir anahtar kullanın. Yan etkisi olmayan hatalar (yetersiz bakiye, uygun teklif yok) anahtarı serbest bırakır, böylece bakiye yükleyip aynı anahtarla yeniden deneyebilirsiniz. Bir anahtarı farklı bir gövde ile yeniden kullanmak 422 IDEMPOTENCY_KEY_REUSED döndürür ve bu anahtarla hâlâ devam eden bir istek 409 REQUEST_IN_PROGRESS döndürür. create yanıtlarındaki failed_reason alanı her zaman null'dur — yalnızca sipariş sorgulama/listeleme sırasında doldurulur.
Örnek İstek
curl -s -X POST https://api.smscode.gg/v2/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}'
# Or order by stable catalog_product_id — the server picks the best current offer
# (cheapest, reliability-aware). Optional max_price caps the price; on v1 it is an
# IDR integer, on v2 it is a USD decimal string (e.g. "0.50"). prefer_provider
# (provider code) is a soft tie-breaker. Pass EITHER product_id OR catalog_product_id.
curl -s -X POST https://api.smscode.gg/v2/orders/create \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-request-id-124" \
-d '{"catalog_product_id":87,"max_price":20000}'const res = await fetch("https://api.smscode.gg/v2/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/v2/orders/create",
json={"product_id": 142, "quantity": 1},
headers={
"Authorization": "Bearer YOUR_API_TOKEN",
"Idempotency-Key": "unique-request-id-123",
})
data = res.json()Örnek Yanıt
{
"success": true,
"data": {
"orders": [
{
"id": 1002,
"status": "ACTIVE",
"product_id": 142,
"catalog_product_id": 87,
"amount": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
"phone_number": "+6281234567891",
"otp_code": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:50:00+00:00",
"failed_reason": null
}
],
"failed_count": 0
},
"meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
} v2: para alanları USD para nesneleridir ve yanıt tek bir meta.fx { pair, rate, rate_as_of } taşır. rate, 1 USD başına tam sayı IDR'dir, dolayısıyla USD = canonical_amount / rate. Toplamlar 2 ondalık; kalem başına fiyatlar/iadeler 4 ondalık kullanır. Kesinlikle pozitif bir tutar asla 0.00'a yuvarlanmaz. rate_as_of, kurun RFC3339 zaman damgasıdır (+00:00 biçimi) veya kaydedilmiş bir zaman damgası yoksa null'dur.
Yalnızca v2: kullanılabilir bir USD/IDR kuru yoksa, para endpoint'leri bir para gövdesi yerine Retry-After başlığıyla 503 FX_RATE_UNAVAILABLE döndürür. v1 bunu asla döndürmez.
/orders/cancel Aktif bir siparişi iptal eder. Kiralama bedeli hesap bakiyenize iade edilir.
İstek Gövdesi
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
id | integer | Evet | İptal edilecek sipariş kimliği |
Örnek İstek
curl -s -X POST https://api.smscode.gg/v2/orders/cancel \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id":1001}'const res = await fetch("https://api.smscode.gg/v2/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/v2/orders/cancel",
json={"id": 1001},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": {
"order_id": 1001,
"status": "CANCELED",
"refund_amount": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
"new_balance": { "amount": "31.69", "currency": "USD", "canonical_amount": 515000, "canonical_currency": "IDR" }
},
"meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
} v2: para alanları USD para nesneleridir ve yanıt tek bir meta.fx { pair, rate, rate_as_of } taşır. rate, 1 USD başına tam sayı IDR'dir, dolayısıyla USD = canonical_amount / rate. Toplamlar 2 ondalık; kalem başına fiyatlar/iadeler 4 ondalık kullanır. Kesinlikle pozitif bir tutar asla 0.00'a yuvarlanmaz. rate_as_of, kurun RFC3339 zaman damgasıdır (+00:00 biçimi) veya kaydedilmiş bir zaman damgası yoksa null'dur.
Yalnızca v2: kullanılabilir bir USD/IDR kuru yoksa, para endpoint'leri bir para gövdesi yerine Retry-After başlığıyla 503 FX_RATE_UNAVAILABLE döndürür. v1 bunu asla döndürmez.
/orders/finish OTP alındıktan sonra siparişi tamamlandı olarak işaretler. Süre dolmasını beklemek yerine numarayı hemen serbest bırakır.
İstek Gövdesi
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
id | integer | Evet | Tamamlanacak sipariş kimliği |
Örnek İstek
curl -s -X POST https://api.smscode.gg/v2/orders/finish \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id":1001}'const res = await fetch("https://api.smscode.gg/v2/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/v2/orders/finish",
json={"id": 1001},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": {
"order_id": 1001,
"status": "COMPLETED"
}
} v1 ile aynı — yalnızca temel yol değişir (/v1 → /v2).
/orders/resend Platformdan kiralanan numaraya SMS'i yeniden göndermesini ister. Tüm platformlar yeniden gönderimi desteklemez — yanıttaki resent alanını kontrol edin.
İstek Gövdesi
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
id | integer | Evet | SMS yeniden gönderilecek sipariş kimliği |
Örnek İstek
curl -s -X POST https://api.smscode.gg/v2/orders/resend \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id":1001}'const res = await fetch("https://api.smscode.gg/v2/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/v2/orders/resend",
json={"id": 1001},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": {
"order_id": 1001,
"status": "ACTIVE",
"resent": true
}
} v1 ile aynı — yalnızca temel yol değişir (/v1 → /v2).
/webhook Mevcut webhook bildirim yapılandırmanızı döndürür.
Parametreler
Yok
Örnek İstek
curl -s https://api.smscode.gg/v2/webhook \
-H "Authorization: Bearer YOUR_API_TOKEN"const res = await fetch("https://api.smscode.gg/v2/webhook", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();import requests
res = requests.get("https://api.smscode.gg/v2/webhook",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} v1 ile aynı — yalnızca temel yol değişir (/v1 → /v2).
/webhook Webhook URL'nizi ve/veya gizli anahtarınızı güncelleyin. İlk kez URL belirlediğinizde gizli anahtar otomatik oluşturulur. Temizlemek için boş dize gönderin. URL HTTPS kullanmalıdır.
İstek Gövdesi
| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
webhook_url | string | Hayır | Webhook olaylarını alacak HTTPS URL'si (temizlemek için boş dize) |
webhook_secret | string | Hayır | HMAC-SHA256 imzası için paylaşılan gizli anahtar (ilk ayarlamada belirtilmezse otomatik oluşturulur) |
En az bir alan gereklidir.
Örnek İstek
curl -s -X PATCH https://api.smscode.gg/v2/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/v2/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/v2/webhook",
json={"webhook_url": "https://example.com/webhook"},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} v1 ile aynı — yalnızca temel yol değişir (/v1 → /v2).
/webhook/test Yapılandırılmış webhook URL'nize bir test olayı gönderir. Sunucunuzdan dönen HTTP durum kodunu döndürür. Canlıya geçmeden önce endpoint'inizin çalıştığını doğrulamak için kullanışlıdır.
Parametreler
Yok
Örnek İstek
curl -s -X POST https://api.smscode.gg/v2/webhook/test \
-H "Authorization: Bearer YOUR_API_TOKEN"const res = await fetch("https://api.smscode.gg/v2/webhook/test", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();import requests
res = requests.post("https://api.smscode.gg/v2/webhook/test",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()Örnek Yanıt
{
"success": true,
"data": {
"status_code": 200
}
} v1 ile aynı — yalnızca temel yol değişir (/v1 → /v2).
⟩Webhook Bildirimleri
Polling yerine sipariş olayları için gerçek zamanlı push bildirimleri almak üzere bir webhook URL'si yapılandırın. Bu, bot betikleri için önerilen yaklaşımdır.
Olaylar
| Olay | Tetikleyici |
|---|---|
order.otp_received | Kiralanan numaraya OTP kodu teslim edildi |
order.completed | Sipariş tamamlandı olarak işaretlendi (manuel olarak veya süre dolmasıyla) |
order.expired | Sipariş OTP alınmadan süresi doldu (bakiye iade edildi) |
order.canceled | Sipariş kullanıcı tarafından iptal edildi (bakiye iade edildi) |
Veri Yükü
{
"event": "order.otp_received",
"timestamp": "2026-02-25T12:00:00+00:00",
"data": {
"order_id": 1001,
"phone_number": "+628123456789",
"otp_code": "1234",
"otp_message": "Your verification code is 1234",
"product_id": 42,
"catalog_product_id": 87,
"country": "Indonesia",
"platform": "WhatsApp"
}
} İmza Doğrulama
Her webhook isteği, webhook_secret'ınızı anahtar olarak kullanarak istek gövdesinin HMAC-SHA256 imzasını içeren bir X-Webhook-Signature başlığı içerir:
İsteğin gerçek olduğundan emin olmak için bu imzayı sunucunuzda doğrulayın. Teslim, 3 saniyelik zaman aşımıyla tek seferlik gönderimdir ve yeniden deneme yapılmaz.
⟩Rate Limit'ler
API isteklerine endpoint grubuna göre rate limit uygulanır. Limiti aşmak, kaç saniye bekleneceğini belirten bir Retry-After başlığıyla birlikte 429 Too Many Requests döndürür.
| Endpoint Grubu | Limit | Pencere |
|---|---|---|
| Katalog (ülkeler, hizmetler, ürünler, döviz kuru) | 5.000 istek | 60 saniye |
| Bakiye | 600 istek | 60 saniye |
| Sipariş okumaları (liste, tekil, aktif) | 5.000 istek | 60 saniye |
| Sipariş oluşturma | 3.000 istek | 60 saniye |
| Sipariş iptali | 1.000 istek | 60 saniye |
| Sipariş işlemleri (tamamla, yeniden gönder) | 1.000 istek | 60 saniye |
| Webhook yapılandırması (al, güncelle) | 600 istek | 60 saniye |
| Webhook testi | 10 istek | 60 saniye |
⟩Hata Kodları
error.code içinde aşağıdaki kodlardan biri yer alır:
| Kod | HTTP | Açıklama |
|---|---|---|
UNAUTHORIZED | 401 | Eksik veya geçersiz API token |
FORBIDDEN | 403 | Erişim reddedildi |
NOT_FOUND | 404 | Kaynak bulunamadı (sipariş, döviz kuru vb.) |
CONFLICT | 409 | Yinelenen istek veya kaynak çakışması |
INSUFFICIENT_BALANCE | 409 | Sipariş oluşturmak için yeterli bakiye yok |
VALIDATION_ERROR | 422 | İstek parametreleri doğrulamayı geçemedi |
RATE_LIMIT_EXCEEDED | 429 | Çok fazla istek (Retry-After başlığını kontrol edin) |
INTERNAL_ERROR | 500 | Sunucu iç hatası |
PROVIDER_ERROR | 422 | Üst düzey SMS sağlayıcısı isteği reddetti. Sipariş oluşturma başarısız olduğunda hata <code>details</code> taşıyabilir: <code>cause_counts</code> (eski <code>product_id</code> siparişleri — nedene göre gruplanmış bir sayım) veya <code>attempts</code> (<code>catalog_product_id</code> siparişleri — deneme başına sonuçlar), şu değerlerle: <code>ok</code>, <code>no_numbers</code>, <code>insufficient_balance</code>, <code>price_rejected</code>, <code>provider_unavailable</code>, <code>provider_account_balance</code>, <code>provider_error</code>. |
NO_OFFER_AVAILABLE | 422 | İstenen ürün ve politikaya (fiyat üst sınırı, stok durumu) uyan etkin bir teklif yok. |
CANCEL_TOO_EARLY | 409 | Sipariş iptal etmek için çok yeni — 2 dakika bekleyin |
REQUEST_IN_PROGRESS | 409 | Bu idempotency anahtarıyla bir oluşturma isteği hâlâ devam ediyor |
IDEMPOTENCY_KEY_REUSED | 422 | Bu idempotency anahtarı zaten farklı bir istek gövdesiyle kullanıldı |
SERVICE_UNAVAILABLE | 503 | Hizmet geçici olarak kullanılamıyor (bakım) |
FX_RATE_UNAVAILABLE | 503 | USD/IDR döviz kuru kullanılamıyor (v2 para endpoint'leri) — Retry-After başlığıyla 503 döndürür. |
⟩v1'den v2'ye geçiş
v1 IDR sunar; v2 USD sunar. Her iki sürüm de kalıcı olarak bir arada bulunur — kullanımdan kaldırma yoktur. Her entegrasyon için bir sürüm seçin; temel yolları karıştırmayın. v2, paranın nasıl temsil edildiği dışında v1 ile aynıdır.
| Boyut | v1 · IDR | v2 · USD |
|---|---|---|
| Para alanları | Tam sayı IDR, örn. 15000 | Para nesnesi { amount, currency, canonical_amount, canonical_currency } |
meta.fx | Yok | Para taşıyan her yanıtta zorunlu |
| Para birimi | IDR | USD (sabit kodlanmış) |
FX_RATE_UNAVAILABLE | — | Kullanılabilir kur yokken yeni 503 + Retry-After |
| Hassasiyet | — | Toplamlar 2 ondalık, fiyatlar/iadeler 4 ondalık, pozitiflerde yukarı yuvarlama |
GET /catalog/exchange-rate | {pair, base_currency, quote_currency, rate}; ?pair'i dikkate alır | {pair, rate, rate_as_of}; ?pair yok sayılır (yalnızca USD/IDR) |
Yan yana örnekler
{
"success": true,
"data": {
"currency": "IDR",
"balance": 500000
}
}{
"success": true,
"data": {
"balance": { "amount": "30.77", "currency": "USD", "canonical_amount": 500000, "canonical_currency": "IDR" }
},
"meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}{
"success": true,
"data": [
{
"id": 142,
"name": "WhatsApp Indonesia",
"country_id": 6,
"platform_id": 3,
"catalog_product_id": 87,
"available": 42,
"price": 15000,
"active": true
}
],
"meta": { "page": 1, "limit": 10, "count": 1 }
}{
"success": true,
"data": [
{
"id": 142,
"name": "WhatsApp Indonesia",
"country_id": 6,
"platform_id": 3,
"catalog_product_id": 87,
"available": 42,
"price": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
"active": true
}
],
"meta": { "page": 1, "limit": 10, "count": 1, "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}catalog_product_id, ürünün KARARLI kimliğidir (ülke + platform başına bir tane) — sistemlerinizde saklamak güvenlidir VE doğrudan sipariş verilebilir: catalog_product_id (ve isteğe bağlı max_price ile prefer_provider) ile sipariş verin, sunucu sizin için canlı teklifi belirlesin. Teklif başına product_id yolu hâlâ desteklenir ve geriye dönük uyumludur — o id değişkendir ve sağlayıcının fiyat kademesi her değiştiğinde değişir, bu yüzden sipariş vermeden önce kataloğu yeniden çekme önerisi yalnızca bu yol için geçerlidir.
{
"success": true,
"data": {
"order_id": 1001,
"status": "CANCELED",
"refund_amount": 15000,
"new_balance": 515000
}
}{
"success": true,
"data": {
"order_id": 1001,
"status": "CANCELED",
"refund_amount": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
"new_balance": { "amount": "31.69", "currency": "USD", "canonical_amount": 515000, "canonical_currency": "IDR" }
},
"meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}Geçiş kontrol listesi
- Temel yolu
/v1→/v2olarak değiştirin. - Para alanlarını nesne olarak ayrıştırın —
amount'u ondalık bir dize olarak okuyun;currencydeğeri"USD"'dir. - Defter mutabakatı için
canonical_amount(tam IDR) kullanın; USDamountrender zamanlı bir projeksiyondur veratebir kezmeta.fxiçinde açıklanır. - Yeni
FX_RATE_UNAVAILABLE(503) durumunu ele alın —Retry-After'dan sonra yeniden deneyin. v1 bunu asla döndürmez.