API Belgeleri

Sanal numaralara, siparişlere ve hesap bakiyesine programatik erişim.

Önerilen

Resmi SDK'lerle başlayın

Yeni entegrasyonlar için TypeScript/JavaScript veya Python SDK'yı kullanın. Her iki SDK da varsayılan olarak genel /v2 API'sini kullanır, güvenli yeniden denemelerde idempotency key'leri korur, typed error'lar sunar ve OTP yaşam döngüsünü tutarlı tutar.

01

Güvenli oluştur

Tam ve kararlı bir kademe yuvası için product_id ile ya da catalog_product_id, isteğe bağlı operator_id, min_price/max_price ve yeniden denemeye güvenli yönlendirilmiş ücretli çağrılar için idempotency anahtarıyla sipariş oluşturun.

catalog_product_idmax_priceIdempotency-Key
import { SmscodeClient, OtpTimeoutError } from "@smscode/sdk";

const client = new SmscodeClient({ token: process.env.SMSCODE_TOKEN! });

let orderId: number | undefined;

try {
  const created = await client.orders.create({
    catalog_product_id: Number(process.env.SMSCODE_CATALOG_PRODUCT_ID),
    max_price: "0.50",
    quantity: 1,
  });

  const order = created.orders[0]!;
  orderId = order.id;
  const first = await client.orders.waitForOtp(orderId, { timeoutMs: 120_000 });

  console.log(first.otpCode); // Bu kodu hedef uygulamada gönderin.
  await client.orders.finish(orderId);
} catch (err) {
  if (err instanceof OtpTimeoutError && orderId !== undefined) {
    const current = await client.orders.get(orderId);
    if (current.can_cancel) await client.orders.cancel(orderId);
  }
  throw err;
}
import os

from smscode import OtpTimeoutError, SmscodeClient

with SmscodeClient(token=os.environ["SMSCODE_TOKEN"]) as client:
    created = client.orders.create(
        catalog_product_id=int(os.environ["SMSCODE_CATALOG_PRODUCT_ID"]),
        max_price="0.50",
        quantity=1,
    )

    order = created.orders[0]
    order_id = int(order["id"])

    try:
        first = client.orders.wait_for_otp(order_id, timeout_ms=120_000)
        print(first.otp_code)  # Bu kodu hedef uygulamada gönderin.
        client.orders.finish(order_id)
    except OtpTimeoutError:
        current = client.orders.get(order_id)
        if current["can_cancel"]:
            client.orders.cancel(order_id)
        raise

Resend zamanlaması için can_resend ve resend_available_at kullanın. Düşük seviye resend timestamp'leri internal'dır ve public response field değildir.

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=7" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/catalog/services?country_id=7", {
  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": 7},
    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/operators

Bir ülke + servis için seçilebilir operatörleri döndürür. Gerçek operatörler ve Any stoğu birlikte mevcutsa yanıt, operator_id null olan bir Any satırı içerir; operatöre özel ürün yoksa liste boştur.

Sorgu Parametreleri

AdTürZorunluAçıklama
country_idintegerEvetÜlke ID’si
platform_idintegerEvetPlatform/servis ID’si

Örnek İstek

curl -s "https://api.smscode.gg/v1/catalog/operators?country_id=7&platform_id=3" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const params = new URLSearchParams({
  country_id: "7", platform_id: "3",
});
const res = await fetch(`https://api.smscode.gg/v1/catalog/operators?${params}`, {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/catalog/operators",
    params={"country_id": 7, "platform_id": 3},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Örnek Yanıt

200 OK
{
  "success": true,
  "data": [
    {
      "operator_id": null,
      "code": "any",
      "name": "Any",
      "local_name": null
    },
    {
      "operator_id": 433,
      "code": "axis",
      "name": "AXIS (XL Axiata)",
      "local_name": "AXIS (XL Axiata)"
    }
  ]
}
GET/catalog/products

Mevcut ürünlerin sayfalanmış listesini döndürür. Ülke, platform ve isteğe bağlı olarak operatöre 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
operator_idintegerHayır/catalog/operators içinden isteğe bağlı operatör ID’si. Any ürünleri için göndermeyin.
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=7&platform_id=3&limit=10&page=1" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const params = new URLSearchParams({
  country_id: "7", 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": 7, "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": 7,
      "platform_id": 3,
      "catalog_product_id": 87,
      "operator_id": null,
      "operator_name": null,
      "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,
      "catalog_product_id": 87,
      "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,
      "operator_id": null,
      "operator_name": 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,
    "catalog_product_id": 87,
    "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,
    "operator_id": null,
    "operator_name": 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": null,
      "otp_message": "Confirm your login: https://example.com/confirm",
      "sms_revision": 1,
      "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,
      "sms_revision": 0,
      "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ırDoğrudan sipariş için tam ve kararlı kademe yuvası ürün ID’si. Bunu YA DA catalog_product_id değerini gönderin, ikisini birden göndermeyin.
catalog_product_idintegerHayırYönlendirilmiş ülke+platform umbrella ID’si. Sunucu güncel ve eşleşen bir kademe seçer. Bunu veya product_id değerini gönderin.
operator_idintegerHayır/catalog/operators içinden isteğe bağlı operatör ID’si. Yalnızca catalog_product_id ile geçerlidir; Any için göndermeyin.
min_priceintegerHayırİsteğe bağlı fiyat alt sınırı. IDR tam sayısı. Yalnızca catalog_product_id ile geçerlidir.
max_priceintegerHayırİsteğe bağlı fiyat üst sınırı. IDR tam sayısı. Yalnızca catalog_product_id ile geçerlidir.
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 route by catalog_product_id — the server picks a current tier.
# product_id is the stable exact tier-slot id. catalog_product_id is the
# country+platform umbrella for routed ordering. Optional min_price/max_price
# bound the tier; operator_id scopes to a carrier from /catalog/operators.
# 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,"min_price":12000,"max_price":20000,"operator_id":433}'
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,
        "operator_id": null,
        "operator_name": 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
  }
}
POST/orders/reactivate

Tamamlanmış bir numarayı yeniden etkinleştirir — yeni bir numara kiralamadan, aynı numarayı başka bir doğrulama kodu için tekrar sipariş eder. Yalnızca numarası yeniden etkinleştirmeyi destekleyen, tamamlanmış bir sipariş uygundur (siparişte can_reactivate değerini kontrol edin veya reactivate-options ile önizleyin). Yeniden etkinleştirilen alt sipariş YENİ bir sipariştir ve create ile aynı biçimde döndürülür; bakiye otomatik olarak düşülür.

İstek Gövdesi

AdTürZorunluAçıklama
idintegerEvetYeniden etkinleştirilecek tamamlanmış sipariş.
max_priceintegerHayırİsteğe bağlı maliyet üst sınırı. IDR tam sayısı. Güncel maliyet bunu aşarsa yeniden etkinleştirme 422 VALIDATION_ERROR ile reddedilir.

create gibi bu da parasal bir değişikliktir — güvenli yeniden denemeler için bir Idempotency-Key başlığı gönderin (bir create ile bir reactivate aynı anahtarda asla çakışmaz). Bir anahtarı farklı bir gövde ile yeniden kullanmak 422 IDEMPOTENCY_KEY_REUSED döndürür ve o anahtarla hâlâ sonuçlanmakta olan bir istek 409 REQUEST_IN_PROGRESS döndürür. Yeniden etkinleştirilemeyen bir numara 409 CONFLICT döndürür; çok düşük bakiye 409 INSUFFICIENT_BALANCE döndürür.

Örnek İstek

curl -s -X POST https://api.smscode.gg/v1/orders/reactivate \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-901" \
  -d '{"id":1001,"max_price":20000}'
const res = await fetch("https://api.smscode.gg/v1/orders/reactivate", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
    "Idempotency-Key": "unique-request-id-901",
  },
  body: JSON.stringify({ id: 1001, max_price: 20000 }),
});
const data = await res.json();
import requests

res = requests.post("https://api.smscode.gg/v1/orders/reactivate",
    json={"id": 1001, "max_price": 20000},
    headers={
        "Authorization": "Bearer YOUR_API_TOKEN",
        "Idempotency-Key": "unique-request-id-901",
    })
data = res.json()

Örnek Yanıt

200 OK
{
  "success": true,
  "data": {
    "orders": [
      {
        "id": 1044,
        "status": "ACTIVE",
        "product_id": 142,
        "catalog_product_id": 87,
        "amount": 15000,
        "phone_number": "+6281234567890",
        "otp_code": null,
        "otp_received_at": null,
        "expires_at": "2026-02-25T11:20:00+00:00",
        "failed_reason": null,
        "operator_id": null,
        "operator_name": null
      }
    ],
    "failed_count": 0
  }
}
GET/orders/{id}/reactivate-options

Şu anda bir yeniden etkinleştirmenin ne kadar ücretlendirileceğini önizler. Salt okunur — hiçbir Idempotency-Key tüketmez ve hiçbir şey oluşturmaz. Maliyeti IDR tam sayısı olarak döndürür. Yalnızca numarası yeniden etkinleştirmeyi destekleyen, tamamlanmış bir sipariş için kullanılabilir.

Yol Parametreleri

AdTürZorunluAçıklama
idintegerEvetYeniden etkinleştirme maliyetinin önizleneceği sipariş kimliği (yol parametresi).

Örnek İstek

curl -s https://api.smscode.gg/v1/orders/1001/reactivate-options \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/orders/1001/reactivate-options", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/orders/1001/reactivate-options",
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Örnek Yanıt

200 OK
{
  "success": true,
  "data": {
    "cost": 15000
  }
}
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_receivedYeni SMS teslim edildi; ayrıştırılan kod null olabilir
order.completedSipariş tamamlandı olarak işaretlendi (manuel olarak veya süre dolmasıyla)
order.expiredSipariş herhangi bir SMS alınmadan sona erdi (bakiye iade edildi)
order.canceledSipariş kullanıcı tarafından iptal edildi (bakiye iade edildi)

Her yeni SMS bu olayı üretir. otp_message mevcutken otp_code null olabilir. Birden fazla SMS olayı sırasız gelebilir; daha eski bir toplu çifti yok saymak için sms_revision kullanın.

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": null,
    "otp_message": "Confirm your login: https://example.com/confirm",
    "sms_revision": 1,
    "product_id": 142,
    "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 GrubuSınırPencere
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 details taşıyabilir: cause_counts (eski product_id siparişleri — nedene göre gruplanmış bir sayım) veya attempts (catalog_product_id siparişleri — deneme başına sonuçlar), şu değerlerle: ok, no_numbers, insufficient_balance, price_rejected, provider_unavailable, provider_account_balance, provider_error.
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=7" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v2/catalog/services?country_id=7", {
  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": 7},
    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/operators

Bir ülke + servis için seçilebilir operatörleri döndürür. Gerçek operatörler ve Any stoğu birlikte mevcutsa yanıt, operator_id null olan bir Any satırı içerir; operatöre özel ürün yoksa liste boştur.

Sorgu Parametreleri

AdTürZorunluAçıklama
country_idintegerEvetÜlke ID’si
platform_idintegerEvetPlatform/servis ID’si

Örnek İstek

curl -s "https://api.smscode.gg/v2/catalog/operators?country_id=7&platform_id=3" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const params = new URLSearchParams({
  country_id: "7", platform_id: "3",
});
const res = await fetch(`https://api.smscode.gg/v2/catalog/operators?${params}`, {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v2/catalog/operators",
    params={"country_id": 7, "platform_id": 3},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Örnek Yanıt

200 OK
{
  "success": true,
  "data": [
    {
      "operator_id": null,
      "code": "any",
      "name": "Any",
      "local_name": null
    },
    {
      "operator_id": 433,
      "code": "axis",
      "name": "AXIS (XL Axiata)",
      "local_name": "AXIS (XL Axiata)"
    }
  ]
}

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, platform ve isteğe bağlı olarak operatöre 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
operator_idintegerHayır/catalog/operators içinden isteğe bağlı operatör ID’si. Any ürünleri için göndermeyin.
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=7&platform_id=3&limit=10&page=1" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const params = new URLSearchParams({
  country_id: "7", 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": 7, "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": 7,
      "platform_id": 3,
      "catalog_product_id": 87,
      "operator_id": null,
      "operator_name": null,
      "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,
      "catalog_product_id": 87,
      "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,
      "operator_id": null,
      "operator_name": 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,
    "catalog_product_id": 87,
    "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,
    "operator_id": null,
    "operator_name": 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": null,
      "otp_message": "Confirm your login: https://example.com/confirm",
      "sms_revision": 1,
      "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,
      "sms_revision": 0,
      "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ırDoğrudan sipariş için tam ve kararlı kademe yuvası ürün ID’si. Bunu YA DA catalog_product_id değerini gönderin, ikisini birden göndermeyin.
catalog_product_idintegerHayırYönlendirilmiş ülke+platform umbrella ID’si. Sunucu güncel ve eşleşen bir kademe seçer. Bunu veya product_id değerini gönderin.
operator_idintegerHayır/catalog/operators içinden isteğe bağlı operatör ID’si. Yalnızca catalog_product_id ile geçerlidir; Any için göndermeyin.
min_pricestringHayırİsteğe bağlı fiyat alt sınırı. USD ondalık string (örn. "0.30"). Yalnızca catalog_product_id ile geçerlidir.
max_pricestringHayırİsteğe bağlı fiyat üst sınırı. USD ondalık string (örn. "0.50"). Yalnızca catalog_product_id ile geçerlidir.
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 '{"catalog_product_id":87,"min_price":"0.30","max_price":"0.50","operator_id":433,"quantity":1}'
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({
    catalog_product_id: 87,
    min_price: "0.30",
    max_price: "0.50",
    operator_id: 433,
    quantity: 1,
  }),
});
const data = await res.json();
import requests

res = requests.post("https://api.smscode.gg/v2/orders/create",
    json={
        "catalog_product_id": 87,
        "min_price": "0.30",
        "max_price": "0.50",
        "operator_id": 433,
        "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,
        "operator_id": null,
        "operator_name": 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).

POST/orders/reactivate

Tamamlanmış bir numarayı yeniden etkinleştirir — yeni bir numara kiralamadan, aynı numarayı başka bir doğrulama kodu için tekrar sipariş eder. Yalnızca numarası yeniden etkinleştirmeyi destekleyen, tamamlanmış bir sipariş uygundur (siparişte can_reactivate değerini kontrol edin veya reactivate-options ile önizleyin). Yeniden etkinleştirilen alt sipariş YENİ bir sipariştir ve create ile aynı biçimde döndürülür; bakiye otomatik olarak düşülür.

İstek Gövdesi

AdTürZorunluAçıklama
idintegerEvetYeniden etkinleştirilecek tamamlanmış sipariş.
max_pricestringHayırİsteğe bağlı maliyet üst sınırı. USD ondalık string (örn. "0.50"). Güncel maliyet bunu aşarsa yeniden etkinleştirme 422 VALIDATION_ERROR ile reddedilir.

create gibi bu da parasal bir değişikliktir — güvenli yeniden denemeler için bir Idempotency-Key başlığı gönderin (bir create ile bir reactivate aynı anahtarda asla çakışmaz). Bir anahtarı farklı bir gövde ile yeniden kullanmak 422 IDEMPOTENCY_KEY_REUSED döndürür ve o anahtarla hâlâ sonuçlanmakta olan bir istek 409 REQUEST_IN_PROGRESS döndürür. Yeniden etkinleştirilemeyen bir numara 409 CONFLICT döndürür; çok düşük bakiye 409 INSUFFICIENT_BALANCE döndürür.

Örnek İstek

curl -s -X POST https://api.smscode.gg/v2/orders/reactivate \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-901" \
  -d '{"id":1001,"max_price":"0.50"}'
const res = await fetch("https://api.smscode.gg/v2/orders/reactivate", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
    "Idempotency-Key": "unique-request-id-901",
  },
  body: JSON.stringify({ id: 1001, max_price: "0.50" }),
});
const data = await res.json();
import requests

res = requests.post("https://api.smscode.gg/v2/orders/reactivate",
    json={"id": 1001, "max_price": "0.50"},
    headers={
        "Authorization": "Bearer YOUR_API_TOKEN",
        "Idempotency-Key": "unique-request-id-901",
    })
data = res.json()

Örnek Yanıt

200 OK
{
  "success": true,
  "data": {
    "orders": [
      {
        "id": 1044,
        "status": "ACTIVE",
        "product_id": 142,
        "catalog_product_id": 87,
        "amount": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
        "phone_number": "+6281234567890",
        "otp_code": null,
        "otp_received_at": null,
        "expires_at": "2026-02-25T11:20:00+00:00",
        "failed_reason": null,
        "operator_id": null,
        "operator_name": 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.

GET/orders/{id}/reactivate-options

Şu anda bir yeniden etkinleştirmenin ne kadar ücretlendirileceğini önizler. Salt okunur — hiçbir Idempotency-Key tüketmez ve hiçbir şey oluşturmaz. Maliyeti FX makbuzuyla birlikte USD para nesnesi olarak döndürür. Yalnızca numarası yeniden etkinleştirmeyi destekleyen, tamamlanmış bir sipariş için kullanılabilir.

Yol Parametreleri

AdTürZorunluAçıklama
idintegerEvetYeniden etkinleştirme maliyetinin önizleneceği sipariş kimliği (yol parametresi).

Örnek İstek

curl -s https://api.smscode.gg/v2/orders/1001/reactivate-options \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v2/orders/1001/reactivate-options", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v2/orders/1001/reactivate-options",
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Örnek Yanıt

200 OK
{
  "success": true,
  "data": {
    "cost": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "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/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_receivedYeni SMS teslim edildi; ayrıştırılan kod null olabilir
order.completedSipariş tamamlandı olarak işaretlendi (manuel olarak veya süre dolmasıyla)
order.expiredSipariş herhangi bir SMS alınmadan sona erdi (bakiye iade edildi)
order.canceledSipariş kullanıcı tarafından iptal edildi (bakiye iade edildi)

Her yeni SMS bu olayı üretir. otp_message mevcutken otp_code null olabilir. Birden fazla SMS olayı sırasız gelebilir; daha eski bir toplu çifti yok saymak için sms_revision kullanın.

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": null,
    "otp_message": "Confirm your login: https://example.com/confirm",
    "sms_revision": 1,
    "product_id": 142,
    "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 GrubuSınırPencere
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 details taşıyabilir: cause_counts (eski product_id siparişleri — nedene göre gruplanmış bir sayım) veya attempts (catalog_product_id siparişleri — deneme başına sonuçlar), şu değerlerle: ok, no_numbers, insufficient_balance, price_rejected, provider_unavailable, provider_account_balance, provider_error.
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": 7,
      "platform_id": 3,
      "catalog_product_id": 87,
      "operator_id": null,
      "operator_name": null,
      "available": 42,
      "price": 15000,
      "active": true
    }
  ],
  "meta": { "page": 1, "limit": 10, "count": 1 }
}
v2
{
  "success": true,
  "data": [
    {
      "id": 142,
      "name": "WhatsApp Indonesia",
      "country_id": 7,
      "platform_id": 3,
      "catalog_product_id": 87,
      "operator_id": null,
      "operator_name": null,
      "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" } }
}

product_id, SMSCode’un kararlı kademe yuvası ID’sidir. Tam olarak o kademeyi sipariş etmek istediğinizde saklayın; fiyatı ve kullanılabilirliği aynı satırda değişebilir. catalog_product_id, yönlendirilmiş siparişler için kararlı ülke+platform umbrella değeridir; sunucunun güncel ve eşleşen bir kademe seçmesini istediğinizde isteğe bağlı operator_id, min_price, max_price, prefer_provider ve policy ile kullanın.

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.