API डॉक्यूमेंटेशन

वर्चुअल नंबर, ऑर्डर्स, और अकाउंट बैलेंस तक प्रोग्रामैटिक एक्सेस।

अनुशंसित

आधिकारिक SDKs से शुरू करें

नई integrations के लिए TypeScript/JavaScript या Python SDK का उपयोग करें। दोनों SDK डिफ़ॉल्ट रूप से सार्वजनिक /v2 API का उपयोग करते हैं, सुरक्षित retries में idempotency keys सुरक्षित रखते हैं, typed errors देते हैं, और OTP lifecycle को consistent रखते हैं।

01

सुरक्षित रूप से बनाएँ

किसी सटीक स्थिर टियर-स्लॉट के लिए product_id से ऑर्डर बनाएं, या catalog_product_id, वैकल्पिक operator_id, min_price/max_price और retry-safe routed paid calls के लिए idempotency key के साथ ऑर्डर बनाएं।

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); // इस कोड को लक्ष्य ऐप में दर्ज करें।
  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)  # इस कोड को लक्ष्य ऐप में दर्ज करें।
        client.orders.finish(order_id)
    except OtpTimeoutError:
        current = client.orders.get(order_id)
        if current["can_cancel"]:
            client.orders.cancel(order_id)
        raise

Resend timing के लिए can_resend और resend_available_at का उपयोग करें। Lower-level resend timestamps internal हैं और public response fields नहीं हैं।

अवलोकन

/v1 API के सभी मनी फ़ील्ड IDR में हैं (इंडोनेशियन रुपिया), पूर्णांक इकाइयों के रूप में — उदाहरण के लिए "price": 15000 और "balance": 500000 का मतलब Rp 15,000 और Rp 500,000 है। उसी लेजर के USD-नेटिव प्रोजेक्शन के लिए, ऊपर दिए गए वर्शन टॉगल से v2 API पर स्विच करें।

ऑथेंटिकेशन

सभी API रिक्वेस्ट के लिए Bearer token ज़रूरी है। डैशबोर्ड में Account Settings से एक जनरेट करें, फिर हर रिक्वेस्ट में शामिल करें:

Authorization:Bearer YOUR_API_TOKEN

बिना वैध token वाली रिक्वेस्ट को 401 UNAUTHORIZED रिस्पॉन्स मिलता है।

बेस URL

नीचे दिए गए सभी endpoint पाथ इसके रिलेटिव हैं:

https://api.smscode.gg/v1

रिस्पॉन्स फ़ॉर्मेट

हर रिस्पॉन्स एक कंसिस्टेंट एन्वेलप के साथ JSON लौटाता है। सभी रिस्पॉन्स में डीबगिंग के लिए x-request-id हेडर शामिल होता है।

सफल
{
  "success": true,
  "data": { ... }
}
एरर
{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable message"
  }
}

/v1 API के सभी मनी फ़ील्ड IDR में हैं (इंडोनेशियन रुपिया), पूर्णांक इकाइयों के रूप में — उदाहरण के लिए "price": 15000 और "balance": 500000 का मतलब Rp 15,000 और Rp 500,000 है। उसी लेजर के USD-नेटिव प्रोजेक्शन के लिए, ऊपर दिए गए वर्शन टॉगल से v2 API पर स्विच करें।

GET/catalog/countries

सभी उपलब्ध देशों की सूची लौटाता है।

पैरामीटर्स

कोई नहीं

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

उपलब्ध सर्विसेज़ (प्लेटफ़ॉर्म) की सूची लौटाता है। वैकल्पिक रूप से देश के अनुसार फ़िल्टर करें।

क्वेरी पैरामीटर्स

नामटाइपज़रूरीविवरण
country_idintegerनहींइस देश के लिए उपलब्ध सर्विसेज़ फ़िल्टर करें

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

किसी देश + सेवा के लिए चुने जा सकने वाले ऑपरेटर लौटाता है। अगर वास्तविक ऑपरेटर और Any stock दोनों उपलब्ध हों, तो response में operator_id null वाली Any row शामिल होती है; अगर operator-specific उत्पाद नहीं हैं, तो सूची खाली होती है।

क्वेरी पैरामीटर्स

नामटाइपज़रूरीविवरण
country_idintegerहाँदेश ID
platform_idintegerहाँप्लेटफ़ॉर्म/सेवा ID

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

उपलब्ध उत्पादों की पेजिनेटेड सूची लौटाता है। देश, प्लेटफ़ॉर्म और वैकल्पिक रूप से ऑपरेटर के अनुसार फ़िल्टर करें।

क्वेरी पैरामीटर्स

नामटाइपज़रूरीविवरण
country_idintegerनहींकंट्री ID से फ़िल्टर करें
platform_idintegerनहींप्लेटफ़ॉर्म/सर्विस ID से फ़िल्टर करें
operator_idintegerनहीं/catalog/operators से वैकल्पिक ऑपरेटर ID। Any उत्पादों के लिए इसे छोड़ दें।
sortstringनहींसॉर्ट ऑर्डर: price_asc (डिफ़ॉल्ट), price_desc, available_asc, available_desc, name_asc, name_desc
limitintegerनहींप्रति पेज रिज़ल्ट (1-10,000, डिफ़ॉल्ट 1,000)
pageintegerनहींपेज नंबर (न्यूनतम 1, डिफ़ॉल्ट 1)

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

करेंसी कन्वर्ज़न के लिए उपयोग किया जाने वाला वर्तमान USD/IDR एक्सचेंज रेट लौटाता है।

क्वेरी पैरामीटर्स

नामटाइपज़रूरीविवरण
pairstringनहींकरेंसी पेयर (डिफ़ॉल्ट: USD/IDR)

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

200 OK
{
  "success": true,
  "data": {
    "pair": "USD/IDR",
    "base_currency": "USD",
    "quote_currency": "IDR",
    "rate": 16250
  }
}
GET/balance

ऑथेंटिकेटेड यूज़र का अकाउंट बैलेंस लौटाता है।

पैरामीटर्स

कोई नहीं

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

200 OK
{
  "success": true,
  "data": {
    "currency": "IDR",
    "balance": 500000
  }
}
GET/orders

ऑथेंटिकेटेड यूज़र के ऑर्डर्स की सूची लौटाता है, सबसे हाल के पहले। स्टेटस और offset के ज़रिए पेजिनेशन द्वारा फ़िल्टरिंग सपोर्ट करता है।

क्वेरी पैरामीटर्स

नामटाइपज़रूरीविवरण
limitintegerनहींअधिकतम रिज़ल्ट (1-100, डिफ़ॉल्ट 20)
offsetintegerनहींस्किप करने के लिए रिज़ल्ट की संख्या (डिफ़ॉल्ट 0)
statusstringनहींस्टेटस से फ़िल्टर करें: ACTIVE, OTP_RECEIVED, COMPLETED, CANCELED, EXPIRED (केस-इनसेंसिटिव)

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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}

ID के अनुसार एक ऑर्डर लौटाता है। सिर्फ़ ऑथेंटिकेटेड यूज़र के ऑर्डर लौटाता है।

पाथ पैरामीटर्स

नामटाइपज़रूरीविवरण
idintegerहाँऑर्डर ID (path parameter)

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

सभी वर्तमान एक्टिव ऑर्डर्स (ACTIVE + OTP_RECEIVED) की सूची। OTP स्टेटस अपडेट के लिए पोल करने हेतु इसका उपयोग करें।

पैरामीटर्स

कोई नहीं

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

एक नया वर्चुअल नंबर ऑर्डर बनाता है। बैलेंस ऑटोमैटिकली कटता है। नेटवर्क रिट्राई पर डुप्लिकेट ऑर्डर रोकने के लिए वैकल्पिक Idempotency-Key हेडर सपोर्ट करता है।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
product_idintegerनहींसीधे ऑर्डर करने के लिए सटीक स्थिर टियर-स्लॉट product ID। या तो यह दें या catalog_product_id, दोनों नहीं।
catalog_product_idintegerनहींरूटेड देश+प्लेटफ़ॉर्म umbrella ID। सर्वर वर्तमान matching tier चुनता है। यह दें या product_id।
operator_idintegerनहीं/catalog/operators से वैकल्पिक ऑपरेटर ID। केवल catalog_product_id के साथ मान्य; Any के लिए छोड़ दें।
min_priceintegerनहींवैकल्पिक price floor। IDR integer। केवल catalog_product_id के साथ मान्य।
max_priceintegerनहींवैकल्पिक price cap। IDR integer। केवल catalog_product_id के साथ मान्य।
prefer_providerstringनहींवैकल्पिक प्रोवाइडर कोड, जब ऑफ़र बराबर हों तो इसे प्राथमिकता दी जाती है।
policystringनहींवैकल्पिक रूटिंग नीति, केवल catalog_product_id के साथ मान्य। मान: cheapest (डिफ़ॉल्ट) सबसे कम कीमत वाला स्वस्थ ऑफ़र चुनता है; best_success पहले हाल की डिलीवरी सफलता के आधार पर ऑफ़र को क्रमबद्ध करता है। best_success हर प्रोवाइडर को पिछले 30 पूर्ण दिनों में OTP पाने वाले ऑर्डर के अनुपात पर 10% बैंड में आँकता है, और किसी प्रोवाइडर को तभी गिनता है जब उस अवधि में उसके कम से कम 20 ऑर्डर हों — इस सीमा से नीचे या बिना इतिहास वाले प्रोवाइडर तटस्थ माने जाते हैं, इसलिए नए ऑफ़र कभी उपेक्षित नहीं होते (वैकल्पिक; संकेत तटस्थ से शुरू होता है)। यदि prefer_provider भी सेट है, तो पसंदीदा प्रोवाइडर फिर भी सबसे पहले रहता है।
quantityintegerनहींआइटम की संख्या (1-100, डिफ़ॉल्ट 1)

डुप्लिकेट ऑर्डर बनाए बिना सुरक्षित रूप से रिट्राई करने के लिए Idempotency-Key हेडर पास करें। key में अक्षर, अंक, हाइफ़न और अंडरस्कोर (A-Z a-z 0-9 _ -) हो सकते हैं, अधिकतम 128 कैरेक्टर; अमान्य key को 422 VALIDATION_ERROR के साथ अस्वीकार किया जाता है। एक ही key और एक ही body के साथ रिट्राई करने पर मूल रिज़ल्ट दोबारा मिलता है (आंशिक सफलता के failed_count सहित)। ऐसा रिट्राई जो प्रोवाइडर तक पहुँच गया पर विफल हो गया, रिकॉर्ड हो जाता है और दोबारा वही एरर लौटाता है — दोबारा कोशिश के लिए नई key का इस्तेमाल करें। बिना साइड-इफ़ेक्ट वाली विफलताएँ (अपर्याप्त बैलेंस, कोई उपलब्ध ऑफ़र नहीं) key को रिलीज़ कर देती हैं, इसलिए आप टॉप-अप करके उसी key के साथ रिट्राई कर सकते हैं। किसी key को अलग body के साथ दोबारा इस्तेमाल करने पर 422 IDEMPOTENCY_KEY_REUSED मिलता है, और उस key के साथ अभी चल रहे रिक्वेस्ट पर 409 REQUEST_IN_PROGRESS मिलता है। create रिस्पॉन्स में failed_reason फ़ील्ड हमेशा null होता है — यह केवल ऑर्डर poll/list के समय भरता है।

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

एक एक्टिव ऑर्डर कैंसल करता है। रेंटल कॉस्ट आपके अकाउंट बैलेंस में रिफंड हो जाती है।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
idintegerहाँकैंसल करने के लिए ऑर्डर ID

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "CANCELED",
    "refund_amount": 15000,
    "new_balance": 515000
  }
}
POST/orders/finish

OTP प्राप्त होने के बाद ऑर्डर को कम्प्लीट मार्क करता है। एक्सपायरी का इंतज़ार करने के बजाय नंबर तुरंत रिलीज़ होता है।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
idintegerहाँफ़िनिश करने के लिए ऑर्डर ID

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "COMPLETED"
  }
}
POST/orders/resend

रेंटेड नंबर पर SMS दोबारा भेजने का अनुरोध करता है। सभी प्लेटफ़ॉर्म रीसेंड सपोर्ट नहीं करते — रिस्पॉन्स में resent फ़ील्ड चेक करें।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
idintegerहाँSMS रीसेंड करने के लिए ऑर्डर ID

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "ACTIVE",
    "resent": true
  }
}
POST/orders/reactivate

पूरा हो चुका नंबर रीएक्टिवेट करता है — नया नंबर किराए पर लिए बिना उसी नंबर को दूसरे वेरिफ़िकेशन कोड के लिए दोबारा ऑर्डर करता है। केवल वही पूरा हो चुका ऑर्डर योग्य है जिसका नंबर रीएक्टिवेशन सपोर्ट करता है (ऑर्डर पर can_reactivate चेक करें, या reactivate-options से प्रीव्यू करें)। रीएक्टिवेट किया गया चाइल्ड एक नया ऑर्डर होता है, जो create जैसी ही शेप में लौटाया जाता है; बैलेंस ऑटोमैटिकली कट जाता है।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
idintegerहाँरीएक्टिवेट किया जाने वाला पूरा हो चुका ऑर्डर।
max_priceintegerनहींवैकल्पिक कॉस्ट सीलिंग। IDR integer। अगर लाइव कॉस्ट इससे ज़्यादा हो तो रीएक्टिवेशन 422 VALIDATION_ERROR के साथ अस्वीकार कर दिया जाता है।

create की तरह यह भी एक money mutation है — सुरक्षित रिट्राई के लिए Idempotency-Key हेडर पास करें (एक create और एक reactivate कभी भी एक ही key पर नहीं टकरा सकते)। किसी key को अलग body के साथ दोबारा इस्तेमाल करने पर 422 IDEMPOTENCY_KEY_REUSED मिलता है, और उस key के साथ अभी सेटल हो रहे रिक्वेस्ट पर 409 REQUEST_IN_PROGRESS मिलता है। जिस नंबर को रीएक्टिवेट नहीं किया जा सकता, वह 409 CONFLICT लौटाता है; बैलेंस बहुत कम होने पर 409 INSUFFICIENT_BALANCE मिलता है।

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

अभी रीएक्टिवेशन पर कितना चार्ज होगा, इसका प्रीव्यू देता है। केवल-पढ़ने के लिए — कोई Idempotency-Key इस्तेमाल नहीं करता और कुछ भी नहीं बनाता। कॉस्ट को IDR integer के रूप में लौटाता है। यह केवल उसी पूरा हो चुके ऑर्डर के लिए उपलब्ध है जिसका नंबर रीएक्टिवेशन सपोर्ट करता है।

पाथ पैरामीटर्स

नामटाइपज़रूरीविवरण
idintegerहाँवह ऑर्डर ID जिसके लिए रीएक्टिवेशन कॉस्ट का प्रीव्यू करना है (path parameter)।

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

200 OK
{
  "success": true,
  "data": {
    "cost": 15000
  }
}
GET/webhook

आपकी वर्तमान webhook नोटिफ़िकेशन कॉन्फ़िगरेशन लौटाता है।

पैरामीटर्स

कोई नहीं

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

अपना webhook URL और/या secret अपडेट करें। पहली बार URL सेट करने पर secret ऑटो-जनरेट होता है। क्लियर करने के लिए खाली स्ट्रिंग भेजें। URL HTTPS होना चाहिए।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
webhook_urlstringनहींWebhook इवेंट प्राप्त करने के लिए HTTPS URL (क्लियर करने के लिए खाली स्ट्रिंग)
webhook_secretstringनहींHMAC-SHA256 सिग्नेचर के लिए शेयर्ड secret (पहली बार सेट पर छोड़ने पर ऑटो-जनरेट)

कम से कम एक फ़ील्ड ज़रूरी है।

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

आपके कॉन्फ़िगर किए गए webhook URL पर एक टेस्ट इवेंट भेजता है। आपके सर्वर से HTTP स्टेटस कोड लौटाता है। लाइव होने से पहले endpoint वेरिफाई करने के लिए उपयोगी।

पैरामीटर्स

कोई नहीं

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

200 OK
{
  "success": true,
  "data": {
    "status_code": 200
  }
}

Webhook नोटिफ़िकेशन

पोलिंग के बजाय ऑर्डर इवेंट्स के लिए रियल-टाइम पुश नोटिफ़िकेशन प्राप्त करने हेतु webhook URL कॉन्फ़िगर करें। बॉट स्क्रिप्ट्स के लिए यह रेकमेंडेड तरीक़ा है।

इवेंट्स

इवेंटट्रिगर
order.otp_receivedनया SMS मिला; पहचाना गया कोड null हो सकता है
order.completedऑर्डर कम्प्लीट मार्क हुआ (मैन्युअली या एक्सपायरी द्वारा)
order.expiredकोई SMS मिलने से पहले ऑर्डर एक्सपायर हुआ (बैलेंस रिफंड)
order.canceledयूज़र द्वारा ऑर्डर कैंसल (बैलेंस रिफंड)

हर नया SMS यह event भेजता है। otp_message मौजूद होने पर otp_code null हो सकता है। कई SMS event क्रम से बाहर आ सकते हैं; पुराने aggregate pair को अनदेखा करने के लिए sms_revision का उपयोग करें।

पेलोड

Webhook POST बॉडी
{
  "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"
  }
}

सिग्नेचर वेरिफ़िकेशन

हर webhook रिक्वेस्ट में X-Webhook-Signature हेडर शामिल होता है जिसमें रिक्वेस्ट बॉडी का HMAC-SHA256 सिग्नेचर होता है, आपके webhook_secret को key के रूप में उपयोग करते हुए:

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

रिक्वेस्ट ऑथेंटिक है यह सुनिश्चित करने के लिए अपने सर्वर पर इस सिग्नेचर को वेरिफाई करें। डिलीवरी फ़ायर-एंड-फ़ॉरगेट है जिसमें 3-सेकंड टाइमआउट और कोई रिट्राई नहीं।

रेट लिमिट्स

API रिक्वेस्ट प्रति endpoint ग्रुप rate-limited हैं। लिमिट पार करने पर 429 Too Many Requests रिस्पॉन्स मिलता है जिसमें Retry-After हेडर बताता है कितने सेकंड इंतज़ार करना है।

Endpoint ग्रुपलिमिटविंडो
कैटलॉग (देश, सर्विसेज़, प्रोडक्ट्स, एक्सचेंज रेट)5,000 रिक्वेस्ट60 सेकंड
बैलेंस600 रिक्वेस्ट60 सेकंड
ऑर्डर पढ़ना (सूची, गेट, एक्टिव)5,000 रिक्वेस्ट60 सेकंड
ऑर्डर बनाना3,000 रिक्वेस्ट60 सेकंड
ऑर्डर कैंसल करना1,000 रिक्वेस्ट60 सेकंड
ऑर्डर कार्रवाइयाँ (finish, resend)1,000 रिक्वेस्ट60 सेकंड
Webhook कॉन्फ़िगरेशन (गेट, अपडेट)600 रिक्वेस्ट60 सेकंड
Webhook टेस्ट10 रिक्वेस्ट60 सेकंड

एरर कोड

एरर रिस्पॉन्स में error.code में इनमें से एक कोड शामिल होता है:

कोडHTTPविवरण
UNAUTHORIZED401API token गायब या अमान्य
FORBIDDEN403एक्सेस अस्वीकृत
NOT_FOUND404रिसोर्स नहीं मिला (ऑर्डर, एक्सचेंज रेट, आदि)
CONFLICT409डुप्लिकेट रिक्वेस्ट या रिसोर्स कॉन्फ़्लिक्ट
INSUFFICIENT_BALANCE409ऑर्डर बनाने के लिए पर्याप्त बैलेंस नहीं
VALIDATION_ERROR422रिक्वेस्ट पैरामीटर्स वैलिडेशन में फ़ेल
RATE_LIMIT_EXCEEDED429बहुत ज़्यादा रिक्वेस्ट (Retry-After हेडर देखें)
INTERNAL_ERROR500इंटरनल सर्वर एरर
PROVIDER_ERROR422अपस्ट्रीम SMS प्रोवाइडर ने रिक्वेस्ट रिजेक्ट की। ऑर्डर बनाने में विफलता पर error में details हो सकता है: cause_counts (पुराने product_id ऑर्डर — कारण के अनुसार गिनती) या attempts (catalog_product_id ऑर्डर — प्रति प्रयास परिणाम), जिनके मान ok, no_numbers, insufficient_balance, price_rejected, provider_unavailable, provider_account_balance, provider_error होते हैं।
NO_OFFER_AVAILABLE422अनुरोधित प्रोडक्ट और नीति (मूल्य सीमा, उपलब्धता) से मेल खाता कोई सक्रिय ऑफ़र नहीं है।
CANCEL_TOO_EARLY409ऑर्डर कैंसल करने के लिए बहुत नया — 2 मिनट इंतज़ार करें
REQUEST_IN_PROGRESS409इस idempotency key के साथ एक क्रिएट रिक्वेस्ट अभी भी चल रहा है
IDEMPOTENCY_KEY_REUSED422यह idempotency key पहले से किसी अलग रिक्वेस्ट body के साथ इस्तेमाल हो चुकी है
SERVICE_UNAVAILABLE503सर्विस अस्थायी रूप से अनुपलब्ध (मेंटेनेंस)

अवलोकन

/v2 API के सभी मनी फ़ील्ड USD में हैं, जो एक मनी ऑब्जेक्ट के रूप में लौटाए जाते हैं — { "amount": "0.92", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" }amount एक दशमलव स्ट्रिंग है; canonical_amount सटीक IDR लेजर वैल्यू है (रिकंसिलिएशन के लिए इसका उपयोग करें)। लागू किया गया USD/IDR rate प्रति रिस्पॉन्स एक बार meta.fx में दर्शाया जाता है। v2 v1 के समान ही IDR लेजर पर रेंडर-टाइम USD प्रोजेक्शन है — यह कभी भी USD स्टोर या ट्रांज़ैक्ट नहीं करता।

v1 से v2 में माइग्रेशन

ऑथेंटिकेशन

सभी API रिक्वेस्ट के लिए Bearer token ज़रूरी है। डैशबोर्ड में Account Settings से एक जनरेट करें, फिर हर रिक्वेस्ट में शामिल करें:

Authorization:Bearer YOUR_API_TOKEN

बिना वैध token वाली रिक्वेस्ट को 401 UNAUTHORIZED रिस्पॉन्स मिलता है।

बेस URL

नीचे दिए गए सभी endpoint पाथ इसके रिलेटिव हैं:

https://api.smscode.gg/v2

रिस्पॉन्स फ़ॉर्मेट

हर रिस्पॉन्स एक कंसिस्टेंट एन्वेलप के साथ JSON लौटाता है। सभी रिस्पॉन्स में डीबगिंग के लिए x-request-id हेडर शामिल होता है।

सफल
{
  "success": true,
  "data": { ... }
}
एरर
{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable message"
  }
}

v2 एरर: कोई उपयोग योग्य एक्सचेंज रेट नहीं (503)

503 Service Unavailable · Retry-After: 60
{
  "success": false,
  "error": { "code": "FX_RATE_UNAVAILABLE", "message": "USD/IDR exchange rate is unavailable" }
}

/v2 API के सभी मनी फ़ील्ड USD में हैं, जो एक मनी ऑब्जेक्ट के रूप में लौटाए जाते हैं — { "amount": "0.92", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" }amount एक दशमलव स्ट्रिंग है; canonical_amount सटीक IDR लेजर वैल्यू है (रिकंसिलिएशन के लिए इसका उपयोग करें)। लागू किया गया USD/IDR rate प्रति रिस्पॉन्स एक बार meta.fx में दर्शाया जाता है। v2 v1 के समान ही IDR लेजर पर रेंडर-टाइम USD प्रोजेक्शन है — यह कभी भी USD स्टोर या ट्रांज़ैक्ट नहीं करता।

GET/catalog/countries

सभी उपलब्ध देशों की सूची लौटाता है।

पैरामीटर्स

कोई नहीं

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

v1 के समान — केवल बेस पाथ बदलता है (/v1/v2)।

GET/catalog/services

उपलब्ध सर्विसेज़ (प्लेटफ़ॉर्म) की सूची लौटाता है। वैकल्पिक रूप से देश के अनुसार फ़िल्टर करें।

क्वेरी पैरामीटर्स

नामटाइपज़रूरीविवरण
country_idintegerनहींइस देश के लिए उपलब्ध सर्विसेज़ फ़िल्टर करें

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

v1 के समान — केवल बेस पाथ बदलता है (/v1/v2)।

GET/catalog/operators

किसी देश + सेवा के लिए चुने जा सकने वाले ऑपरेटर लौटाता है। अगर वास्तविक ऑपरेटर और Any stock दोनों उपलब्ध हों, तो response में operator_id null वाली Any row शामिल होती है; अगर operator-specific उत्पाद नहीं हैं, तो सूची खाली होती है।

क्वेरी पैरामीटर्स

नामटाइपज़रूरीविवरण
country_idintegerहाँदेश ID
platform_idintegerहाँप्लेटफ़ॉर्म/सेवा ID

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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 के समान — केवल बेस पाथ बदलता है (/v1/v2)।

GET/catalog/products

उपलब्ध उत्पादों की पेजिनेटेड सूची लौटाता है। देश, प्लेटफ़ॉर्म और वैकल्पिक रूप से ऑपरेटर के अनुसार फ़िल्टर करें।

क्वेरी पैरामीटर्स

नामटाइपज़रूरीविवरण
country_idintegerनहींकंट्री ID से फ़िल्टर करें
platform_idintegerनहींप्लेटफ़ॉर्म/सर्विस ID से फ़िल्टर करें
operator_idintegerनहीं/catalog/operators से वैकल्पिक ऑपरेटर ID। Any उत्पादों के लिए इसे छोड़ दें।
sortstringनहींसॉर्ट ऑर्डर: price_asc (डिफ़ॉल्ट), price_desc, available_asc, available_desc, name_asc, name_desc
limitintegerनहींप्रति पेज रिज़ल्ट (1-10,000, डिफ़ॉल्ट 1,000)
pageintegerनहींपेज नंबर (न्यूनतम 1, डिफ़ॉल्ट 1)

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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: मनी फ़ील्ड USD मनी ऑब्जेक्ट हैं और रिस्पॉन्स में एक ही meta.fx { pair, rate, rate_as_of } होता है। rate प्रति 1 USD पूर्णांक IDR है, इसलिए USD = canonical_amount / rate। टोटल में 2 दशमलव; प्रति-आइटम कीमत/रिफ़ंड में 4 दशमलव उपयोग होते हैं। पूर्णतः धनात्मक राशि कभी भी 0.00 में राउंड नहीं होती। rate_as_of उस रेट का RFC3339 टाइमस्टैम्प (+00:00 रूप) है, या जब कोई टाइमस्टैम्प दर्ज नहीं है तो null

केवल v2: यदि कोई उपयोग योग्य USD/IDR रेट उपलब्ध नहीं है, तो मनी एंडपॉइंट मनी बॉडी के बजाय Retry-After हेडर के साथ 503 FX_RATE_UNAVAILABLE लौटाते हैं। v1 यह कभी नहीं लौटाता।

GET/catalog/exchange-rate

करेंसी कन्वर्ज़न के लिए उपयोग किया जाने वाला वर्तमान USD/IDR एक्सचेंज रेट लौटाता है।

पैरामीटर्स

कोई नहीं — v2 हमेशा USD/IDR लौटाता है; v1 का ?pair पैरामीटर नज़रअंदाज़ किया जाता है।

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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 } लौटाता है (कोई base_currency/quote_currency नहीं, कोई meta रैपर नहीं — रेट ही डेटा है)। ?pair को नज़रअंदाज़ किया जाता है — v2 हमेशा USD/IDR लौटाता है (v1 ?pair का सम्मान करता है)। यदि कोई उपयोग योग्य रेट नहीं है तो 503 FX_RATE_UNAVAILABLE लौटाता है।

GET/balance

ऑथेंटिकेटेड यूज़र का अकाउंट बैलेंस लौटाता है।

पैरामीटर्स

कोई नहीं

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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: मनी फ़ील्ड USD मनी ऑब्जेक्ट हैं और रिस्पॉन्स में एक ही meta.fx { pair, rate, rate_as_of } होता है। rate प्रति 1 USD पूर्णांक IDR है, इसलिए USD = canonical_amount / rate। टोटल में 2 दशमलव; प्रति-आइटम कीमत/रिफ़ंड में 4 दशमलव उपयोग होते हैं। पूर्णतः धनात्मक राशि कभी भी 0.00 में राउंड नहीं होती। rate_as_of उस रेट का RFC3339 टाइमस्टैम्प (+00:00 रूप) है, या जब कोई टाइमस्टैम्प दर्ज नहीं है तो null

केवल v2: यदि कोई उपयोग योग्य USD/IDR रेट उपलब्ध नहीं है, तो मनी एंडपॉइंट मनी बॉडी के बजाय Retry-After हेडर के साथ 503 FX_RATE_UNAVAILABLE लौटाते हैं। v1 यह कभी नहीं लौटाता।

GET/orders

ऑथेंटिकेटेड यूज़र के ऑर्डर्स की सूची लौटाता है, सबसे हाल के पहले। स्टेटस और offset के ज़रिए पेजिनेशन द्वारा फ़िल्टरिंग सपोर्ट करता है।

क्वेरी पैरामीटर्स

नामटाइपज़रूरीविवरण
limitintegerनहींअधिकतम रिज़ल्ट (1-100, डिफ़ॉल्ट 20)
offsetintegerनहींस्किप करने के लिए रिज़ल्ट की संख्या (डिफ़ॉल्ट 0)
statusstringनहींस्टेटस से फ़िल्टर करें: ACTIVE, OTP_RECEIVED, COMPLETED, CANCELED, EXPIRED (केस-इनसेंसिटिव)

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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: मनी फ़ील्ड USD मनी ऑब्जेक्ट हैं और रिस्पॉन्स में एक ही meta.fx { pair, rate, rate_as_of } होता है। rate प्रति 1 USD पूर्णांक IDR है, इसलिए USD = canonical_amount / rate। टोटल में 2 दशमलव; प्रति-आइटम कीमत/रिफ़ंड में 4 दशमलव उपयोग होते हैं। पूर्णतः धनात्मक राशि कभी भी 0.00 में राउंड नहीं होती। rate_as_of उस रेट का RFC3339 टाइमस्टैम्प (+00:00 रूप) है, या जब कोई टाइमस्टैम्प दर्ज नहीं है तो null

केवल v2: यदि कोई उपयोग योग्य USD/IDR रेट उपलब्ध नहीं है, तो मनी एंडपॉइंट मनी बॉडी के बजाय Retry-After हेडर के साथ 503 FX_RATE_UNAVAILABLE लौटाते हैं। v1 यह कभी नहीं लौटाता।

GET/orders/{id}

ID के अनुसार एक ऑर्डर लौटाता है। सिर्फ़ ऑथेंटिकेटेड यूज़र के ऑर्डर लौटाता है।

पाथ पैरामीटर्स

नामटाइपज़रूरीविवरण
idintegerहाँऑर्डर ID (path parameter)

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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: मनी फ़ील्ड USD मनी ऑब्जेक्ट हैं और रिस्पॉन्स में एक ही meta.fx { pair, rate, rate_as_of } होता है। rate प्रति 1 USD पूर्णांक IDR है, इसलिए USD = canonical_amount / rate। टोटल में 2 दशमलव; प्रति-आइटम कीमत/रिफ़ंड में 4 दशमलव उपयोग होते हैं। पूर्णतः धनात्मक राशि कभी भी 0.00 में राउंड नहीं होती। rate_as_of उस रेट का RFC3339 टाइमस्टैम्प (+00:00 रूप) है, या जब कोई टाइमस्टैम्प दर्ज नहीं है तो null

केवल v2: यदि कोई उपयोग योग्य USD/IDR रेट उपलब्ध नहीं है, तो मनी एंडपॉइंट मनी बॉडी के बजाय Retry-After हेडर के साथ 503 FX_RATE_UNAVAILABLE लौटाते हैं। v1 यह कभी नहीं लौटाता।

GET/orders/active

सभी वर्तमान एक्टिव ऑर्डर्स (ACTIVE + OTP_RECEIVED) की सूची। OTP स्टेटस अपडेट के लिए पोल करने हेतु इसका उपयोग करें।

पैरामीटर्स

कोई नहीं

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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: यह एंडपॉइंट मनी-बेयरिंग नहीं है — यह न amount लौटाता है और न meta.fx (v1 जैसी ही संरचना, /v2 के अंतर्गत)।

POST/orders/create

एक नया वर्चुअल नंबर ऑर्डर बनाता है। बैलेंस ऑटोमैटिकली कटता है। नेटवर्क रिट्राई पर डुप्लिकेट ऑर्डर रोकने के लिए वैकल्पिक Idempotency-Key हेडर सपोर्ट करता है।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
product_idintegerनहींसीधे ऑर्डर करने के लिए सटीक स्थिर टियर-स्लॉट product ID। या तो यह दें या catalog_product_id, दोनों नहीं।
catalog_product_idintegerनहींरूटेड देश+प्लेटफ़ॉर्म umbrella ID। सर्वर वर्तमान matching tier चुनता है। यह दें या product_id।
operator_idintegerनहीं/catalog/operators से वैकल्पिक ऑपरेटर ID। केवल catalog_product_id के साथ मान्य; Any के लिए छोड़ दें।
min_pricestringनहींवैकल्पिक price floor। USD decimal string (जैसे "0.30")। केवल catalog_product_id के साथ मान्य।
max_pricestringनहींवैकल्पिक price cap। USD decimal string (जैसे "0.50")। केवल catalog_product_id के साथ मान्य।
prefer_providerstringनहींवैकल्पिक प्रोवाइडर कोड, जब ऑफ़र बराबर हों तो इसे प्राथमिकता दी जाती है।
policystringनहींवैकल्पिक रूटिंग नीति, केवल catalog_product_id के साथ मान्य। मान: cheapest (डिफ़ॉल्ट) सबसे कम कीमत वाला स्वस्थ ऑफ़र चुनता है; best_success पहले हाल की डिलीवरी सफलता के आधार पर ऑफ़र को क्रमबद्ध करता है। best_success हर प्रोवाइडर को पिछले 30 पूर्ण दिनों में OTP पाने वाले ऑर्डर के अनुपात पर 10% बैंड में आँकता है, और किसी प्रोवाइडर को तभी गिनता है जब उस अवधि में उसके कम से कम 20 ऑर्डर हों — इस सीमा से नीचे या बिना इतिहास वाले प्रोवाइडर तटस्थ माने जाते हैं, इसलिए नए ऑफ़र कभी उपेक्षित नहीं होते (वैकल्पिक; संकेत तटस्थ से शुरू होता है)। यदि prefer_provider भी सेट है, तो पसंदीदा प्रोवाइडर फिर भी सबसे पहले रहता है।
quantityintegerनहींआइटम की संख्या (1-100, डिफ़ॉल्ट 1)

डुप्लिकेट ऑर्डर बनाए बिना सुरक्षित रूप से रिट्राई करने के लिए Idempotency-Key हेडर पास करें। key में अक्षर, अंक, हाइफ़न और अंडरस्कोर (A-Z a-z 0-9 _ -) हो सकते हैं, अधिकतम 128 कैरेक्टर; अमान्य key को 422 VALIDATION_ERROR के साथ अस्वीकार किया जाता है। एक ही key और एक ही body के साथ रिट्राई करने पर मूल रिज़ल्ट दोबारा मिलता है (आंशिक सफलता के failed_count सहित)। ऐसा रिट्राई जो प्रोवाइडर तक पहुँच गया पर विफल हो गया, रिकॉर्ड हो जाता है और दोबारा वही एरर लौटाता है — दोबारा कोशिश के लिए नई key का इस्तेमाल करें। बिना साइड-इफ़ेक्ट वाली विफलताएँ (अपर्याप्त बैलेंस, कोई उपलब्ध ऑफ़र नहीं) key को रिलीज़ कर देती हैं, इसलिए आप टॉप-अप करके उसी key के साथ रिट्राई कर सकते हैं। किसी key को अलग body के साथ दोबारा इस्तेमाल करने पर 422 IDEMPOTENCY_KEY_REUSED मिलता है, और उस key के साथ अभी चल रहे रिक्वेस्ट पर 409 REQUEST_IN_PROGRESS मिलता है। create रिस्पॉन्स में failed_reason फ़ील्ड हमेशा null होता है — यह केवल ऑर्डर poll/list के समय भरता है।

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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: मनी फ़ील्ड USD मनी ऑब्जेक्ट हैं और रिस्पॉन्स में एक ही meta.fx { pair, rate, rate_as_of } होता है। rate प्रति 1 USD पूर्णांक IDR है, इसलिए USD = canonical_amount / rate। टोटल में 2 दशमलव; प्रति-आइटम कीमत/रिफ़ंड में 4 दशमलव उपयोग होते हैं। पूर्णतः धनात्मक राशि कभी भी 0.00 में राउंड नहीं होती। rate_as_of उस रेट का RFC3339 टाइमस्टैम्प (+00:00 रूप) है, या जब कोई टाइमस्टैम्प दर्ज नहीं है तो null

केवल v2: यदि कोई उपयोग योग्य USD/IDR रेट उपलब्ध नहीं है, तो मनी एंडपॉइंट मनी बॉडी के बजाय Retry-After हेडर के साथ 503 FX_RATE_UNAVAILABLE लौटाते हैं। v1 यह कभी नहीं लौटाता।

POST/orders/cancel

एक एक्टिव ऑर्डर कैंसल करता है। रेंटल कॉस्ट आपके अकाउंट बैलेंस में रिफंड हो जाती है।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
idintegerहाँकैंसल करने के लिए ऑर्डर ID

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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: मनी फ़ील्ड USD मनी ऑब्जेक्ट हैं और रिस्पॉन्स में एक ही meta.fx { pair, rate, rate_as_of } होता है। rate प्रति 1 USD पूर्णांक IDR है, इसलिए USD = canonical_amount / rate। टोटल में 2 दशमलव; प्रति-आइटम कीमत/रिफ़ंड में 4 दशमलव उपयोग होते हैं। पूर्णतः धनात्मक राशि कभी भी 0.00 में राउंड नहीं होती। rate_as_of उस रेट का RFC3339 टाइमस्टैम्प (+00:00 रूप) है, या जब कोई टाइमस्टैम्प दर्ज नहीं है तो null

केवल v2: यदि कोई उपयोग योग्य USD/IDR रेट उपलब्ध नहीं है, तो मनी एंडपॉइंट मनी बॉडी के बजाय Retry-After हेडर के साथ 503 FX_RATE_UNAVAILABLE लौटाते हैं। v1 यह कभी नहीं लौटाता।

POST/orders/finish

OTP प्राप्त होने के बाद ऑर्डर को कम्प्लीट मार्क करता है। एक्सपायरी का इंतज़ार करने के बजाय नंबर तुरंत रिलीज़ होता है।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
idintegerहाँफ़िनिश करने के लिए ऑर्डर ID

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

v1 के समान — केवल बेस पाथ बदलता है (/v1/v2)।

POST/orders/resend

रेंटेड नंबर पर SMS दोबारा भेजने का अनुरोध करता है। सभी प्लेटफ़ॉर्म रीसेंड सपोर्ट नहीं करते — रिस्पॉन्स में resent फ़ील्ड चेक करें।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
idintegerहाँSMS रीसेंड करने के लिए ऑर्डर ID

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

v1 के समान — केवल बेस पाथ बदलता है (/v1/v2)।

POST/orders/reactivate

पूरा हो चुका नंबर रीएक्टिवेट करता है — नया नंबर किराए पर लिए बिना उसी नंबर को दूसरे वेरिफ़िकेशन कोड के लिए दोबारा ऑर्डर करता है। केवल वही पूरा हो चुका ऑर्डर योग्य है जिसका नंबर रीएक्टिवेशन सपोर्ट करता है (ऑर्डर पर can_reactivate चेक करें, या reactivate-options से प्रीव्यू करें)। रीएक्टिवेट किया गया चाइल्ड एक नया ऑर्डर होता है, जो create जैसी ही शेप में लौटाया जाता है; बैलेंस ऑटोमैटिकली कट जाता है।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
idintegerहाँरीएक्टिवेट किया जाने वाला पूरा हो चुका ऑर्डर।
max_pricestringनहींवैकल्पिक कॉस्ट सीलिंग। USD decimal string (जैसे "0.50")। अगर लाइव कॉस्ट इससे ज़्यादा हो तो रीएक्टिवेशन 422 VALIDATION_ERROR के साथ अस्वीकार कर दिया जाता है।

create की तरह यह भी एक money mutation है — सुरक्षित रिट्राई के लिए Idempotency-Key हेडर पास करें (एक create और एक reactivate कभी भी एक ही key पर नहीं टकरा सकते)। किसी key को अलग body के साथ दोबारा इस्तेमाल करने पर 422 IDEMPOTENCY_KEY_REUSED मिलता है, और उस key के साथ अभी सेटल हो रहे रिक्वेस्ट पर 409 REQUEST_IN_PROGRESS मिलता है। जिस नंबर को रीएक्टिवेट नहीं किया जा सकता, वह 409 CONFLICT लौटाता है; बैलेंस बहुत कम होने पर 409 INSUFFICIENT_BALANCE मिलता है।

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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: मनी फ़ील्ड USD मनी ऑब्जेक्ट हैं और रिस्पॉन्स में एक ही meta.fx { pair, rate, rate_as_of } होता है। rate प्रति 1 USD पूर्णांक IDR है, इसलिए USD = canonical_amount / rate। टोटल में 2 दशमलव; प्रति-आइटम कीमत/रिफ़ंड में 4 दशमलव उपयोग होते हैं। पूर्णतः धनात्मक राशि कभी भी 0.00 में राउंड नहीं होती। rate_as_of उस रेट का RFC3339 टाइमस्टैम्प (+00:00 रूप) है, या जब कोई टाइमस्टैम्प दर्ज नहीं है तो null

केवल v2: यदि कोई उपयोग योग्य USD/IDR रेट उपलब्ध नहीं है, तो मनी एंडपॉइंट मनी बॉडी के बजाय Retry-After हेडर के साथ 503 FX_RATE_UNAVAILABLE लौटाते हैं। v1 यह कभी नहीं लौटाता।

GET/orders/{id}/reactivate-options

अभी रीएक्टिवेशन पर कितना चार्ज होगा, इसका प्रीव्यू देता है। केवल-पढ़ने के लिए — कोई Idempotency-Key इस्तेमाल नहीं करता और कुछ भी नहीं बनाता। कॉस्ट को FX रसीद के साथ USD money object के रूप में लौटाता है। यह केवल उसी पूरा हो चुके ऑर्डर के लिए उपलब्ध है जिसका नंबर रीएक्टिवेशन सपोर्ट करता है।

पाथ पैरामीटर्स

नामटाइपज़रूरीविवरण
idintegerहाँवह ऑर्डर ID जिसके लिए रीएक्टिवेशन कॉस्ट का प्रीव्यू करना है (path parameter)।

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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: मनी फ़ील्ड USD मनी ऑब्जेक्ट हैं और रिस्पॉन्स में एक ही meta.fx { pair, rate, rate_as_of } होता है। rate प्रति 1 USD पूर्णांक IDR है, इसलिए USD = canonical_amount / rate। टोटल में 2 दशमलव; प्रति-आइटम कीमत/रिफ़ंड में 4 दशमलव उपयोग होते हैं। पूर्णतः धनात्मक राशि कभी भी 0.00 में राउंड नहीं होती। rate_as_of उस रेट का RFC3339 टाइमस्टैम्प (+00:00 रूप) है, या जब कोई टाइमस्टैम्प दर्ज नहीं है तो null

केवल v2: यदि कोई उपयोग योग्य USD/IDR रेट उपलब्ध नहीं है, तो मनी एंडपॉइंट मनी बॉडी के बजाय Retry-After हेडर के साथ 503 FX_RATE_UNAVAILABLE लौटाते हैं। v1 यह कभी नहीं लौटाता।

GET/webhook

आपकी वर्तमान webhook नोटिफ़िकेशन कॉन्फ़िगरेशन लौटाता है।

पैरामीटर्स

कोई नहीं

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

v1 के समान — केवल बेस पाथ बदलता है (/v1/v2)।

PATCH/webhook

अपना webhook URL और/या secret अपडेट करें। पहली बार URL सेट करने पर secret ऑटो-जनरेट होता है। क्लियर करने के लिए खाली स्ट्रिंग भेजें। URL HTTPS होना चाहिए।

रिक्वेस्ट बॉडी

नामटाइपज़रूरीविवरण
webhook_urlstringनहींWebhook इवेंट प्राप्त करने के लिए HTTPS URL (क्लियर करने के लिए खाली स्ट्रिंग)
webhook_secretstringनहींHMAC-SHA256 सिग्नेचर के लिए शेयर्ड secret (पहली बार सेट पर छोड़ने पर ऑटो-जनरेट)

कम से कम एक फ़ील्ड ज़रूरी है।

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

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

v1 के समान — केवल बेस पाथ बदलता है (/v1/v2)।

POST/webhook/test

आपके कॉन्फ़िगर किए गए webhook URL पर एक टेस्ट इवेंट भेजता है। आपके सर्वर से HTTP स्टेटस कोड लौटाता है। लाइव होने से पहले endpoint वेरिफाई करने के लिए उपयोगी।

पैरामीटर्स

कोई नहीं

एग्ज़ांपल रिक्वेस्ट

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()

एग्ज़ांपल रिस्पॉन्स

200 OK
{
  "success": true,
  "data": {
    "status_code": 200
  }
}

v1 के समान — केवल बेस पाथ बदलता है (/v1/v2)।

Webhook नोटिफ़िकेशन

पोलिंग के बजाय ऑर्डर इवेंट्स के लिए रियल-टाइम पुश नोटिफ़िकेशन प्राप्त करने हेतु webhook URL कॉन्फ़िगर करें। बॉट स्क्रिप्ट्स के लिए यह रेकमेंडेड तरीक़ा है।

इवेंट्स

इवेंटट्रिगर
order.otp_receivedनया SMS मिला; पहचाना गया कोड null हो सकता है
order.completedऑर्डर कम्प्लीट मार्क हुआ (मैन्युअली या एक्सपायरी द्वारा)
order.expiredकोई SMS मिलने से पहले ऑर्डर एक्सपायर हुआ (बैलेंस रिफंड)
order.canceledयूज़र द्वारा ऑर्डर कैंसल (बैलेंस रिफंड)

हर नया SMS यह event भेजता है। otp_message मौजूद होने पर otp_code null हो सकता है। कई SMS event क्रम से बाहर आ सकते हैं; पुराने aggregate pair को अनदेखा करने के लिए sms_revision का उपयोग करें।

पेलोड

Webhook POST बॉडी
{
  "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"
  }
}

सिग्नेचर वेरिफ़िकेशन

हर webhook रिक्वेस्ट में X-Webhook-Signature हेडर शामिल होता है जिसमें रिक्वेस्ट बॉडी का HMAC-SHA256 सिग्नेचर होता है, आपके webhook_secret को key के रूप में उपयोग करते हुए:

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

रिक्वेस्ट ऑथेंटिक है यह सुनिश्चित करने के लिए अपने सर्वर पर इस सिग्नेचर को वेरिफाई करें। डिलीवरी फ़ायर-एंड-फ़ॉरगेट है जिसमें 3-सेकंड टाइमआउट और कोई रिट्राई नहीं।

रेट लिमिट्स

API रिक्वेस्ट प्रति endpoint ग्रुप rate-limited हैं। लिमिट पार करने पर 429 Too Many Requests रिस्पॉन्स मिलता है जिसमें Retry-After हेडर बताता है कितने सेकंड इंतज़ार करना है।

Endpoint ग्रुपलिमिटविंडो
कैटलॉग (देश, सर्विसेज़, प्रोडक्ट्स, एक्सचेंज रेट)5,000 रिक्वेस्ट60 सेकंड
बैलेंस600 रिक्वेस्ट60 सेकंड
ऑर्डर पढ़ना (सूची, गेट, एक्टिव)5,000 रिक्वेस्ट60 सेकंड
ऑर्डर बनाना3,000 रिक्वेस्ट60 सेकंड
ऑर्डर कैंसल करना1,000 रिक्वेस्ट60 सेकंड
ऑर्डर कार्रवाइयाँ (finish, resend)1,000 रिक्वेस्ट60 सेकंड
Webhook कॉन्फ़िगरेशन (गेट, अपडेट)600 रिक्वेस्ट60 सेकंड
Webhook टेस्ट10 रिक्वेस्ट60 सेकंड

एरर कोड

एरर रिस्पॉन्स में error.code में इनमें से एक कोड शामिल होता है:

कोडHTTPविवरण
UNAUTHORIZED401API token गायब या अमान्य
FORBIDDEN403एक्सेस अस्वीकृत
NOT_FOUND404रिसोर्स नहीं मिला (ऑर्डर, एक्सचेंज रेट, आदि)
CONFLICT409डुप्लिकेट रिक्वेस्ट या रिसोर्स कॉन्फ़्लिक्ट
INSUFFICIENT_BALANCE409ऑर्डर बनाने के लिए पर्याप्त बैलेंस नहीं
VALIDATION_ERROR422रिक्वेस्ट पैरामीटर्स वैलिडेशन में फ़ेल
RATE_LIMIT_EXCEEDED429बहुत ज़्यादा रिक्वेस्ट (Retry-After हेडर देखें)
INTERNAL_ERROR500इंटरनल सर्वर एरर
PROVIDER_ERROR422अपस्ट्रीम SMS प्रोवाइडर ने रिक्वेस्ट रिजेक्ट की। ऑर्डर बनाने में विफलता पर error में details हो सकता है: cause_counts (पुराने product_id ऑर्डर — कारण के अनुसार गिनती) या attempts (catalog_product_id ऑर्डर — प्रति प्रयास परिणाम), जिनके मान ok, no_numbers, insufficient_balance, price_rejected, provider_unavailable, provider_account_balance, provider_error होते हैं।
NO_OFFER_AVAILABLE422अनुरोधित प्रोडक्ट और नीति (मूल्य सीमा, उपलब्धता) से मेल खाता कोई सक्रिय ऑफ़र नहीं है।
CANCEL_TOO_EARLY409ऑर्डर कैंसल करने के लिए बहुत नया — 2 मिनट इंतज़ार करें
REQUEST_IN_PROGRESS409इस idempotency key के साथ एक क्रिएट रिक्वेस्ट अभी भी चल रहा है
IDEMPOTENCY_KEY_REUSED422यह idempotency key पहले से किसी अलग रिक्वेस्ट body के साथ इस्तेमाल हो चुकी है
SERVICE_UNAVAILABLE503सर्विस अस्थायी रूप से अनुपलब्ध (मेंटेनेंस)
FX_RATE_UNAVAILABLE503USD/IDR एक्सचेंज रेट अनुपलब्ध (v2 मनी एंडपॉइंट) — Retry-After हेडर के साथ 503 लौटाता है।
v1 → v2

v1 से v2 में माइग्रेशन

v1 IDR देता है; v2 USD देता है। दोनों वर्शन स्थायी रूप से साथ-साथ रहते हैं — कोई सनसेट नहीं है। प्रति इंटीग्रेशन एक वर्शन चुनें; बेस पाथ मिक्स न करें। मनी कैसे दर्शाई जाती है, इसके अलावा v2 v1 के समान है।

पहलूv1 · IDRv2 · USD
मनी फ़ील्डपूर्णांक IDR, जैसे 15000मनी ऑब्जेक्ट { amount, currency, canonical_amount, canonical_currency }
meta.fxअनुपस्थितहर मनी-बेयरिंग रिस्पॉन्स पर आवश्यक
करेंसीIDRUSD (हार्डकोडेड)
FX_RATE_UNAVAILABLEउपयोग योग्य रेट न होने पर नया 503 + Retry-After
प्रिसिज़नटोटल 2 दशमलव, कीमत/रिफ़ंड 4 दशमलव, धनात्मक के लिए ऊपर राउंड
GET /catalog/exchange-rate{pair, base_currency, quote_currency, rate}; ?pair का सम्मान करता है{pair, rate, rate_as_of}; ?pair नज़रअंदाज़ (केवल USD/IDR)

साथ-साथ उदाहरण

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 tier-slot ID है। अगर आप वही सटीक tier ऑर्डर करना चाहते हैं तो इसे सहेजें; इसकी कीमत और उपलब्धता उसी row में बदल सकती है। catalog_product_id routed ordering के लिए स्थिर देश+प्लेटफ़ॉर्म umbrella है; जब आप चाहते हैं कि सर्वर वर्तमान matching tier चुने, तो इसे वैकल्पिक operator_id, min_price, max_price, prefer_provider और policy के साथ उपयोग करें।

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" } }
}

माइग्रेशन चेकलिस्ट

  1. बेस पाथ /v1/v2 बदलें।
  2. मनी फ़ील्ड को ऑब्जेक्ट के रूप में पार्स करें — amount को दशमलव स्ट्रिंग के रूप में पढ़ें; currency "USD" है।
  3. लेजर रिकंसिलिएशन के लिए canonical_amount (सटीक IDR) का उपयोग करें; USD amount एक रेंडर-टाइम प्रोजेक्शन है और rate meta.fx में एक बार दर्शाया जाता है।
  4. नए FX_RATE_UNAVAILABLE (503) को हैंडल करें — Retry-After के बाद फिर कोशिश करें। v1 यह कभी नहीं लौटाता।