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

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

Overview

/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 रिस्पॉन्स मिलता है।

Base 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

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

Query Parameters

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

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

curl -s "https://api.smscode.gg/v1/catalog/services?country_id=6" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/catalog/services?country_id=6", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

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

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

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

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

Query Parameters

नामटाइपज़रूरीविवरण
country_idintegerनहींकंट्री ID से फ़िल्टर करें
platform_idintegerनहींप्लेटफ़ॉर्म/सर्विस ID से फ़िल्टर करें
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=6&platform_id=3&limit=10&page=1" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const params = new URLSearchParams({
  country_id: "6", platform_id: "3", limit: "10", page: "1",
});
const res = await fetch(`https://api.smscode.gg/v1/catalog/products?${params}`, {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/catalog/products",
    params={"country_id": 6, "platform_id": 3, "limit": 10, "page": 1},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

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

200 OK
{
  "success": true,
  "data": [
    {
      "id": 142,
      "name": "WhatsApp Indonesia",
      "country_id": 6,
      "platform_id": 3,
      "catalog_product_id": 87,
      "available": 42,
      "price": 15000,
      "active": true
    }
  ],
  "meta": { "page": 1, "limit": 10, "count": 1 }
}
GET /catalog/exchange-rate

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

Query Parameters

नामटाइपज़रूरीविवरण
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 के ज़रिए पेजिनेशन द्वारा फ़िल्टरिंग सपोर्ट करता है।

Query Parameters

नामटाइपज़रूरीविवरण
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,
      "phone_number": "+6281234567890",
      "amount": 15000,
      "otp_code": null,
      "otp_received_at": null,
      "expires_at": "2026-02-25T10:20:00+00:00",
      "canceled_at": null,
      "failed_reason": null
    }
  ]
}
GET /orders/{id}

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

Path Parameters

नामटाइपज़रूरीविवरण
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,
    "phone_number": "+6281234567890",
    "amount": 15000,
    "otp_code": "123456",
    "otp_received_at": "2026-02-25T10:05:00+00:00",
    "expires_at": "2026-02-25T10:20:00+00:00",
    "canceled_at": null,
    "failed_reason": null
  }
}
GET /orders/active

सभी वर्तमान एक्टिव ऑर्डर्स (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": "123456",
      "otp_message": "Your verification code is 123456",
      "otp_received_at": "2026-02-25T10:05:00+00:00",
      "expires_at": "2026-02-25T10:20:00+00:00",
      "failed_reason": null
    },
    {
      "id": 1002,
      "status": "ACTIVE",
      "otp_code": null,
      "otp_message": null,
      "otp_received_at": null,
      "expires_at": "2026-02-25T10:50:00+00:00",
      "failed_reason": null
    }
  ]
}
POST /orders/create

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

Request Body

नामटाइपज़रूरीविवरण
product_idintegerनहींऑर्डर करने के लिए प्रोडक्ट की ID। दोनों में से केवल एक दें: product_id या catalog_product_id, दोनों नहीं।
catalog_product_idintegerनहींस्थिर प्रोडक्ट ID — सर्वर मौजूदा सबसे अच्छा ऑफ़र चुनता है (सबसे सस्ता, विश्वसनीयता को ध्यान में रखते हुए)। यह या product_id में से कोई एक दें।
max_priceinteger · stringनहींवैकल्पिक मूल्य सीमा। v1: IDR पूर्णांक। v2: USD दशमलव स्ट्रिंग (जैसे "0.50")।
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 order by stable catalog_product_id — the server picks the best current offer
# (cheapest, reliability-aware). Optional max_price caps the price; on v1 it is an
# IDR integer, on v2 it is a USD decimal string (e.g. "0.50"). prefer_provider
# (provider code) is a soft tie-breaker. Pass EITHER product_id OR catalog_product_id.
curl -s -X POST https://api.smscode.gg/v1/orders/create \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-124" \
  -d '{"catalog_product_id":87,"max_price":20000}'
const res = await fetch("https://api.smscode.gg/v1/orders/create", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
    "Idempotency-Key": "unique-request-id-123",
  },
  body: JSON.stringify({ product_id: 142, quantity: 1 }),
});
const data = await res.json();
import requests

res = requests.post("https://api.smscode.gg/v1/orders/create",
    json={"product_id": 142, "quantity": 1},
    headers={
        "Authorization": "Bearer YOUR_API_TOKEN",
        "Idempotency-Key": "unique-request-id-123",
    })
data = res.json()

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

200 OK
{
  "success": true,
  "data": {
    "orders": [
      {
        "id": 1002,
        "status": "ACTIVE",
        "product_id": 142,
        "catalog_product_id": 87,
        "amount": 15000,
        "phone_number": "+6281234567891",
        "otp_code": null,
        "otp_received_at": null,
        "expires_at": "2026-02-25T10:50:00+00:00",
        "failed_reason": null
      }
    ],
    "failed_count": 0
  }
}
POST /orders/cancel

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

Request Body

नामटाइपज़रूरीविवरण
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 प्राप्त होने के बाद ऑर्डर को कम्प्लीट मार्क करता है। एक्सपायरी का इंतज़ार करने के बजाय नंबर तुरंत रिलीज़ होता है।

Request Body

नामटाइपज़रूरीविवरण
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 फ़ील्ड चेक करें।

Request Body

नामटाइपज़रूरीविवरण
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
  }
}
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 होना चाहिए।

Request Body

नामटाइपज़रूरीविवरण
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रेंटेड नंबर पर OTP कोड डिलीवर हुआ
order.completedऑर्डर कम्प्लीट मार्क हुआ (मैन्युअली या एक्सपायरी द्वारा)
order.expiredऑर्डर बिना OTP के एक्सपायर हुआ (बैलेंस रिफंड)
order.canceledयूज़र द्वारा ऑर्डर कैंसल (बैलेंस रिफंड)

Payload

Webhook POST Body
{
  "event": "order.otp_received",
  "timestamp": "2026-02-25T12:00:00+00:00",
  "data": {
    "order_id": 1001,
    "phone_number": "+628123456789",
    "otp_code": "1234",
    "otp_message": "Your verification code is 1234",
    "product_id": 42,
    "catalog_product_id": 87,
    "country": "Indonesia",
    "platform": "WhatsApp"
  }
}

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

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

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

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

Rate Limits

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

Endpoint ग्रुपलिमिटविंडो
Catalog (countries, services, products, exchange-rate)5,000 रिक्वेस्ट60 सेकंड
Balance600 रिक्वेस्ट60 सेकंड
Order reads (list, get, active)5,000 रिक्वेस्ट60 सेकंड
Order create3,000 रिक्वेस्ट60 सेकंड
Order cancel1,000 रिक्वेस्ट60 सेकंड
Order actions (finish, resend)1,000 रिक्वेस्ट60 सेकंड
Webhook config (get, update)600 रिक्वेस्ट60 सेकंड
Webhook test10 रिक्वेस्ट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 में <code>details</code> हो सकता है: <code>cause_counts</code> (पुराने <code>product_id</code> ऑर्डर — कारण के अनुसार गिनती) या <code>attempts</code> (<code>catalog_product_id</code> ऑर्डर — प्रति प्रयास परिणाम), जिनके मान <code>ok</code>, <code>no_numbers</code>, <code>insufficient_balance</code>, <code>price_rejected</code>, <code>provider_unavailable</code>, <code>provider_account_balance</code>, <code>provider_error</code> होते हैं।
NO_OFFER_AVAILABLE422अनुरोधित प्रोडक्ट और नीति (मूल्य सीमा, उपलब्धता) से मेल खाता कोई सक्रिय ऑफ़र नहीं है।
CANCEL_TOO_EARLY409ऑर्डर कैंसल करने के लिए बहुत नया — 2 मिनट इंतज़ार करें
REQUEST_IN_PROGRESS409इस idempotency key के साथ एक क्रिएट रिक्वेस्ट अभी भी चल रहा है
IDEMPOTENCY_KEY_REUSED422यह idempotency key पहले से किसी अलग रिक्वेस्ट body के साथ इस्तेमाल हो चुकी है
SERVICE_UNAVAILABLE503सर्विस अस्थायी रूप से अनुपलब्ध (मेंटेनेंस)

Overview

/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 रिस्पॉन्स मिलता है।

Base 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

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

Query Parameters

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

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

curl -s "https://api.smscode.gg/v2/catalog/services?country_id=6" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v2/catalog/services?country_id=6", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

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

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

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

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

GET /catalog/products

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

Query Parameters

नामटाइपज़रूरीविवरण
country_idintegerनहींकंट्री ID से फ़िल्टर करें
platform_idintegerनहींप्लेटफ़ॉर्म/सर्विस ID से फ़िल्टर करें
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=6&platform_id=3&limit=10&page=1" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const params = new URLSearchParams({
  country_id: "6", platform_id: "3", limit: "10", page: "1",
});
const res = await fetch(`https://api.smscode.gg/v2/catalog/products?${params}`, {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v2/catalog/products",
    params={"country_id": 6, "platform_id": 3, "limit": 10, "page": 1},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

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

200 OK
{
  "success": true,
  "data": [
    {
      "id": 142,
      "name": "WhatsApp Indonesia",
      "country_id": 6,
      "platform_id": 3,
      "catalog_product_id": 87,
      "available": 42,
      "price": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
      "active": true
    }
  ],
  "meta": { "page": 1, "limit": 10, "count": 1, "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}

v2: मनी फ़ील्ड 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 के ज़रिए पेजिनेशन द्वारा फ़िल्टरिंग सपोर्ट करता है।

Query Parameters

नामटाइपज़रूरीविवरण
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,
      "phone_number": "+6281234567890",
      "amount": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
      "otp_code": null,
      "otp_received_at": null,
      "expires_at": "2026-02-25T10:20:00+00:00",
      "canceled_at": null,
      "failed_reason": null
    }
  ],
  "meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}

v2: मनी फ़ील्ड 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 के अनुसार एक ऑर्डर लौटाता है। सिर्फ़ ऑथेंटिकेटेड यूज़र के ऑर्डर लौटाता है।

Path Parameters

नामटाइपज़रूरीविवरण
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,
    "phone_number": "+6281234567890",
    "amount": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
    "otp_code": "123456",
    "otp_received_at": "2026-02-25T10:05:00+00:00",
    "expires_at": "2026-02-25T10:20:00+00:00",
    "canceled_at": null,
    "failed_reason": null
  },
  "meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}

v2: मनी फ़ील्ड 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": "123456",
      "otp_message": "Your verification code is 123456",
      "otp_received_at": "2026-02-25T10:05:00+00:00",
      "expires_at": "2026-02-25T10:20:00+00:00",
      "failed_reason": null
    },
    {
      "id": 1002,
      "status": "ACTIVE",
      "otp_code": null,
      "otp_message": null,
      "otp_received_at": null,
      "expires_at": "2026-02-25T10:50:00+00:00",
      "failed_reason": null
    }
  ]
}

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

POST /orders/create

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

Request Body

नामटाइपज़रूरीविवरण
product_idintegerनहींऑर्डर करने के लिए प्रोडक्ट की ID। दोनों में से केवल एक दें: product_id या catalog_product_id, दोनों नहीं।
catalog_product_idintegerनहींस्थिर प्रोडक्ट ID — सर्वर मौजूदा सबसे अच्छा ऑफ़र चुनता है (सबसे सस्ता, विश्वसनीयता को ध्यान में रखते हुए)। यह या product_id में से कोई एक दें।
max_priceinteger · stringनहींवैकल्पिक मूल्य सीमा। v1: IDR पूर्णांक। v2: USD दशमलव स्ट्रिंग (जैसे "0.50")।
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 '{"product_id":142,"quantity":1}'

# Or order by stable catalog_product_id — the server picks the best current offer
# (cheapest, reliability-aware). Optional max_price caps the price; on v1 it is an
# IDR integer, on v2 it is a USD decimal string (e.g. "0.50"). prefer_provider
# (provider code) is a soft tie-breaker. Pass EITHER product_id OR catalog_product_id.
curl -s -X POST https://api.smscode.gg/v2/orders/create \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-124" \
  -d '{"catalog_product_id":87,"max_price":20000}'
const res = await fetch("https://api.smscode.gg/v2/orders/create", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
    "Idempotency-Key": "unique-request-id-123",
  },
  body: JSON.stringify({ product_id: 142, quantity: 1 }),
});
const data = await res.json();
import requests

res = requests.post("https://api.smscode.gg/v2/orders/create",
    json={"product_id": 142, "quantity": 1},
    headers={
        "Authorization": "Bearer YOUR_API_TOKEN",
        "Idempotency-Key": "unique-request-id-123",
    })
data = res.json()

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

200 OK
{
  "success": true,
  "data": {
    "orders": [
      {
        "id": 1002,
        "status": "ACTIVE",
        "product_id": 142,
        "catalog_product_id": 87,
        "amount": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
        "phone_number": "+6281234567891",
        "otp_code": null,
        "otp_received_at": null,
        "expires_at": "2026-02-25T10:50:00+00:00",
        "failed_reason": null
      }
    ],
    "failed_count": 0
  },
  "meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}

v2: मनी फ़ील्ड 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

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

Request Body

नामटाइपज़रूरीविवरण
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 प्राप्त होने के बाद ऑर्डर को कम्प्लीट मार्क करता है। एक्सपायरी का इंतज़ार करने के बजाय नंबर तुरंत रिलीज़ होता है।

Request Body

नामटाइपज़रूरीविवरण
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 फ़ील्ड चेक करें।

Request Body

नामटाइपज़रूरीविवरण
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)।

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 होना चाहिए।

Request Body

नामटाइपज़रूरीविवरण
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रेंटेड नंबर पर OTP कोड डिलीवर हुआ
order.completedऑर्डर कम्प्लीट मार्क हुआ (मैन्युअली या एक्सपायरी द्वारा)
order.expiredऑर्डर बिना OTP के एक्सपायर हुआ (बैलेंस रिफंड)
order.canceledयूज़र द्वारा ऑर्डर कैंसल (बैलेंस रिफंड)

Payload

Webhook POST Body
{
  "event": "order.otp_received",
  "timestamp": "2026-02-25T12:00:00+00:00",
  "data": {
    "order_id": 1001,
    "phone_number": "+628123456789",
    "otp_code": "1234",
    "otp_message": "Your verification code is 1234",
    "product_id": 42,
    "catalog_product_id": 87,
    "country": "Indonesia",
    "platform": "WhatsApp"
  }
}

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

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

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

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

Rate Limits

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

Endpoint ग्रुपलिमिटविंडो
Catalog (countries, services, products, exchange-rate)5,000 रिक्वेस्ट60 सेकंड
Balance600 रिक्वेस्ट60 सेकंड
Order reads (list, get, active)5,000 रिक्वेस्ट60 सेकंड
Order create3,000 रिक्वेस्ट60 सेकंड
Order cancel1,000 रिक्वेस्ट60 सेकंड
Order actions (finish, resend)1,000 रिक्वेस्ट60 सेकंड
Webhook config (get, update)600 रिक्वेस्ट60 सेकंड
Webhook test10 रिक्वेस्ट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 में <code>details</code> हो सकता है: <code>cause_counts</code> (पुराने <code>product_id</code> ऑर्डर — कारण के अनुसार गिनती) या <code>attempts</code> (<code>catalog_product_id</code> ऑर्डर — प्रति प्रयास परिणाम), जिनके मान <code>ok</code>, <code>no_numbers</code>, <code>insufficient_balance</code>, <code>price_rejected</code>, <code>provider_unavailable</code>, <code>provider_account_balance</code>, <code>provider_error</code> होते हैं।
NO_OFFER_AVAILABLE422अनुरोधित प्रोडक्ट और नीति (मूल्य सीमा, उपलब्धता) से मेल खाता कोई सक्रिय ऑफ़र नहीं है।
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": 6,
      "platform_id": 3,
      "catalog_product_id": 87,
      "available": 42,
      "price": 15000,
      "active": true
    }
  ],
  "meta": { "page": 1, "limit": 10, "count": 1 }
}
v2
{
  "success": true,
  "data": [
    {
      "id": 142,
      "name": "WhatsApp Indonesia",
      "country_id": 6,
      "platform_id": 3,
      "catalog_product_id": 87,
      "available": 42,
      "price": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
      "active": true
    }
  ],
  "meta": { "page": 1, "limit": 10, "count": 1, "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}

catalog_product_id स्थिर प्रोडक्ट पहचान है (हर देश + प्लेटफ़ॉर्म के लिए एक) — इसे अपने सिस्टम में स्टोर करना सुरक्षित है और इससे सीधे ऑर्डर भी किया जा सकता है: catalog_product_id (और वैकल्पिक max_price व prefer_provider) के साथ ऑर्डर करें और सर्वर आपके लिए लाइव ऑफ़र चुन लेगा। प्रति-ऑफ़र product_id वाला रास्ता अब भी समर्थित और बैकवर्ड-कम्पैटिबल है — वह id अस्थिर है और जब भी प्रोवाइडर का प्राइस टियर बदलता है यह बदल जाती है, इसलिए ऑर्डर से पहले कैटलॉग दोबारा फ़ेच करने की सलाह केवल उसी रास्ते पर लागू होती है।

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 यह कभी नहीं लौटाता।