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:

Authorization: Bearer YOUR_API_TOKEN

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:

https://api.smscode.gg/v1

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.

Başarılı
{
  "success": true,
  "data": { ... }
}
Hata
{
  "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.

GET /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

200 OK
{
  "success": true,
  "data": [
    {
      "id": 6,
      "code": "ID",
      "name": "Indonesia",
      "dial_code": "+62",
      "emoji": "🇮🇩",
      "active": true
    }
  ]
}
GET /catalog/services

Mevcut hizmetlerin (platformların) listesini döndürür. İsteğe bağlı olarak ülkeye göre filtreleyin.

Sorgu Parametreleri

AdTürZorunluAçıklama
country_idintegerHayırBu ü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

200 OK
{
  "success": true,
  "data": [
    {
      "id": 3,
      "code": "wa",
      "name": "WhatsApp",
      "active": true
    }
  ]
}
GET /catalog/products

Mevcut ürünlerin sayfalanmış listesini döndürür. Ülke ve/veya platforma göre filtreleyin.

Sorgu Parametreleri

AdTürZorunluAçıklama
country_idintegerHayırÜlke kimliğine göre filtrele
platform_idintegerHayırPlatform/hizmet kimliğine göre filtrele
sortstringHayırSıralama: price_asc (varsayılan), price_desc, available_asc, available_desc, name_asc, name_desc
limitintegerHayırSayfa başına sonuç (1-10.000, varsayılan 1.000)
pageintegerHayırSayfa 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

200 OK
{
  "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 }
}
GET /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

AdTürZorunluAçıklama
pairstringHayırDö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

200 OK
{
  "success": true,
  "data": {
    "pair": "USD/IDR",
    "base_currency": "USD",
    "quote_currency": "IDR",
    "rate": 16250
  }
}
GET /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

200 OK
{
  "success": true,
  "data": {
    "currency": "IDR",
    "balance": 500000
  }
}
GET /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

AdTürZorunluAçıklama
limitintegerHayırMaksimum sonuç (1-100, varsayılan 20)
offsetintegerHayırAtlanacak sonuç sayısı (varsayılan 0)
statusstringHayırDuruma 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

200 OK
{
  "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
    }
  ]
}
GET /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

AdTürZorunluAçıklama
idintegerEvetSipariş 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

200 OK
{
  "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
  }
}
GET /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

200 OK
{
  "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
    }
  ]
}
POST /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

AdTürZorunluAçıklama
product_idintegerHayırSipariş verilecek ürün kimliği. YALNIZCA BİRİNİ girin: product_id VEYA catalog_product_id, ikisini birden değil.
catalog_product_idintegerHayırKararlı ü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_priceinteger · stringHayırİsteğe bağlı fiyat üst sınırı. v1: IDR tam sayı. v2: USD ondalık dizesi (örn. "0.50").
prefer_providerstringHayırTeklifler eşit olduğunda tercih edilecek isteğe bağlı sağlayıcı kodu.
policystringHayı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.
quantityintegerHayırAdet 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

200 OK
{
  "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
  }
}
POST /orders/cancel

Aktif bir siparişi iptal eder. Kiralama bedeli hesap bakiyenize iade edilir.

İstek Gövdesi

AdTürZorunluAçıklama
idintegerEvetİ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

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "CANCELED",
    "refund_amount": 15000,
    "new_balance": 515000
  }
}
POST /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

AdTürZorunluAçıklama
idintegerEvetTamamlanacak 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

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "COMPLETED"
  }
}
POST /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

AdTürZorunluAçıklama
idintegerEvetSMS 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

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "ACTIVE",
    "resent": true
  }
}
GET /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

200 OK
{
  "success": true,
  "data": {
    "webhook_url": "https://example.com/webhook",
    "webhook_secret": "a1b2c3d4e5f6..."
  }
}
PATCH /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

AdTürZorunluAçıklama
webhook_urlstringHayırWebhook olaylarını alacak HTTPS URL'si (temizlemek için boş dize)
webhook_secretstringHayırHMAC-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

200 OK
{
  "success": true,
  "data": {
    "webhook_url": "https://example.com/webhook",
    "webhook_secret": "a1b2c3d4e5f6..."
  }
}
POST /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

200 OK
{
  "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

OlayTetikleyici
order.otp_receivedKiralanan numaraya OTP kodu teslim edildi
order.completedSipariş tamamlandı olarak işaretlendi (manuel olarak veya süre dolmasıyla)
order.expiredSipariş OTP alınmadan süresi doldu (bakiye iade edildi)
order.canceledSipariş kullanıcı tarafından iptal edildi (bakiye iade edildi)

Veri Yükü

Webhook POST Gövdesi
{
  "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:

X-Webhook-Signature: sha256={HMAC-SHA256(body, webhook_secret)}

İ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 GrubuLimitPencere
Katalog (ülkeler, hizmetler, ürünler, döviz kuru)5.000 istek60 saniye
Bakiye600 istek60 saniye
Sipariş okumaları (liste, tekil, aktif)5.000 istek60 saniye
Sipariş oluşturma3.000 istek60 saniye
Sipariş iptali1.000 istek60 saniye
Sipariş işlemleri (tamamla, yeniden gönder)1.000 istek60 saniye
Webhook yapılandırması (al, güncelle)600 istek60 saniye
Webhook testi10 istek60 saniye

Hata Kodları

error.code içinde aşağıdaki kodlardan biri yer alır:

KodHTTPAçıklama
UNAUTHORIZED401Eksik veya geçersiz API token
FORBIDDEN403Erişim reddedildi
NOT_FOUND404Kaynak bulunamadı (sipariş, döviz kuru vb.)
CONFLICT409Yinelenen istek veya kaynak çakışması
INSUFFICIENT_BALANCE409Sipariş oluşturmak için yeterli bakiye yok
VALIDATION_ERROR422İstek parametreleri doğrulamayı geçemedi
RATE_LIMIT_EXCEEDED429Çok fazla istek (Retry-After başlığını kontrol edin)
INTERNAL_ERROR500Sunucu iç hatası
PROVIDER_ERROR422Ü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_AVAILABLE422İstenen ürün ve politikaya (fiyat üst sınırı, stok durumu) uyan etkin bir teklif yok.
CANCEL_TOO_EARLY409Sipariş iptal etmek için çok yeni — 2 dakika bekleyin
REQUEST_IN_PROGRESS409Bu idempotency anahtarıyla bir oluşturma isteği hâlâ devam ediyor
IDEMPOTENCY_KEY_REUSED422Bu idempotency anahtarı zaten farklı bir istek gövdesiyle kullanıldı
SERVICE_UNAVAILABLE503Hizmet 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.

v1'den v2'ye geçiş

Kimlik Doğrulama

Tüm API istekleri bir Bearer token gerektirir. Paneldeki Hesap Ayarları'ndan bir tane oluşturun ve her istekte ekleyin:

Authorization: Bearer YOUR_API_TOKEN

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:

https://api.smscode.gg/v2

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.

Başarılı
{
  "success": true,
  "data": { ... }
}
Hata
{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable message"
  }
}

v2 hatası: kullanılabilir döviz kuru yok (503)

503 Service Unavailable · Retry-After: 60
{
  "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.

GET /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

200 OK
{
  "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).

GET /catalog/services

Mevcut hizmetlerin (platformların) listesini döndürür. İsteğe bağlı olarak ülkeye göre filtreleyin.

Sorgu Parametreleri

AdTürZorunluAçıklama
country_idintegerHayırBu ü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

200 OK
{
  "success": true,
  "data": [
    {
      "id": 3,
      "code": "wa",
      "name": "WhatsApp",
      "active": true
    }
  ]
}

v1 ile aynı — yalnızca temel yol değişir (/v1/v2).

GET /catalog/products

Mevcut ürünlerin sayfalanmış listesini döndürür. Ülke ve/veya platforma göre filtreleyin.

Sorgu Parametreleri

AdTürZorunluAçıklama
country_idintegerHayırÜlke kimliğine göre filtrele
platform_idintegerHayırPlatform/hizmet kimliğine göre filtrele
sortstringHayırSıralama: price_asc (varsayılan), price_desc, available_asc, available_desc, name_asc, name_desc
limitintegerHayırSayfa başına sonuç (1-10.000, varsayılan 1.000)
pageintegerHayırSayfa 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

200 OK
{
  "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.

GET /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

200 OK
{
  "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.

GET /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

200 OK
{
  "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.

GET /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

AdTürZorunluAçıklama
limitintegerHayırMaksimum sonuç (1-100, varsayılan 20)
offsetintegerHayırAtlanacak sonuç sayısı (varsayılan 0)
statusstringHayırDuruma 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

200 OK
{
  "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.

GET /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

AdTürZorunluAçıklama
idintegerEvetSipariş 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

200 OK
{
  "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.

GET /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

200 OK
{
  "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).

POST /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

AdTürZorunluAçıklama
product_idintegerHayırSipariş verilecek ürün kimliği. YALNIZCA BİRİNİ girin: product_id VEYA catalog_product_id, ikisini birden değil.
catalog_product_idintegerHayırKararlı ü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_priceinteger · stringHayırİsteğe bağlı fiyat üst sınırı. v1: IDR tam sayı. v2: USD ondalık dizesi (örn. "0.50").
prefer_providerstringHayırTeklifler eşit olduğunda tercih edilecek isteğe bağlı sağlayıcı kodu.
policystringHayı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.
quantityintegerHayırAdet 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

200 OK
{
  "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.

POST /orders/cancel

Aktif bir siparişi iptal eder. Kiralama bedeli hesap bakiyenize iade edilir.

İstek Gövdesi

AdTürZorunluAçıklama
idintegerEvetİ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

200 OK
{
  "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.

POST /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

AdTürZorunluAçıklama
idintegerEvetTamamlanacak 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

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "COMPLETED"
  }
}

v1 ile aynı — yalnızca temel yol değişir (/v1/v2).

POST /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

AdTürZorunluAçıklama
idintegerEvetSMS 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

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "ACTIVE",
    "resent": true
  }
}

v1 ile aynı — yalnızca temel yol değişir (/v1/v2).

GET /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

200 OK
{
  "success": true,
  "data": {
    "webhook_url": "https://example.com/webhook",
    "webhook_secret": "a1b2c3d4e5f6..."
  }
}

v1 ile aynı — yalnızca temel yol değişir (/v1/v2).

PATCH /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

AdTürZorunluAçıklama
webhook_urlstringHayırWebhook olaylarını alacak HTTPS URL'si (temizlemek için boş dize)
webhook_secretstringHayırHMAC-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

200 OK
{
  "success": true,
  "data": {
    "webhook_url": "https://example.com/webhook",
    "webhook_secret": "a1b2c3d4e5f6..."
  }
}

v1 ile aynı — yalnızca temel yol değişir (/v1/v2).

POST /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

200 OK
{
  "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

OlayTetikleyici
order.otp_receivedKiralanan numaraya OTP kodu teslim edildi
order.completedSipariş tamamlandı olarak işaretlendi (manuel olarak veya süre dolmasıyla)
order.expiredSipariş OTP alınmadan süresi doldu (bakiye iade edildi)
order.canceledSipariş kullanıcı tarafından iptal edildi (bakiye iade edildi)

Veri Yükü

Webhook POST Gövdesi
{
  "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:

X-Webhook-Signature: sha256={HMAC-SHA256(body, webhook_secret)}

İ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 GrubuLimitPencere
Katalog (ülkeler, hizmetler, ürünler, döviz kuru)5.000 istek60 saniye
Bakiye600 istek60 saniye
Sipariş okumaları (liste, tekil, aktif)5.000 istek60 saniye
Sipariş oluşturma3.000 istek60 saniye
Sipariş iptali1.000 istek60 saniye
Sipariş işlemleri (tamamla, yeniden gönder)1.000 istek60 saniye
Webhook yapılandırması (al, güncelle)600 istek60 saniye
Webhook testi10 istek60 saniye

Hata Kodları

error.code içinde aşağıdaki kodlardan biri yer alır:

KodHTTPAçıklama
UNAUTHORIZED401Eksik veya geçersiz API token
FORBIDDEN403Erişim reddedildi
NOT_FOUND404Kaynak bulunamadı (sipariş, döviz kuru vb.)
CONFLICT409Yinelenen istek veya kaynak çakışması
INSUFFICIENT_BALANCE409Sipariş oluşturmak için yeterli bakiye yok
VALIDATION_ERROR422İstek parametreleri doğrulamayı geçemedi
RATE_LIMIT_EXCEEDED429Çok fazla istek (Retry-After başlığını kontrol edin)
INTERNAL_ERROR500Sunucu iç hatası
PROVIDER_ERROR422Ü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_AVAILABLE422İstenen ürün ve politikaya (fiyat üst sınırı, stok durumu) uyan etkin bir teklif yok.
CANCEL_TOO_EARLY409Sipariş iptal etmek için çok yeni — 2 dakika bekleyin
REQUEST_IN_PROGRESS409Bu idempotency anahtarıyla bir oluşturma isteği hâlâ devam ediyor
IDEMPOTENCY_KEY_REUSED422Bu idempotency anahtarı zaten farklı bir istek gövdesiyle kullanıldı
SERVICE_UNAVAILABLE503Hizmet geçici olarak kullanılamıyor (bakım)
FX_RATE_UNAVAILABLE503USD/IDR döviz kuru kullanılamıyor (v2 para endpoint'leri) — Retry-After başlığıyla 503 döndürür.
v1 → v2

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.

Boyutv1 · IDRv2 · USD
Para alanlarıTam sayı IDR, örn. 15000Para nesnesi { amount, currency, canonical_amount, canonical_currency }
meta.fxYokPara taşıyan her yanıtta zorunlu
Para birimiIDRUSD (sabit kodlanmış)
FX_RATE_UNAVAILABLEKullanılabilir kur yokken yeni 503 + Retry-After
HassasiyetToplamlar 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

GET/balance
v1
{
  "success": true,
  "data": {
    "currency": "IDR",
    "balance": 500000
  }
}
v2
{
  "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" } }
}
GET/catalog/products
v1
{
  "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 }
}
v2
{
  "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.

POST/orders/cancel
v1
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "CANCELED",
    "refund_amount": 15000,
    "new_balance": 515000
  }
}
v2
{
  "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

  1. Temel yolu /v1/v2 olarak değiştirin.
  2. Para alanlarını nesne olarak ayrıştırın — amount'u ondalık bir dize olarak okuyun; currency değeri "USD"'dir.
  3. Defter mutabakatı için canonical_amount (tam IDR) kullanın; USD amount render zamanlı bir projeksiyondur ve rate bir kez meta.fx içinde açıklanır.
  4. Yeni FX_RATE_UNAVAILABLE (503) durumunu ele alın — Retry-After'dan sonra yeniden deneyin. v1 bunu asla döndürmez.