API डॉक्यूमेंटेशन
वर्चुअल नंबर, ऑर्डर्स, और अकाउंट बैलेंस तक प्रोग्रामैटिक एक्सेस।
Overview
/v1 API के सभी मनी फ़ील्ड IDR में हैं (इंडोनेशियन रुपिया), पूर्णांक इकाइयों के रूप में — उदाहरण के लिए "price": 15000 और "balance": 500000 का मतलब Rp 15,000 और Rp 500,000 है। उसी लेजर के USD-नेटिव प्रोजेक्शन के लिए, ऊपर दिए गए वर्शन टॉगल से v2 API पर स्विच करें।
⟩ऑथेंटिकेशन
सभी API रिक्वेस्ट के लिए Bearer token ज़रूरी है। डैशबोर्ड में Account Settings से एक जनरेट करें, फिर हर रिक्वेस्ट में शामिल करें:
बिना वैध token वाली रिक्वेस्ट को 401 UNAUTHORIZED रिस्पॉन्स मिलता है।
⟩Base URL
नीचे दिए गए सभी endpoint पाथ इसके रिलेटिव हैं:
⟩रिस्पॉन्स फ़ॉर्मेट
हर रिस्पॉन्स एक कंसिस्टेंट एन्वेलप के साथ 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 पर स्विच करें।
/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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": [
{
"id": 6,
"code": "ID",
"name": "Indonesia",
"dial_code": "+62",
"emoji": "🇮🇩",
"active": true
}
]
} /catalog/services उपलब्ध सर्विसेज़ (प्लेटफ़ॉर्म) की सूची लौटाता है। वैकल्पिक रूप से देश के अनुसार फ़िल्टर करें।
Query Parameters
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
country_id | integer | नहीं | इस देश के लिए उपलब्ध सर्विसेज़ फ़िल्टर करें |
एग्ज़ांपल रिक्वेस्ट
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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": [
{
"id": 3,
"code": "wa",
"name": "WhatsApp",
"active": true
}
]
} /catalog/products उपलब्ध प्रोडक्ट्स की पेजिनेटेड सूची लौटाता है। देश और/या प्लेटफ़ॉर्म के अनुसार फ़िल्टर करें।
Query Parameters
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
country_id | integer | नहीं | कंट्री ID से फ़िल्टर करें |
platform_id | integer | नहीं | प्लेटफ़ॉर्म/सर्विस ID से फ़िल्टर करें |
sort | string | नहीं | सॉर्ट ऑर्डर: price_asc (डिफ़ॉल्ट), price_desc, available_asc, available_desc, name_asc, name_desc |
limit | integer | नहीं | प्रति पेज रिज़ल्ट (1-10,000, डिफ़ॉल्ट 1,000) |
page | integer | नहीं | पेज नंबर (न्यूनतम 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": [
{
"id": 142,
"name": "WhatsApp Indonesia",
"country_id": 6,
"platform_id": 3,
"catalog_product_id": 87,
"available": 42,
"price": 15000,
"active": true
}
],
"meta": { "page": 1, "limit": 10, "count": 1 }
} /catalog/exchange-rate करेंसी कन्वर्ज़न के लिए उपयोग किया जाने वाला वर्तमान USD/IDR एक्सचेंज रेट लौटाता है।
Query Parameters
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
pair | string | नहीं | करेंसी पेयर (डिफ़ॉल्ट: 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"pair": "USD/IDR",
"base_currency": "USD",
"quote_currency": "IDR",
"rate": 16250
}
} /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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"currency": "IDR",
"balance": 500000
}
} /orders ऑथेंटिकेटेड यूज़र के ऑर्डर्स की सूची लौटाता है, सबसे हाल के पहले। स्टेटस और offset के ज़रिए पेजिनेशन द्वारा फ़िल्टरिंग सपोर्ट करता है।
Query Parameters
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
limit | integer | नहीं | अधिकतम रिज़ल्ट (1-100, डिफ़ॉल्ट 20) |
offset | integer | नहीं | स्किप करने के लिए रिज़ल्ट की संख्या (डिफ़ॉल्ट 0) |
status | string | नहीं | स्टेटस से फ़िल्टर करें: 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": [
{
"id": 1001,
"status": "ACTIVE",
"created_at": "2026-02-25T10:00:00+00:00",
"product_id": 142,
"phone_number": "+6281234567890",
"amount": 15000,
"otp_code": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:20:00+00:00",
"canceled_at": null,
"failed_reason": null
}
]
} /orders/{id} ID के अनुसार एक ऑर्डर लौटाता है। सिर्फ़ ऑथेंटिकेटेड यूज़र के ऑर्डर लौटाता है।
Path Parameters
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | integer | हाँ | ऑर्डर 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"id": 1001,
"status": "OTP_RECEIVED",
"created_at": "2026-02-25T10:00:00+00:00",
"product_id": 142,
"phone_number": "+6281234567890",
"amount": 15000,
"otp_code": "123456",
"otp_received_at": "2026-02-25T10:05:00+00:00",
"expires_at": "2026-02-25T10:20:00+00:00",
"canceled_at": null,
"failed_reason": null
}
} /orders/active सभी वर्तमान एक्टिव ऑर्डर्स (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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": [
{
"id": 1001,
"status": "OTP_RECEIVED",
"otp_code": "123456",
"otp_message": "Your verification code is 123456",
"otp_received_at": "2026-02-25T10:05:00+00:00",
"expires_at": "2026-02-25T10:20:00+00:00",
"failed_reason": null
},
{
"id": 1002,
"status": "ACTIVE",
"otp_code": null,
"otp_message": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:50:00+00:00",
"failed_reason": null
}
]
} /orders/create एक नया वर्चुअल नंबर ऑर्डर बनाता है। बैलेंस ऑटोमैटिकली कटता है। नेटवर्क रिट्राई पर डुप्लिकेट ऑर्डर रोकने के लिए वैकल्पिक Idempotency-Key हेडर सपोर्ट करता है।
Request Body
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
product_id | integer | नहीं | ऑर्डर करने के लिए प्रोडक्ट की ID। दोनों में से केवल एक दें: product_id या catalog_product_id, दोनों नहीं। |
catalog_product_id | integer | नहीं | स्थिर प्रोडक्ट ID — सर्वर मौजूदा सबसे अच्छा ऑफ़र चुनता है (सबसे सस्ता, विश्वसनीयता को ध्यान में रखते हुए)। यह या product_id में से कोई एक दें। |
max_price | integer · string | नहीं | वैकल्पिक मूल्य सीमा। v1: IDR पूर्णांक। v2: USD दशमलव स्ट्रिंग (जैसे "0.50")। |
prefer_provider | string | नहीं | वैकल्पिक प्रोवाइडर कोड, जब ऑफ़र बराबर हों तो इसे प्राथमिकता दी जाती है। |
policy | string | नहीं | वैकल्पिक रूटिंग नीति, केवल catalog_product_id के साथ मान्य। मान: cheapest (डिफ़ॉल्ट) सबसे कम कीमत वाला स्वस्थ ऑफ़र चुनता है; best_success पहले हाल की डिलीवरी सफलता के आधार पर ऑफ़र को क्रमबद्ध करता है। best_success हर प्रोवाइडर को पिछले 30 पूर्ण दिनों में OTP पाने वाले ऑर्डर के अनुपात पर 10% बैंड में आँकता है, और किसी प्रोवाइडर को तभी गिनता है जब उस अवधि में उसके कम से कम 20 ऑर्डर हों — इस सीमा से नीचे या बिना इतिहास वाले प्रोवाइडर तटस्थ माने जाते हैं, इसलिए नए ऑफ़र कभी उपेक्षित नहीं होते (वैकल्पिक; संकेत तटस्थ से शुरू होता है)। यदि prefer_provider भी सेट है, तो पसंदीदा प्रोवाइडर फिर भी सबसे पहले रहता है। |
quantity | integer | नहीं | आइटम की संख्या (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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"orders": [
{
"id": 1002,
"status": "ACTIVE",
"product_id": 142,
"catalog_product_id": 87,
"amount": 15000,
"phone_number": "+6281234567891",
"otp_code": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:50:00+00:00",
"failed_reason": null
}
],
"failed_count": 0
}
} /orders/cancel एक एक्टिव ऑर्डर कैंसल करता है। रेंटल कॉस्ट आपके अकाउंट बैलेंस में रिफंड हो जाती है।
Request Body
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | integer | हाँ | कैंसल करने के लिए ऑर्डर 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"order_id": 1001,
"status": "CANCELED",
"refund_amount": 15000,
"new_balance": 515000
}
} /orders/finish OTP प्राप्त होने के बाद ऑर्डर को कम्प्लीट मार्क करता है। एक्सपायरी का इंतज़ार करने के बजाय नंबर तुरंत रिलीज़ होता है।
Request Body
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | integer | हाँ | फ़िनिश करने के लिए ऑर्डर 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"order_id": 1001,
"status": "COMPLETED"
}
} /orders/resend रेंटेड नंबर पर SMS दोबारा भेजने का अनुरोध करता है। सभी प्लेटफ़ॉर्म रीसेंड सपोर्ट नहीं करते — रिस्पॉन्स में resent फ़ील्ड चेक करें।
Request Body
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | integer | हाँ | 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"order_id": 1001,
"status": "ACTIVE",
"resent": true
}
} /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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} /webhook अपना webhook URL और/या secret अपडेट करें। पहली बार URL सेट करने पर secret ऑटो-जनरेट होता है। क्लियर करने के लिए खाली स्ट्रिंग भेजें। URL HTTPS होना चाहिए।
Request Body
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
webhook_url | string | नहीं | Webhook इवेंट प्राप्त करने के लिए HTTPS URL (क्लियर करने के लिए खाली स्ट्रिंग) |
webhook_secret | string | नहीं | 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} /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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"status_code": 200
}
} ⟩Webhook नोटिफ़िकेशन
पोलिंग के बजाय ऑर्डर इवेंट्स के लिए रियल-टाइम पुश नोटिफ़िकेशन प्राप्त करने हेतु webhook URL कॉन्फ़िगर करें। बॉट स्क्रिप्ट्स के लिए यह रेकमेंडेड तरीक़ा है।
इवेंट्स
| इवेंट | ट्रिगर |
|---|---|
order.otp_received | रेंटेड नंबर पर OTP कोड डिलीवर हुआ |
order.completed | ऑर्डर कम्प्लीट मार्क हुआ (मैन्युअली या एक्सपायरी द्वारा) |
order.expired | ऑर्डर बिना OTP के एक्सपायर हुआ (बैलेंस रिफंड) |
order.canceled | यूज़र द्वारा ऑर्डर कैंसल (बैलेंस रिफंड) |
Payload
{
"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 के रूप में उपयोग करते हुए:
रिक्वेस्ट ऑथेंटिक है यह सुनिश्चित करने के लिए अपने सर्वर पर इस सिग्नेचर को वेरिफाई करें। डिलीवरी फ़ायर-एंड-फ़ॉरगेट है जिसमें 3-सेकंड टाइमआउट और कोई रिट्राई नहीं।
⟩Rate Limits
API रिक्वेस्ट प्रति endpoint ग्रुप rate-limited हैं। लिमिट पार करने पर 429 Too Many Requests रिस्पॉन्स मिलता है जिसमें Retry-After हेडर बताता है कितने सेकंड इंतज़ार करना है।
| Endpoint ग्रुप | लिमिट | विंडो |
|---|---|---|
| Catalog (countries, services, products, exchange-rate) | 5,000 रिक्वेस्ट | 60 सेकंड |
| Balance | 600 रिक्वेस्ट | 60 सेकंड |
| Order reads (list, get, active) | 5,000 रिक्वेस्ट | 60 सेकंड |
| Order create | 3,000 रिक्वेस्ट | 60 सेकंड |
| Order cancel | 1,000 रिक्वेस्ट | 60 सेकंड |
| Order actions (finish, resend) | 1,000 रिक्वेस्ट | 60 सेकंड |
| Webhook config (get, update) | 600 रिक्वेस्ट | 60 सेकंड |
| Webhook test | 10 रिक्वेस्ट | 60 सेकंड |
⟩एरर कोड
एरर रिस्पॉन्स में error.code में इनमें से एक कोड शामिल होता है:
| कोड | HTTP | विवरण |
|---|---|---|
UNAUTHORIZED | 401 | API token गायब या अमान्य |
FORBIDDEN | 403 | एक्सेस अस्वीकृत |
NOT_FOUND | 404 | रिसोर्स नहीं मिला (ऑर्डर, एक्सचेंज रेट, आदि) |
CONFLICT | 409 | डुप्लिकेट रिक्वेस्ट या रिसोर्स कॉन्फ़्लिक्ट |
INSUFFICIENT_BALANCE | 409 | ऑर्डर बनाने के लिए पर्याप्त बैलेंस नहीं |
VALIDATION_ERROR | 422 | रिक्वेस्ट पैरामीटर्स वैलिडेशन में फ़ेल |
RATE_LIMIT_EXCEEDED | 429 | बहुत ज़्यादा रिक्वेस्ट (Retry-After हेडर देखें) |
INTERNAL_ERROR | 500 | इंटरनल सर्वर एरर |
PROVIDER_ERROR | 422 | अपस्ट्रीम 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_AVAILABLE | 422 | अनुरोधित प्रोडक्ट और नीति (मूल्य सीमा, उपलब्धता) से मेल खाता कोई सक्रिय ऑफ़र नहीं है। |
CANCEL_TOO_EARLY | 409 | ऑर्डर कैंसल करने के लिए बहुत नया — 2 मिनट इंतज़ार करें |
REQUEST_IN_PROGRESS | 409 | इस idempotency key के साथ एक क्रिएट रिक्वेस्ट अभी भी चल रहा है |
IDEMPOTENCY_KEY_REUSED | 422 | यह idempotency key पहले से किसी अलग रिक्वेस्ट body के साथ इस्तेमाल हो चुकी है |
SERVICE_UNAVAILABLE | 503 | सर्विस अस्थायी रूप से अनुपलब्ध (मेंटेनेंस) |
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 स्टोर या ट्रांज़ैक्ट नहीं करता।
⟩ऑथेंटिकेशन
सभी API रिक्वेस्ट के लिए Bearer token ज़रूरी है। डैशबोर्ड में Account Settings से एक जनरेट करें, फिर हर रिक्वेस्ट में शामिल करें:
बिना वैध token वाली रिक्वेस्ट को 401 UNAUTHORIZED रिस्पॉन्स मिलता है।
⟩Base URL
नीचे दिए गए सभी endpoint पाथ इसके रिलेटिव हैं:
⟩रिस्पॉन्स फ़ॉर्मेट
हर रिस्पॉन्स एक कंसिस्टेंट एन्वेलप के साथ JSON लौटाता है। सभी रिस्पॉन्स में डीबगिंग के लिए x-request-id हेडर शामिल होता है।
{
"success": true,
"data": { ... }
} {
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable message"
}
} v2 एरर: कोई उपयोग योग्य एक्सचेंज रेट नहीं (503)
{
"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 स्टोर या ट्रांज़ैक्ट नहीं करता।
/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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": [
{
"id": 6,
"code": "ID",
"name": "Indonesia",
"dial_code": "+62",
"emoji": "🇮🇩",
"active": true
}
]
} v1 के समान — केवल बेस पाथ बदलता है (/v1 → /v2)।
/catalog/services उपलब्ध सर्विसेज़ (प्लेटफ़ॉर्म) की सूची लौटाता है। वैकल्पिक रूप से देश के अनुसार फ़िल्टर करें।
Query Parameters
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
country_id | integer | नहीं | इस देश के लिए उपलब्ध सर्विसेज़ फ़िल्टर करें |
एग्ज़ांपल रिक्वेस्ट
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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": [
{
"id": 3,
"code": "wa",
"name": "WhatsApp",
"active": true
}
]
} v1 के समान — केवल बेस पाथ बदलता है (/v1 → /v2)।
/catalog/products उपलब्ध प्रोडक्ट्स की पेजिनेटेड सूची लौटाता है। देश और/या प्लेटफ़ॉर्म के अनुसार फ़िल्टर करें।
Query Parameters
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
country_id | integer | नहीं | कंट्री ID से फ़िल्टर करें |
platform_id | integer | नहीं | प्लेटफ़ॉर्म/सर्विस ID से फ़िल्टर करें |
sort | string | नहीं | सॉर्ट ऑर्डर: price_asc (डिफ़ॉल्ट), price_desc, available_asc, available_desc, name_asc, name_desc |
limit | integer | नहीं | प्रति पेज रिज़ल्ट (1-10,000, डिफ़ॉल्ट 1,000) |
page | integer | नहीं | पेज नंबर (न्यूनतम 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()एग्ज़ांपल रिस्पॉन्स
{
"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 यह कभी नहीं लौटाता।
/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()एग्ज़ांपल रिस्पॉन्स
{
"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 लौटाता है।
/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()एग्ज़ांपल रिस्पॉन्स
{
"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 यह कभी नहीं लौटाता।
/orders ऑथेंटिकेटेड यूज़र के ऑर्डर्स की सूची लौटाता है, सबसे हाल के पहले। स्टेटस और offset के ज़रिए पेजिनेशन द्वारा फ़िल्टरिंग सपोर्ट करता है।
Query Parameters
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
limit | integer | नहीं | अधिकतम रिज़ल्ट (1-100, डिफ़ॉल्ट 20) |
offset | integer | नहीं | स्किप करने के लिए रिज़ल्ट की संख्या (डिफ़ॉल्ट 0) |
status | string | नहीं | स्टेटस से फ़िल्टर करें: 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()एग्ज़ांपल रिस्पॉन्स
{
"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 यह कभी नहीं लौटाता।
/orders/{id} ID के अनुसार एक ऑर्डर लौटाता है। सिर्फ़ ऑथेंटिकेटेड यूज़र के ऑर्डर लौटाता है।
Path Parameters
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | integer | हाँ | ऑर्डर 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()एग्ज़ांपल रिस्पॉन्स
{
"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 यह कभी नहीं लौटाता।
/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()एग्ज़ांपल रिस्पॉन्स
{
"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 के अंतर्गत)।
/orders/create एक नया वर्चुअल नंबर ऑर्डर बनाता है। बैलेंस ऑटोमैटिकली कटता है। नेटवर्क रिट्राई पर डुप्लिकेट ऑर्डर रोकने के लिए वैकल्पिक Idempotency-Key हेडर सपोर्ट करता है।
Request Body
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
product_id | integer | नहीं | ऑर्डर करने के लिए प्रोडक्ट की ID। दोनों में से केवल एक दें: product_id या catalog_product_id, दोनों नहीं। |
catalog_product_id | integer | नहीं | स्थिर प्रोडक्ट ID — सर्वर मौजूदा सबसे अच्छा ऑफ़र चुनता है (सबसे सस्ता, विश्वसनीयता को ध्यान में रखते हुए)। यह या product_id में से कोई एक दें। |
max_price | integer · string | नहीं | वैकल्पिक मूल्य सीमा। v1: IDR पूर्णांक। v2: USD दशमलव स्ट्रिंग (जैसे "0.50")। |
prefer_provider | string | नहीं | वैकल्पिक प्रोवाइडर कोड, जब ऑफ़र बराबर हों तो इसे प्राथमिकता दी जाती है। |
policy | string | नहीं | वैकल्पिक रूटिंग नीति, केवल catalog_product_id के साथ मान्य। मान: cheapest (डिफ़ॉल्ट) सबसे कम कीमत वाला स्वस्थ ऑफ़र चुनता है; best_success पहले हाल की डिलीवरी सफलता के आधार पर ऑफ़र को क्रमबद्ध करता है। best_success हर प्रोवाइडर को पिछले 30 पूर्ण दिनों में OTP पाने वाले ऑर्डर के अनुपात पर 10% बैंड में आँकता है, और किसी प्रोवाइडर को तभी गिनता है जब उस अवधि में उसके कम से कम 20 ऑर्डर हों — इस सीमा से नीचे या बिना इतिहास वाले प्रोवाइडर तटस्थ माने जाते हैं, इसलिए नए ऑफ़र कभी उपेक्षित नहीं होते (वैकल्पिक; संकेत तटस्थ से शुरू होता है)। यदि prefer_provider भी सेट है, तो पसंदीदा प्रोवाइडर फिर भी सबसे पहले रहता है। |
quantity | integer | नहीं | आइटम की संख्या (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()एग्ज़ांपल रिस्पॉन्स
{
"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 यह कभी नहीं लौटाता।
/orders/cancel एक एक्टिव ऑर्डर कैंसल करता है। रेंटल कॉस्ट आपके अकाउंट बैलेंस में रिफंड हो जाती है।
Request Body
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | integer | हाँ | कैंसल करने के लिए ऑर्डर 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()एग्ज़ांपल रिस्पॉन्स
{
"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 यह कभी नहीं लौटाता।
/orders/finish OTP प्राप्त होने के बाद ऑर्डर को कम्प्लीट मार्क करता है। एक्सपायरी का इंतज़ार करने के बजाय नंबर तुरंत रिलीज़ होता है।
Request Body
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | integer | हाँ | फ़िनिश करने के लिए ऑर्डर 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"order_id": 1001,
"status": "COMPLETED"
}
} v1 के समान — केवल बेस पाथ बदलता है (/v1 → /v2)।
/orders/resend रेंटेड नंबर पर SMS दोबारा भेजने का अनुरोध करता है। सभी प्लेटफ़ॉर्म रीसेंड सपोर्ट नहीं करते — रिस्पॉन्स में resent फ़ील्ड चेक करें।
Request Body
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | integer | हाँ | 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"order_id": 1001,
"status": "ACTIVE",
"resent": true
}
} v1 के समान — केवल बेस पाथ बदलता है (/v1 → /v2)।
/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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} v1 के समान — केवल बेस पाथ बदलता है (/v1 → /v2)।
/webhook अपना webhook URL और/या secret अपडेट करें। पहली बार URL सेट करने पर secret ऑटो-जनरेट होता है। क्लियर करने के लिए खाली स्ट्रिंग भेजें। URL HTTPS होना चाहिए।
Request Body
| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
webhook_url | string | नहीं | Webhook इवेंट प्राप्त करने के लिए HTTPS URL (क्लियर करने के लिए खाली स्ट्रिंग) |
webhook_secret | string | नहीं | 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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} v1 के समान — केवल बेस पाथ बदलता है (/v1 → /v2)।
/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()एग्ज़ांपल रिस्पॉन्स
{
"success": true,
"data": {
"status_code": 200
}
} v1 के समान — केवल बेस पाथ बदलता है (/v1 → /v2)।
⟩Webhook नोटिफ़िकेशन
पोलिंग के बजाय ऑर्डर इवेंट्स के लिए रियल-टाइम पुश नोटिफ़िकेशन प्राप्त करने हेतु webhook URL कॉन्फ़िगर करें। बॉट स्क्रिप्ट्स के लिए यह रेकमेंडेड तरीक़ा है।
इवेंट्स
| इवेंट | ट्रिगर |
|---|---|
order.otp_received | रेंटेड नंबर पर OTP कोड डिलीवर हुआ |
order.completed | ऑर्डर कम्प्लीट मार्क हुआ (मैन्युअली या एक्सपायरी द्वारा) |
order.expired | ऑर्डर बिना OTP के एक्सपायर हुआ (बैलेंस रिफंड) |
order.canceled | यूज़र द्वारा ऑर्डर कैंसल (बैलेंस रिफंड) |
Payload
{
"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 के रूप में उपयोग करते हुए:
रिक्वेस्ट ऑथेंटिक है यह सुनिश्चित करने के लिए अपने सर्वर पर इस सिग्नेचर को वेरिफाई करें। डिलीवरी फ़ायर-एंड-फ़ॉरगेट है जिसमें 3-सेकंड टाइमआउट और कोई रिट्राई नहीं।
⟩Rate Limits
API रिक्वेस्ट प्रति endpoint ग्रुप rate-limited हैं। लिमिट पार करने पर 429 Too Many Requests रिस्पॉन्स मिलता है जिसमें Retry-After हेडर बताता है कितने सेकंड इंतज़ार करना है।
| Endpoint ग्रुप | लिमिट | विंडो |
|---|---|---|
| Catalog (countries, services, products, exchange-rate) | 5,000 रिक्वेस्ट | 60 सेकंड |
| Balance | 600 रिक्वेस्ट | 60 सेकंड |
| Order reads (list, get, active) | 5,000 रिक्वेस्ट | 60 सेकंड |
| Order create | 3,000 रिक्वेस्ट | 60 सेकंड |
| Order cancel | 1,000 रिक्वेस्ट | 60 सेकंड |
| Order actions (finish, resend) | 1,000 रिक्वेस्ट | 60 सेकंड |
| Webhook config (get, update) | 600 रिक्वेस्ट | 60 सेकंड |
| Webhook test | 10 रिक्वेस्ट | 60 सेकंड |
⟩एरर कोड
एरर रिस्पॉन्स में error.code में इनमें से एक कोड शामिल होता है:
| कोड | HTTP | विवरण |
|---|---|---|
UNAUTHORIZED | 401 | API token गायब या अमान्य |
FORBIDDEN | 403 | एक्सेस अस्वीकृत |
NOT_FOUND | 404 | रिसोर्स नहीं मिला (ऑर्डर, एक्सचेंज रेट, आदि) |
CONFLICT | 409 | डुप्लिकेट रिक्वेस्ट या रिसोर्स कॉन्फ़्लिक्ट |
INSUFFICIENT_BALANCE | 409 | ऑर्डर बनाने के लिए पर्याप्त बैलेंस नहीं |
VALIDATION_ERROR | 422 | रिक्वेस्ट पैरामीटर्स वैलिडेशन में फ़ेल |
RATE_LIMIT_EXCEEDED | 429 | बहुत ज़्यादा रिक्वेस्ट (Retry-After हेडर देखें) |
INTERNAL_ERROR | 500 | इंटरनल सर्वर एरर |
PROVIDER_ERROR | 422 | अपस्ट्रीम 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_AVAILABLE | 422 | अनुरोधित प्रोडक्ट और नीति (मूल्य सीमा, उपलब्धता) से मेल खाता कोई सक्रिय ऑफ़र नहीं है। |
CANCEL_TOO_EARLY | 409 | ऑर्डर कैंसल करने के लिए बहुत नया — 2 मिनट इंतज़ार करें |
REQUEST_IN_PROGRESS | 409 | इस idempotency key के साथ एक क्रिएट रिक्वेस्ट अभी भी चल रहा है |
IDEMPOTENCY_KEY_REUSED | 422 | यह idempotency key पहले से किसी अलग रिक्वेस्ट body के साथ इस्तेमाल हो चुकी है |
SERVICE_UNAVAILABLE | 503 | सर्विस अस्थायी रूप से अनुपलब्ध (मेंटेनेंस) |
FX_RATE_UNAVAILABLE | 503 | USD/IDR एक्सचेंज रेट अनुपलब्ध (v2 मनी एंडपॉइंट) — Retry-After हेडर के साथ 503 लौटाता है। |
⟩v1 से v2 में माइग्रेशन
v1 IDR देता है; v2 USD देता है। दोनों वर्शन स्थायी रूप से साथ-साथ रहते हैं — कोई सनसेट नहीं है। प्रति इंटीग्रेशन एक वर्शन चुनें; बेस पाथ मिक्स न करें। मनी कैसे दर्शाई जाती है, इसके अलावा v2 v1 के समान है।
| पहलू | v1 · IDR | v2 · USD |
|---|---|---|
| मनी फ़ील्ड | पूर्णांक IDR, जैसे 15000 | मनी ऑब्जेक्ट { amount, currency, canonical_amount, canonical_currency } |
meta.fx | अनुपस्थित | हर मनी-बेयरिंग रिस्पॉन्स पर आवश्यक |
| करेंसी | IDR | USD (हार्डकोडेड) |
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) |
साथ-साथ उदाहरण
{
"success": true,
"data": {
"currency": "IDR",
"balance": 500000
}
}{
"success": true,
"data": {
"balance": { "amount": "30.77", "currency": "USD", "canonical_amount": 500000, "canonical_currency": "IDR" }
},
"meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}{
"success": true,
"data": [
{
"id": 142,
"name": "WhatsApp Indonesia",
"country_id": 6,
"platform_id": 3,
"catalog_product_id": 87,
"available": 42,
"price": 15000,
"active": true
}
],
"meta": { "page": 1, "limit": 10, "count": 1 }
}{
"success": true,
"data": [
{
"id": 142,
"name": "WhatsApp Indonesia",
"country_id": 6,
"platform_id": 3,
"catalog_product_id": 87,
"available": 42,
"price": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
"active": true
}
],
"meta": { "page": 1, "limit": 10, "count": 1, "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}catalog_product_id स्थिर प्रोडक्ट पहचान है (हर देश + प्लेटफ़ॉर्म के लिए एक) — इसे अपने सिस्टम में स्टोर करना सुरक्षित है और इससे सीधे ऑर्डर भी किया जा सकता है: catalog_product_id (और वैकल्पिक max_price व prefer_provider) के साथ ऑर्डर करें और सर्वर आपके लिए लाइव ऑफ़र चुन लेगा। प्रति-ऑफ़र product_id वाला रास्ता अब भी समर्थित और बैकवर्ड-कम्पैटिबल है — वह id अस्थिर है और जब भी प्रोवाइडर का प्राइस टियर बदलता है यह बदल जाती है, इसलिए ऑर्डर से पहले कैटलॉग दोबारा फ़ेच करने की सलाह केवल उसी रास्ते पर लागू होती है।
{
"success": true,
"data": {
"order_id": 1001,
"status": "CANCELED",
"refund_amount": 15000,
"new_balance": 515000
}
}{
"success": true,
"data": {
"order_id": 1001,
"status": "CANCELED",
"refund_amount": { "amount": "0.9231", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" },
"new_balance": { "amount": "31.69", "currency": "USD", "canonical_amount": 515000, "canonical_currency": "IDR" }
},
"meta": { "fx": { "pair": "USD/IDR", "rate": 16250, "rate_as_of": "2026-05-27T08:00:00+00:00" } }
}माइग्रेशन चेकलिस्ट
- बेस पाथ
/v1→/v2बदलें। - मनी फ़ील्ड को ऑब्जेक्ट के रूप में पार्स करें —
amountको दशमलव स्ट्रिंग के रूप में पढ़ें;currency"USD"है। - लेजर रिकंसिलिएशन के लिए
canonical_amount(सटीक IDR) का उपयोग करें; USDamountएक रेंडर-टाइम प्रोजेक्शन है औरratemeta.fxमें एक बार दर्शाया जाता है। - नए
FX_RATE_UNAVAILABLE(503) को हैंडल करें —Retry-Afterके बाद फिर कोशिश करें। v1 यह कभी नहीं लौटाता।